Revision 852d481f target-sh4/translate.c

b/target-sh4/translate.c
50 50
    uint32_t delayed_pc;
51 51
    int singlestep_enabled;
52 52
    uint32_t features;
53
    int has_movcal;
53 54
} DisasContext;
54 55

  
55 56
#if defined(CONFIG_USER_ONLY)
......
283 284
    env = qemu_mallocz(sizeof(CPUSH4State));
284 285
    env->features = def->features;
285 286
    cpu_exec_init(env);
287
    env->movcal_backup_tail = &(env->movcal_backup);
286 288
    sh4_translate_init();
287 289
    env->cpu_model_str = cpu_model;
288 290
    cpu_sh4_reset(env);
......
495 497

  
496 498
static void _decode_opc(DisasContext * ctx)
497 499
{
500
    /* This code tries to make movcal emulation sufficiently
501
       accurate for Linux purposes.  This instruction writes
502
       memory, and prior to that, always allocates a cache line.
503
       It is used in two contexts:
504
       - in memcpy, where data is copied in blocks, the first write
505
       of to a block uses movca.l for performance.
506
       - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
507
       to flush the cache. Here, the data written by movcal.l is never
508
       written to memory, and the data written is just bogus.
509

  
510
       To simulate this, we simulate movcal.l, we store the value to memory,
511
       but we also remember the previous content. If we see ocbi, we check
512
       if movcal.l for that address was done previously. If so, the write should
513
       not have hit the memory, so we restore the previous content.
514
       When we see an instruction that is neither movca.l
515
       nor ocbi, the previous content is discarded.
516

  
517
       To optimize, we only try to flush stores when we're at the start of
518
       TB, or if we already saw movca.l in this TB and did not flush stores
519
       yet.  */
520
    if (ctx->has_movcal)
521
	{
522
	  int opcode = ctx->opcode & 0xf0ff;
523
	  if (opcode != 0x0093 /* ocbi */
524
	      && opcode != 0x00c3 /* movca.l */)
525
	      {
526
		  gen_helper_discard_movcal_backup ();
527
		  ctx->has_movcal = 0;
528
	      }
529
	}
530

  
498 531
#if 0
499 532
    fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
500 533
#endif
......
1545 1578
	}
1546 1579
	return;
1547 1580
    case 0x00c3:		/* movca.l R0,@Rm */
1548
	tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
1581
        {
1582
            TCGv val = tcg_temp_new();
1583
            tcg_gen_qemu_ld32u(val, REG(B11_8), ctx->memidx);
1584
            gen_helper_movcal (REG(B11_8), val);            
1585
            tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
1586
        }
1587
        ctx->has_movcal = 1;
1549 1588
	return;
1550 1589
    case 0x40a9:
1551 1590
	/* MOVUA.L @Rm,R0 (Rm) -> R0
......
1594 1633
	    break;
1595 1634
    case 0x0093:		/* ocbi @Rn */
1596 1635
	{
1597
	    TCGv dummy = tcg_temp_new();
1598
	    tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1599
	    tcg_temp_free(dummy);
1636
	    gen_helper_ocbi (REG(B11_8));
1600 1637
	}
1601 1638
	return;
1602 1639
    case 0x00a3:		/* ocbp @Rn */
......
1876 1913
    ctx.tb = tb;
1877 1914
    ctx.singlestep_enabled = env->singlestep_enabled;
1878 1915
    ctx.features = env->features;
1916
    ctx.has_movcal = (tb->flags & TB_FLAG_PENDING_MOVCA);
1879 1917

  
1880 1918
#ifdef DEBUG_DISAS
1881 1919
    qemu_log_mask(CPU_LOG_TB_CPU,

Also available in: Unified diff