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; | ... | ... |