Commit 34ae7b51f54a5d58d30e31a92f8ece02973de50b

Authored by ths
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
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;
... ...