Commit 34ae7b51f54a5d58d30e31a92f8ece02973de50b
1 parent
f96f4c9d
Work around the lack of proper handling for self-modifying code.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2827 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
30 additions
and
2 deletions
target-mips/op.c
... | ... | @@ -1001,6 +1001,16 @@ void op_jnz_T2 (void) |
1001 | 1001 | RETURN(); |
1002 | 1002 | } |
1003 | 1003 | |
1004 | +void op_flush_icache_range(void) { | |
1005 | + CALL_FROM_TB2(tlb_flush_page, env, T0 + T1); | |
1006 | + RETURN(); | |
1007 | +} | |
1008 | + | |
1009 | +void op_flush_icache_all(void) { | |
1010 | + CALL_FROM_TB1(tb_flush, env); | |
1011 | + RETURN(); | |
1012 | +} | |
1013 | + | |
1004 | 1014 | /* CP0 functions */ |
1005 | 1015 | void op_mfc0_index (void) |
1006 | 1016 | { | ... | ... |
target-mips/translate.c
... | ... | @@ -5648,8 +5648,26 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5648 | 5648 | gen_ldst(ctx, op, rt, rs, imm); |
5649 | 5649 | break; |
5650 | 5650 | case OPC_CACHE: |
5651 | - /* Treat as a noop */ | |
5652 | - break; | |
5651 | + /* FIXME: This works around self-modifying code, but only | |
5652 | + if the guest OS handles it properly, and if there's no | |
5653 | + such code executed in uncached space. */ | |
5654 | + if (!(rt & 0x3)) | |
5655 | + switch ((rt >> 2) & 0x7) { | |
5656 | + case 4: | |
5657 | + GEN_LOAD_REG_TN(T0, rs); | |
5658 | + GEN_LOAD_IMM_TN(T1, imm); | |
5659 | + gen_op_flush_icache_range(); | |
5660 | + break; | |
5661 | + case 2: | |
5662 | + case 1: | |
5663 | + case 0: | |
5664 | + /* Can be very inefficient. */ | |
5665 | + gen_op_flush_icache_all(); | |
5666 | + break; | |
5667 | + default: | |
5668 | + break; | |
5669 | + } | |
5670 | + break; | |
5653 | 5671 | case OPC_PREF: |
5654 | 5672 | /* Treat as a noop */ |
5655 | 5673 | break; | ... | ... |