-------- Forwarded Message -------- > From: Jocelyn Mayer <[EMAIL PROTECTED]> > Reply-To: [EMAIL PROTECTED], qemu-devel@nongnu.org > To: qemu-devel@nongnu.org > Subject: Re: [Qemu-devel] RFC: Code fetch optimisation > Date: Fri, 12 Oct 2007 20:24:44 +0200 > > On Fri, 2007-10-12 at 18:21 +0300, Blue Swirl wrote: > > On 10/12/07, J. Mayer <[EMAIL PROTECTED]> wrote: > > > Here's a small patch that allow an optimisation for code fetch, at least > > > for RISC CPU targets, as suggested by Fabrice Bellard. > > > The main idea is that a translated block is never to span over a page > > > boundary. As the tb_find_slow routine already gets the physical address > > > of the page of code to be translated, the code translator could then > > > fetch the code using raw host memory accesses instead of doing it > > > through the softmmu routines. > > > This patch could also be adapted to RISC CPU targets, with care for the > > > last instruction of a page. For now, I did implement it for alpha, arm, > > > mips, PowerPC and SH4. > > > I don't actually know if the optimsation would bring a sensible speed > > > gain or if it will be absolutelly marginal. > > > > > > Please comment. > > > > This will not work correctly for execution of MMIO registers, but > > maybe that won't work on real hardware either. Who cares. > > I wonder if this is important or not... But maybe, when retrieving the > physical address we could check if it is inside ROM/RAM or an I/O area > and in the last case do not give the phys_addr information to the > translator. In that case, it would go on using the ldxx_code. I guess if > we want to do that, a set of helpers would be appreciated to avoid > adding code like: > if (phys_pc == 0) > opc = ldul_code(virt_pc) > else > opc = ldul_raw(phys_pc) > everywhere... I could also add another check so this set of macro would > automatically use ldxx_code if we reach a page boundary, which would > then make easy to use this optimisation for CISC/VLE architectures too. > > I'm not sure of the proper solution to allow executing code from mmio > devices. But adding specific accessors to handle the CISC/VLE case is to > be done.
[...] I did update my patch following this way and it's now able to run x86 and PowerPC targets. PowerPC is the easy case, x86 is maybe the worst... Well, I'm not really sure of what I've done for Sparc, but other targets should be safe. Please comment. -- J. Mayer <[EMAIL PROTECTED]> Never organized
Index: cpu-all.h =================================================================== RCS file: /sources/qemu/qemu/cpu-all.h,v retrieving revision 1.76 diff -u -d -d -p -r1.76 cpu-all.h --- cpu-all.h 23 Sep 2007 15:28:03 -0000 1.76 +++ cpu-all.h 12 Oct 2007 22:53:37 -0000 @@ -646,6 +646,13 @@ static inline void stfq_be_p(void *ptr, #define ldl_code(p) ldl_raw(p) #define ldq_code(p) ldq_raw(p) +#define ldub_code_p(sp, pp, p) ldub_raw(p) +#define ldsb_code_p(sp, pp, p) ldsb_raw(p) +#define lduw_code_p(sp, pp, p) lduw_raw(p) +#define ldsw_code_p(sp, pp, p) ldsw_raw(p) +#define ldl_code_p(sp, pp, p) ldl_raw(p) +#define ldq_code_p(sp, pp, p) ldq_raw(p) + #define ldub_kernel(p) ldub_raw(p) #define ldsb_kernel(p) ldsb_raw(p) #define lduw_kernel(p) lduw_raw(p) Index: cpu-exec.c =================================================================== RCS file: /sources/qemu/qemu/cpu-exec.c,v retrieving revision 1.119 diff -u -d -d -p -r1.119 cpu-exec.c --- cpu-exec.c 8 Oct 2007 13:16:13 -0000 1.119 +++ cpu-exec.c 12 Oct 2007 22:53:37 -0000 @@ -133,6 +133,7 @@ static TranslationBlock *tb_find_slow(ta tb->tc_ptr = tc_ptr; tb->cs_base = cs_base; tb->flags = flags; + tb->page_addr[0] = phys_page1; cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); Index: softmmu_header.h =================================================================== RCS file: /sources/qemu/qemu/softmmu_header.h,v retrieving revision 1.17 diff -u -d -d -p -r1.17 softmmu_header.h --- softmmu_header.h 8 Oct 2007 13:16:14 -0000 1.17 +++ softmmu_header.h 12 Oct 2007 22:53:37 -0000 @@ -336,6 +336,60 @@ static inline void glue(glue(st, SUFFIX) } } +#else + +#if DATA_SIZE <= 2 +static inline RES_TYPE glue(glue(glue(lds,SUFFIX),MEMSUFFIX),_p)(unsigned long *start_pc, + unsigned long phys_pc, + target_ulong virt_pc) +{ + RES_TYPE opc; + + if (unlikely((*start_pc ^ + (phys_pc + sizeof(RES_TYPE) - 1)) >> TARGET_PAGE_BITS)) { + /* Slow path: phys_pc is not in the same page than start_pc + * or the insn is spanning two pages + */ + opc = glue(glue(lds,SUFFIX),MEMSUFFIX)(virt_pc); + /* Avoid softmmu access on next load */ + /* XXX: dont: phys PC is not correct anymore + * We chould call get_phys_addr_code(env, pc); and remove the else + * condition, here. + */ + //*start_pc = phys_pc; + } else { + opc = glue(glue(lds,SUFFIX),_raw)(phys_pc); + } + + return opc; +} +#endif + +static inline RES_TYPE glue(glue(glue(ld,USUFFIX),MEMSUFFIX),_p)(unsigned long *start_pc, + unsigned long phys_pc, + target_ulong virt_pc) +{ + RES_TYPE opc; + + if (unlikely((*start_pc ^ + (phys_pc + sizeof(RES_TYPE) - 1)) >> TARGET_PAGE_BITS)) { + /* Slow path: phys_pc is not in the same page than start_pc + * or the insn is spanning two pages + */ + opc = glue(glue(ld,USUFFIX),MEMSUFFIX)(virt_pc); + /* Avoid softmmu access on next load */ + /* XXX: dont: phys PC is not correct anymore + * We chould call get_phys_addr_code(env, pc); and remove the else + * condition, here. + */ + //*start_pc = phys_pc; + } else { + opc = glue(glue(ld,USUFFIX),_raw)(phys_pc); + } + + return opc; +} + #endif /* ACCESS_TYPE != 3 */ #endif /* !asm */ Index: target-alpha/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-alpha/translate.c,v retrieving revision 1.5 diff -u -d -d -p -r1.5 translate.c --- target-alpha/translate.c 16 Sep 2007 21:08:01 -0000 1.5 +++ target-alpha/translate.c 12 Oct 2007 22:53:38 -0000 @@ -1965,6 +1965,7 @@ int gen_intermediate_code_internal (CPUS static int insn_count; #endif DisasContext ctx, *ctxp = &ctx; + unsigned long phys_pc, phys_pc_start; target_ulong pc_start; uint32_t insn; uint16_t *gen_opc_end; @@ -1972,6 +1973,9 @@ int gen_intermediate_code_internal (CPUS int ret; pc_start = tb->pc; + phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + phys_pc = phys_pc_start; gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; @@ -2010,7 +2014,7 @@ int gen_intermediate_code_internal (CPUS ctx.pc, ctx.mem_idx); } #endif - insn = ldl_code(ctx.pc); + insn = ldl_code_p(&phys_pc_start, phys_pc, ctx.pc); #if defined ALPHA_DEBUG_DISAS insn_count++; if (logfile != NULL) { @@ -2018,6 +2022,7 @@ int gen_intermediate_code_internal (CPUS } #endif ctx.pc += 4; + phys_pc += 4; ret = translate_one(ctxp, insn); if (ret != 0) break; Index: target-arm/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-arm/translate.c,v retrieving revision 1.57 diff -u -d -d -p -r1.57 translate.c --- target-arm/translate.c 17 Sep 2007 08:09:51 -0000 1.57 +++ target-arm/translate.c 12 Oct 2007 22:53:38 -0000 @@ -38,6 +38,8 @@ /* internal defines */ typedef struct DisasContext { target_ulong pc; + unsigned long phys_pc; + unsigned long phys_pc_start; int is_jmp; /* Nonzero if this instruction has been conditionally skipped. */ int condjmp; @@ -2206,8 +2208,9 @@ static void disas_arm_insn(CPUState * en { unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; - insn = ldl_code(s->pc); + insn = ldl_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 4; + s->phys_pc += 4; cond = insn >> 28; if (cond == 0xf){ @@ -2971,8 +2974,9 @@ static void disas_thumb_insn(DisasContex int32_t offset; int i; - insn = lduw_code(s->pc); + insn = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; switch (insn >> 12) { case 0: case 1: @@ -3494,7 +3498,7 @@ static void disas_thumb_insn(DisasContex break; } offset = ((int32_t)insn << 21) >> 10; - insn = lduw_code(s->pc); + insn = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); offset |= insn & 0x7ff; val = (uint32_t)s->pc + 2; @@ -3544,6 +3548,9 @@ static inline int gen_intermediate_code_ dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; + dc->phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + dc->phys_pc = dc->phys_pc_start; dc->singlestep_enabled = env->singlestep_enabled; dc->condjmp = 0; dc->thumb = env->thumb; Index: target-cris/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-cris/translate.c,v retrieving revision 1.1 diff -u -d -d -p -r1.1 translate.c --- target-cris/translate.c 8 Oct 2007 12:49:08 -0000 1.1 +++ target-cris/translate.c 12 Oct 2007 22:53:38 -0000 @@ -100,6 +100,7 @@ enum { typedef struct DisasContext { CPUState *env; target_ulong pc, insn_pc; + unsigned long phys_pc, phys_pc_start; /* Decoder. */ uint32_t ir; @@ -828,7 +829,8 @@ static int dec_prep_alu_m(DisasContext * if (memsize == 1) insn_len++; - imm = ldl_code(dc->pc + 2); + imm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, + dc->pc + 2); if (memsize != 4) { if (s_ext) { imm = sign_extend(imm, (memsize * 8) - 1); @@ -1962,7 +1964,7 @@ static unsigned int dec_lapc_im(DisasCon rd = dc->op2; cris_cc_mask(dc, 0); - imm = ldl_code(dc->pc + 2); + imm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2)); gen_op_movl_T0_im (dc->pc + imm); gen_movl_reg_T0[rd] (); @@ -1999,7 +2001,7 @@ static unsigned int dec_jas_im(DisasCont { uint32_t imm; - imm = ldl_code(dc->pc + 2); + imm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); DIS(fprintf (logfile, "jas 0x%x\n", imm)); cris_cc_mask(dc, 0); @@ -2016,7 +2018,7 @@ static unsigned int dec_jasc_im(DisasCon { uint32_t imm; - imm = ldl_code(dc->pc + 2); + imm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); DIS(fprintf (logfile, "jasc 0x%x\n", imm)); cris_cc_mask(dc, 0); @@ -2047,7 +2049,7 @@ static unsigned int dec_bcc_im(DisasCont int32_t offset; uint32_t cond = dc->op2; - offset = ldl_code(dc->pc + 2); + offset = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); offset = sign_extend(offset, 15); DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n", @@ -2065,7 +2067,7 @@ static unsigned int dec_bas_im(DisasCont int32_t simm; - simm = ldl_code(dc->pc + 2); + simm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); cris_cc_mask(dc, 0); @@ -2081,7 +2083,7 @@ static unsigned int dec_bas_im(DisasCont static unsigned int dec_basc_im(DisasContext *dc) { int32_t simm; - simm = ldl_code(dc->pc + 2); + simm = ldl_code_p(&dc->phys_pc_start, dc->phys_pc + 2, dc->pc + 2); DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); cris_cc_mask(dc, 0); @@ -2259,7 +2261,7 @@ cris_decoder(DisasContext *dc) int i; /* Load a halfword onto the instruction register. */ - tmp = ldl_code(dc->pc); + tmp = ldl_code_p(&dc->phys_pc_start, dc->phys_pc, dc->pc); dc->ir = tmp & 0xffff; /* Now decode it. */ @@ -2313,6 +2315,9 @@ gen_intermediate_code_internal(CPUState uint32_t next_page_start; pc_start = tb->pc; + dc->phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + dc->phys_pc = dc->phys_pc_start; dc->env = env; dc->tb = tb; @@ -2347,6 +2352,7 @@ gen_intermediate_code_internal(CPUState insn_len = cris_decoder(dc); STATS(gen_op_exec_insn()); dc->pc += insn_len; + dc->phys_pc += insn_len; if (!dc->flagx_live || (dc->flagx_live && !(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) { Index: target-i386/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-i386/translate.c,v retrieving revision 1.72 diff -u -d -d -p -r1.72 translate.c --- target-i386/translate.c 27 Sep 2007 01:52:00 -0000 1.72 +++ target-i386/translate.c 12 Oct 2007 22:53:39 -0000 @@ -73,6 +73,7 @@ typedef struct DisasContext { int prefix; int aflag, dflag; target_ulong pc; /* pc = eip + cs_base */ + unsigned long phys_pc,phys_pc_start; int is_jmp; /* 1 = means jump (stop translation), 2 means CPU static state change (stop translation) */ /* current block context */ @@ -1451,7 +1452,7 @@ static void gen_lea_modrm(DisasContext * if (base == 4) { havesib = 1; - code = ldub_code(s->pc++); + code = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); scale = (code >> 6) & 3; index = ((code >> 3) & 7) | REX_X(s); base = (code & 7); @@ -1462,8 +1463,10 @@ static void gen_lea_modrm(DisasContext * case 0: if ((base & 7) == 5) { base = -1; - disp = (int32_t)ldl_code(s->pc); + disp = (int32_t)ldl_code_p(&s->phys_pc_start, s->phys_pc, + s->pc); s->pc += 4; + s->phys_pc += 4; if (CODE64(s) && !havesib) { disp += s->pc + s->rip_offset; } @@ -1472,12 +1475,14 @@ static void gen_lea_modrm(DisasContext * } break; case 1: - disp = (int8_t)ldub_code(s->pc++); + disp = (int8_t)ldub_code_p(&s->phys_pc_start, s->phys_pc++, + s->pc++); break; default: case 2: - disp = ldl_code(s->pc); + disp = ldl_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 4; + s->phys_pc += 4; break; } @@ -1545,8 +1550,9 @@ static void gen_lea_modrm(DisasContext * switch (mod) { case 0: if (rm == 6) { - disp = lduw_code(s->pc); + disp = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; gen_op_movl_A0_im(disp); rm = 0; /* avoid SS override */ goto no_rm; @@ -1555,12 +1561,14 @@ static void gen_lea_modrm(DisasContext * } break; case 1: - disp = (int8_t)ldub_code(s->pc++); + disp = (int8_t)ldub_code_p(&s->phys_pc_start, s->phys_pc++, + s->pc++); break; default: case 2: - disp = lduw_code(s->pc); + disp = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; break; } switch(rm) { @@ -1629,7 +1637,7 @@ static void gen_nop_modrm(DisasContext * base = rm; if (base == 4) { - code = ldub_code(s->pc++); + code = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); base = (code & 7); } @@ -1637,14 +1645,17 @@ static void gen_nop_modrm(DisasContext * case 0: if (base == 5) { s->pc += 4; + s->phys_pc += 4; } break; case 1: s->pc++; + s->phys_pc++; break; default: case 2: s->pc += 4; + s->phys_pc += 4; break; } } else { @@ -1652,14 +1663,17 @@ static void gen_nop_modrm(DisasContext * case 0: if (rm == 6) { s->pc += 2; + s->phys_pc += 2; } break; case 1: s->pc++; + s->phys_pc++; break; default: case 2: s->pc += 2; + s->phys_pc += 2; break; } } @@ -1727,17 +1741,20 @@ static inline uint32_t insn_get(DisasCon switch(ot) { case OT_BYTE: - ret = ldub_code(s->pc); + ret = ldub_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc++; + s->phys_pc++; break; case OT_WORD: - ret = lduw_code(s->pc); + ret = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; break; default: case OT_LONG: - ret = ldl_code(s->pc); + ret = ldl_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 4; + s->phys_pc += 4; break; } return ret; @@ -2689,7 +2706,7 @@ static void gen_sse(DisasContext *s, int gen_op_enter_mmx(); } - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7); if (is_xmm) reg |= rex_r; @@ -2962,7 +2979,7 @@ static void gen_sse(DisasContext *s, int case 0x171: /* shift xmm, im */ case 0x172: case 0x173: - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (is_xmm) { gen_op_movl_T0_im(val); gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0))); @@ -3082,7 +3099,7 @@ static void gen_sse(DisasContext *s, int case 0x1c4: s->rip_offset = 1; gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (b1) { val &= 7; gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val); @@ -3095,7 +3112,7 @@ static void gen_sse(DisasContext *s, int case 0x1c5: if (mod != 3) goto illegal_op; - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (b1) { val &= 7; rm = (modrm & 7) | REX_B(s); @@ -3213,13 +3230,13 @@ static void gen_sse(DisasContext *s, int switch(b) { case 0x70: /* pshufx insn */ case 0xc6: /* pshufx insn */ - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); sse_op3 = (GenOpFunc3 *)sse_op2; sse_op3(op1_offset, op2_offset, val); break; case 0xc2: /* compare insns */ - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (val >= 8) goto illegal_op; sse_op2 = sse_op_table4[val][b1]; @@ -3260,8 +3277,9 @@ static target_ulong disas_insn(DisasCont #endif s->rip_offset = 0; /* for relative ip address */ next_byte: - b = ldub_code(s->pc); + b = ldub_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc++; + s->phys_pc++; /* check prefixes */ #ifdef TARGET_X86_64 if (CODE64(s)) { @@ -3375,7 +3393,7 @@ static target_ulong disas_insn(DisasCont case 0x0f: /**************************/ /* extended op code */ - b = ldub_code(s->pc++) | 0x100; + b = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++) | 0x100; goto reswitch; /**************************/ @@ -3400,7 +3418,7 @@ static target_ulong disas_insn(DisasCont switch(f) { case 0: /* OP Ev, Gv */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -3422,7 +3440,7 @@ static target_ulong disas_insn(DisasCont gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; reg = ((modrm >> 3) & 7) | rex_r; rm = (modrm & 7) | REX_B(s); @@ -3457,7 +3475,7 @@ static target_ulong disas_insn(DisasCont else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -3506,7 +3524,7 @@ static target_ulong disas_insn(DisasCont else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -3648,7 +3666,7 @@ static target_ulong disas_insn(DisasCont else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -3754,7 +3772,7 @@ static target_ulong disas_insn(DisasCont else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); reg = ((modrm >> 3) & 7) | rex_r; @@ -3805,7 +3823,7 @@ static target_ulong disas_insn(DisasCont case 0x69: /* imul Gv, Ev, I */ case 0x6b: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; if (b == 0x69) s->rip_offset = insn_const_size(ot); @@ -3841,7 +3859,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) { @@ -3868,7 +3886,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; gen_op_mov_TN_reg[ot][1][reg](); @@ -3885,7 +3903,7 @@ static target_ulong disas_insn(DisasCont s->cc_op = CC_OP_SUBB + ot; break; case 0x1c7: /* cmpxchg8b */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -3944,7 +3962,7 @@ static target_ulong disas_insn(DisasCont } else { ot = dflag + OT_WORD; } - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; gen_pop_T0(s); if (mod == 3) { @@ -3963,9 +3981,10 @@ static target_ulong disas_insn(DisasCont case 0xc8: /* enter */ { int level; - val = lduw_code(s->pc); + val = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; - level = ldub_code(s->pc++); + s->phys_pc += 2; + level = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_enter(s, val, level); } break; @@ -4045,7 +4064,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; /* generate a generic store */ @@ -4057,7 +4076,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; if (mod != 3) { s->rip_offset = insn_const_size(ot); @@ -4076,14 +4095,14 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = OT_WORD + dflag; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_reg_T0[ot][reg](); break; case 0x8e: /* mov seg, Gv */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = (modrm >> 3) & 7; if (reg >= 6 || reg == R_CS) goto illegal_op; @@ -4103,7 +4122,7 @@ static target_ulong disas_insn(DisasCont } break; case 0x8c: /* mov Gv, seg */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (reg >= 6) @@ -4126,7 +4145,7 @@ static target_ulong disas_insn(DisasCont d_ot = dflag + OT_WORD; /* ot is the size of source */ ot = (b & 1) + OT_BYTE; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -4163,7 +4182,7 @@ static target_ulong disas_insn(DisasCont case 0x8d: /* lea */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -4190,8 +4209,9 @@ static target_ulong disas_insn(DisasCont ot = dflag + OT_WORD; #ifdef TARGET_X86_64 if (s->aflag == 2) { - offset_addr = ldq_code(s->pc); + offset_addr = ldq_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 8; + s->phys_pc += 8; if (offset_addr == (int32_t)offset_addr) gen_op_movq_A0_im(offset_addr); else @@ -4243,8 +4263,9 @@ static target_ulong disas_insn(DisasCont if (dflag == 2) { uint64_t tmp; /* 64 bit case */ - tmp = ldq_code(s->pc); + tmp = ldq_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 8; + s->phys_pc += 8; reg = (b & 7) | REX_B(s); gen_movtl_T0_im(tmp); gen_op_mov_reg_T0[OT_QUAD][reg](); @@ -4270,7 +4291,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) { @@ -4313,7 +4334,7 @@ static target_ulong disas_insn(DisasCont op = R_GS; do_lxx: ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) @@ -4345,7 +4366,7 @@ static target_ulong disas_insn(DisasCont else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; @@ -4364,7 +4385,8 @@ static target_ulong disas_insn(DisasCont gen_shift(s, op, ot, opreg, OR_ECX); } else { if (shift == 2) { - shift = ldub_code(s->pc++); + shift = ldub_code_p(&s->phys_pc_start, s->phys_pc++, + s->pc++); } gen_shifti(s, op, ot, opreg, shift); } @@ -4398,7 +4420,7 @@ static target_ulong disas_insn(DisasCont shift = 0; do_shiftd: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); reg = ((modrm >> 3) & 7) | rex_r; @@ -4412,7 +4434,7 @@ static target_ulong disas_insn(DisasCont gen_op_mov_TN_reg[ot][1][reg](); if (shift) { - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (ot == OT_QUAD) val &= 0x3f; else @@ -4450,7 +4472,7 @@ static target_ulong disas_insn(DisasCont gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); break; } - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = ((b & 7) << 3) | ((modrm >> 3) & 7); @@ -5013,7 +5035,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, 0, pc_start - s->cs_base); if (gen_svm_check_io(s, pc_start, @@ -5029,7 +5051,7 @@ static target_ulong disas_insn(DisasCont ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, 0, pc_start - s->cs_base); if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) | @@ -5073,8 +5095,9 @@ static target_ulong disas_insn(DisasCont /************************/ /* control */ case 0xc2: /* ret im */ - val = ldsw_code(s->pc); + val = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; gen_pop_T0(s); if (CODE64(s) && s->dflag) s->dflag = 2; @@ -5093,8 +5116,9 @@ static target_ulong disas_insn(DisasCont gen_eob(s); break; case 0xca: /* lret im */ - val = ldsw_code(s->pc); + val = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; do_lret: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) @@ -5223,13 +5247,13 @@ static target_ulong disas_insn(DisasCont break; case 0x190 ... 0x19f: /* setcc Gv */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_setcc(s, b); gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); break; case 0x140 ... 0x14f: /* cmov Gv, Ev */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; gen_setcc(s, b); @@ -5338,7 +5362,7 @@ static target_ulong disas_insn(DisasCont /* bit operations */ case 0x1ba: /* bt/bts/btr/btc Gv, im */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); op = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -5350,7 +5374,7 @@ static target_ulong disas_insn(DisasCont gen_op_mov_TN_reg[ot][0][rm](); } /* load shift */ - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_op_movl_T1_im(val); if (op < 4) goto illegal_op; @@ -5378,7 +5402,7 @@ static target_ulong disas_insn(DisasCont op = 3; do_btx: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -5404,7 +5428,7 @@ static target_ulong disas_insn(DisasCont case 0x1bc: /* bsf */ case 0x1bd: /* bsr */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); /* NOTE: in order to handle the 0 case, we must load the @@ -5451,7 +5475,7 @@ static target_ulong disas_insn(DisasCont case 0xd4: /* aam */ if (CODE64(s)) goto illegal_op; - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (val == 0) { gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base); } else { @@ -5462,7 +5486,7 @@ static target_ulong disas_insn(DisasCont case 0xd5: /* aad */ if (CODE64(s)) goto illegal_op; - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_op_aad(val); s->cc_op = CC_OP_LOGICB; break; @@ -5494,7 +5518,7 @@ static target_ulong disas_insn(DisasCont gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); break; case 0xcd: /* int N */ - val = ldub_code(s->pc++); + val = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) break; if (s->vm86 && s->iopl != 3) { @@ -5567,7 +5591,7 @@ static target_ulong disas_insn(DisasCont if (CODE64(s)) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) @@ -5738,7 +5762,7 @@ static target_ulong disas_insn(DisasCont } break; case 0x100: - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -5808,7 +5832,7 @@ static target_ulong disas_insn(DisasCont } break; case 0x101: - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; rm = modrm & 7; @@ -6022,7 +6046,7 @@ static target_ulong disas_insn(DisasCont /* d_ot is the size of destination */ d_ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -6048,7 +6072,7 @@ static target_ulong disas_insn(DisasCont if (!s->pe || s->vm86) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = modrm & 7; @@ -6075,7 +6099,7 @@ static target_ulong disas_insn(DisasCont if (!s->pe || s->vm86) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_TN_reg[ot][1][reg](); @@ -6089,7 +6113,7 @@ static target_ulong disas_insn(DisasCont gen_op_mov_reg_T1[ot][reg](); break; case 0x118: - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -6108,7 +6132,7 @@ static target_ulong disas_insn(DisasCont } break; case 0x119 ... 0x11f: /* nop (multi byte) */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_nop_modrm(s, modrm); break; case 0x120: /* mov reg, crN */ @@ -6116,7 +6140,7 @@ static target_ulong disas_insn(DisasCont if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = (modrm & 7) | REX_B(s); @@ -6158,7 +6182,7 @@ static target_ulong disas_insn(DisasCont if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = (modrm & 7) | REX_B(s); @@ -6199,7 +6223,7 @@ static target_ulong disas_insn(DisasCont if (!(s->cpuid_features & CPUID_SSE2)) goto illegal_op; ot = s->dflag == 2 ? OT_QUAD : OT_LONG; - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -6208,7 +6232,7 @@ static target_ulong disas_insn(DisasCont gen_ldst_modrm(s, modrm, ot, reg, 1); break; case 0x1ae: - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -6274,7 +6298,7 @@ static target_ulong disas_insn(DisasCont } break; case 0x10d: /* prefetch */ - modrm = ldub_code(s->pc++); + modrm = ldub_code_p(&s->phys_pc_start, s->phys_pc++, s->pc++); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); /* ignore for now */ break; @@ -6752,6 +6776,9 @@ static inline int gen_intermediate_code_ dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; + dc->phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + dc->phys_pc = dc->phys_pc_start; lj = -1; for(;;) { Index: target-m68k/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-m68k/translate.c,v retrieving revision 1.20 diff -u -d -d -p -r1.20 translate.c --- target-m68k/translate.c 17 Sep 2007 08:09:53 -0000 1.20 +++ target-m68k/translate.c 12 Oct 2007 22:53:39 -0000 @@ -45,6 +45,8 @@ typedef struct DisasContext { CPUM68KState *env; target_ulong insn_pc; /* Start of the current instruction. */ target_ulong pc; + unsigned long phys_pc; + unsigned long phys_pc_start; int is_jmp; int cc_op; int user; @@ -207,10 +209,12 @@ static int gen_ldst(DisasContext *s, int static inline uint32_t read_im32(DisasContext *s) { uint32_t im; - im = ((uint32_t)lduw_code(s->pc)) << 16; + im = ((uint32_t)lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc)) << 16; s->pc += 2; - im |= lduw_code(s->pc); + s->phys_pc += 2; + im |= lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; return im; } @@ -244,8 +248,9 @@ static int gen_lea_indexed(DisasContext uint32_t bd, od; offset = s->pc; - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) return -1; @@ -258,8 +263,10 @@ static int gen_lea_indexed(DisasContext if ((ext & 0x30) > 0x10) { /* base displacement */ if ((ext & 0x30) == 0x20) { - bd = (int16_t)lduw_code(s->pc); + bd = (int16_t)lduw_code_p(&s->phys_pc_start, s->phys_pc, + s->pc); s->pc += 2; + s->phys_pc += 2; } else { bd = read_im32(s); } @@ -307,8 +314,10 @@ static int gen_lea_indexed(DisasContext if ((ext & 3) > 1) { /* outer displacement */ if ((ext & 3) == 2) { - od = (int16_t)lduw_code(s->pc); + od = (int16_t)lduw_code_p(&s->phys_pc_start, s->phys_pc, + s->pc); s->pc += 2; + s->phys_pc += 2; } else { od = read_im32(s); } @@ -455,8 +464,9 @@ static int gen_lea(DisasContext *s, uint case 5: /* Indirect displacement. */ reg += QREG_A0; tmp = gen_new_qreg(QMODE_I32); - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; gen_op_add32(tmp, reg, gen_im32((int16_t)ext)); return tmp; case 6: /* Indirect index + displacement. */ @@ -465,8 +475,9 @@ static int gen_lea(DisasContext *s, uint case 7: /* Other */ switch (reg) { case 0: /* Absolute short. */ - offset = ldsw_code(s->pc); + offset = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; return gen_im32(offset); case 1: /* Absolute long. */ offset = read_im32(s); @@ -474,8 +485,9 @@ static int gen_lea(DisasContext *s, uint case 2: /* pc displacement */ tmp = gen_new_qreg(QMODE_I32); offset = s->pc; - offset += ldsw_code(s->pc); + offset += ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; return gen_im32(offset); case 3: /* pc index+displacement. */ return gen_lea_indexed(s, opsize, -1); @@ -581,18 +593,23 @@ static int gen_ea(DisasContext *s, uint1 /* Sign extend values for consistency. */ switch (opsize) { case OS_BYTE: - if (val) - offset = ldsb_code(s->pc + 1); - else - offset = ldub_code(s->pc + 1); + if (val) { + offset = ldsb_code_p(&s->phys_pc_start, s->phys_pc + 1, + s->pc + 1); + } else { + offset = ldub_code_p(&s->phys_pc_start, s->phys_pc + 1, + s->pc + 1); + } s->pc += 2; + s->phys_pc += 2; break; case OS_WORD: if (val) - offset = ldsw_code(s->pc); + offset = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); else - offset = lduw_code(s->pc); + offset = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; break; case OS_LONG: offset = read_im32(s); @@ -879,8 +896,9 @@ DISAS_INSN(divl) int reg; uint16_t ext; - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (ext & 0x87f8) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); return; @@ -1066,8 +1084,9 @@ DISAS_INSN(movem) int tmp; int is_load; - mask = lduw_code(s->pc); + mask = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; tmp = gen_lea(s, insn, OS_LONG); if (tmp == -1) { gen_addr_fault(s); @@ -1111,8 +1130,9 @@ DISAS_INSN(bitop_im) opsize = OS_LONG; op = (insn >> 6) & 3; - bitnum = lduw_code(s->pc); + bitnum = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (bitnum & 0xff00) { disas_undef(s, insn); return; @@ -1375,8 +1395,9 @@ static void gen_set_sr(DisasContext *s, else if ((insn & 0x3f) == 0x3c) { uint16_t val; - val = lduw_code(s->pc); + val = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; gen_set_sr_im(s, val, ccr_only); } else @@ -1502,8 +1523,9 @@ DISAS_INSN(mull) /* The upper 32 bits of the product are discarded, so muls.l and mulu.l are functionally equivalent. */ - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (ext & 0x87ff) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); return; @@ -1523,8 +1545,9 @@ DISAS_INSN(link) int reg; int tmp; - offset = ldsw_code(s->pc); + offset = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; reg = AREG(insn, 0); tmp = gen_new_qreg(QMODE_I32); gen_op_sub32(tmp, QREG_SP, gen_im32(4)); @@ -1622,9 +1645,11 @@ DISAS_INSN(tpf) switch (insn & 7) { case 2: /* One extension word. */ s->pc += 2; + s->phys_pc += 2; break; case 3: /* Two extension words. */ s->pc += 4; + s->phys_pc += 4; break; case 4: /* No extension words. */ break; @@ -1644,8 +1669,9 @@ DISAS_INSN(branch) op = (insn >> 8) & 0xf; offset = (int8_t)insn; if (offset == 0) { - offset = ldsw_code(s->pc); + offset = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; } else if (offset == -1) { offset = read_im32(s); } @@ -1957,14 +1983,16 @@ DISAS_INSN(strldsr) uint32_t addr; addr = s->pc - 2; - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (ext != 0x46FC) { gen_exception(s, addr, EXCP_UNSUPPORTED); return; } - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (IS_USER(s) || (ext & SR_S) == 0) { gen_exception(s, addr, EXCP_PRIVILEGE); return; @@ -2032,8 +2060,9 @@ DISAS_INSN(stop) return; } - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; gen_set_sr_im(s, ext, 0); gen_jmp(s, gen_im32(s->pc)); @@ -2059,8 +2088,9 @@ DISAS_INSN(movec) return; } - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (ext & 0x8000) { reg = AREG(ext, 12); @@ -2121,8 +2151,9 @@ DISAS_INSN(fpu) int round; int opsize; - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; opmode = ext & 0x7f; switch ((ext >> 13) & 7) { case 0: case 2: @@ -2331,6 +2362,7 @@ DISAS_INSN(fpu) return; undef: s->pc -= 2; + s->phys_pc -= 2; disas_undef_fpu(s, insn); } @@ -2343,11 +2375,14 @@ DISAS_INSN(fbcc) int l1; addr = s->pc; - offset = ldsw_code(s->pc); + offset = ldsw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; if (insn & (1 << 6)) { - offset = (offset << 16) | lduw_code(s->pc); + offset = (offset << 16) | + lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; } l1 = gen_new_label(); @@ -2473,8 +2508,9 @@ DISAS_INSN(mac) int dual; int saved_flags = -1; - ext = lduw_code(s->pc); + ext = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); dual = ((insn & 0x30) != 0 && (ext & 3) != 0); @@ -2882,8 +2918,9 @@ static void disas_m68k_insn(CPUState * e { uint16_t insn; - insn = lduw_code(s->pc); + insn = lduw_code_p(&s->phys_pc_start, s->phys_pc, s->pc); s->pc += 2; + s->phys_pc += 2; opcode_table[insn](s, insn); } @@ -3169,6 +3206,9 @@ gen_intermediate_code_internal(CPUState dc->env = env; dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; + dc->phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + dc->phys_pc = dc->phys_pc_start; dc->cc_op = CC_OP_DYNAMIC; dc->singlestep_enabled = env->singlestep_enabled; dc->fpcr = env->fpcr; Index: target-mips/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/translate.c,v retrieving revision 1.106 diff -u -d -d -p -r1.106 translate.c --- target-mips/translate.c 9 Oct 2007 03:39:58 -0000 1.106 +++ target-mips/translate.c 12 Oct 2007 22:53:39 -0000 @@ -536,6 +536,7 @@ FOP_CONDS(abs, ps) typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc, saved_pc; + unsigned long phys_pc, phys_pc_start; uint32_t opcode; uint32_t fp_status; /* Routine used to access memory */ @@ -1764,6 +1765,7 @@ static void gen_compute_branch (DisasCon /* Skip the instruction in the delay slot */ MIPS_DEBUG("bnever, link and skip"); ctx->pc += 4; + ctx->phys_pc += 4; return; case OPC_BNEL: /* rx != rx likely */ case OPC_BGTZL: /* 0 > 0 likely */ @@ -1771,6 +1773,7 @@ static void gen_compute_branch (DisasCon /* Skip the instruction in the delay slot */ MIPS_DEBUG("bnever and skip"); ctx->pc += 4; + ctx->phys_pc += 4; return; case OPC_J: ctx->hflags |= MIPS_HFLAG_B; @@ -6495,6 +6498,9 @@ gen_intermediate_code_internal (CPUState gen_opparam_ptr = gen_opparam_buf; nb_gen_labels = 0; ctx.pc = pc_start; + ctx.phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + ctx.phys_pc = ctx.phys_pc_start; ctx.saved_pc = -1; ctx.tb = tb; ctx.bstate = BS_NONE; @@ -6544,9 +6550,10 @@ gen_intermediate_code_internal (CPUState gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; gen_opc_instr_start[lj] = 1; } - ctx.opcode = ldl_code(ctx.pc); + ctx.opcode = ldl_code_p(&ctx.phys_pc_start, ctx.phys_pc, ctx.pc); decode_opc(env, &ctx); ctx.pc += 4; + ctx.phys_pc += 4; if (env->singlestep_enabled) break; Index: target-ppc/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-ppc/translate.c,v retrieving revision 1.92 diff -u -d -d -p -r1.92 translate.c --- target-ppc/translate.c 7 Oct 2007 23:10:08 -0000 1.92 +++ target-ppc/translate.c 12 Oct 2007 22:53:40 -0000 @@ -6678,6 +6678,7 @@ static always_inline int gen_intermediat { DisasContext ctx, *ctxp = &ctx; opc_handler_t **table, *handler; + unsigned long phys_pc, phys_pc_start; target_ulong pc_start; uint16_t *gen_opc_end; int supervisor; @@ -6685,6 +6686,9 @@ static always_inline int gen_intermediat int j, lj = -1; pc_start = tb->pc; + phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + phys_pc = phys_pc_start; gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; @@ -6763,7 +6767,7 @@ static always_inline int gen_intermediat ctx.nip, 1 - msr_pr, msr_ir); } #endif - ctx.opcode = ldl_code(ctx.nip); + ctx.opcode = ldl_code_p(&phys_pc_start, phys_pc, env->nip); if (msr_le) { ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) | ((ctx.opcode & 0x00FF0000) >> 8) | @@ -6778,6 +6782,7 @@ static always_inline int gen_intermediat } #endif ctx.nip += 4; + phys_pc += 4; table = env->opcodes; handler = table[opc1(ctx.opcode)]; if (is_indirect_opcode(handler)) { Index: target-sh4/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-sh4/translate.c,v retrieving revision 1.18 diff -u -d -d -p -r1.18 translate.c --- target-sh4/translate.c 29 Sep 2007 19:52:22 -0000 1.18 +++ target-sh4/translate.c 12 Oct 2007 22:53:40 -0000 @@ -1150,11 +1150,15 @@ gen_intermediate_code_internal(CPUState { DisasContext ctx; target_ulong pc_start; + unsigned long phys_pc, phys_pc_start; static uint16_t *gen_opc_end; uint32_t old_flags; int i, ii; pc_start = tb->pc; + phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + phys_pc = phys_pc_start; gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; @@ -1210,9 +1214,10 @@ gen_intermediate_code_internal(CPUState fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc); fflush(stderr); #endif - ctx.opcode = lduw_code(ctx.pc); + ctx.opcode = lduw_code_p(&phys_pc_start, phys_pc, ctx.pc); decode_opc(&ctx); ctx.pc += 2; + phys_pc += 2; if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) break; if (env->singlestep_enabled) Index: target-sparc/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-sparc/translate.c,v retrieving revision 1.74 diff -u -d -d -p -r1.74 translate.c --- target-sparc/translate.c 10 Oct 2007 19:11:54 -0000 1.74 +++ target-sparc/translate.c 12 Oct 2007 22:53:40 -0000 @@ -48,6 +48,8 @@ typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ + unsigned long phys_pc; + unsigned long phys_pc_start; int is_br; int mem_idx; int fpu_enabled; @@ -1089,7 +1091,7 @@ static void disas_sparc_insn(DisasContex { unsigned int insn, opc, rs1, rs2, rd; - insn = ldl_code(dc->pc); + insn = ldl_code_p(&dc->phys_pc_start, dc->phys_pc, dc->pc); opc = GET_FIELD(insn, 0, 1); rd = GET_FIELD(insn, 2, 6); @@ -3319,6 +3321,7 @@ static void disas_sparc_insn(DisasContex } /* default case for non jump instructions */ if (dc->npc == DYNAMIC_PC) { + dc->phys_pc += DYNAMIC_PC - dc->pc; dc->pc = DYNAMIC_PC; gen_op_next_insn(); } else if (dc->npc == JUMP_PC) { @@ -3326,6 +3329,7 @@ static void disas_sparc_insn(DisasContex gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1]); dc->is_br = 1; } else { + dc->phys_pc += dc->npc - dc->pc; dc->pc = dc->npc; dc->npc = dc->npc + 4; } @@ -3376,6 +3380,9 @@ static inline int gen_intermediate_code_ dc->tb = tb; pc_start = tb->pc; dc->pc = pc_start; + dc->phys_pc_start = (unsigned long)phys_ram_base + tb->page_addr[0] + + (pc_start & ~TARGET_PAGE_MASK); + dc->phys_pc = dc->phys_pc_start; last_pc = dc->pc; dc->npc = (target_ulong) tb->cs_base; #if defined(CONFIG_USER_ONLY)