From: "J. Mayer" <l_indien@magic.fr>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] RFC: Code fetch optimisation
Date: Sun, 14 Oct 2007 13:44:27 +0200 [thread overview]
Message-ID: <1192362267.9976.383.camel@rapid> (raw)
[-- Attachment #1: Type: text/plain, Size: 480 bytes --]
Here's an updated version of the code fetch optimisation patch against
current CVS.
As a remainder, this patch avoid use of softmmu helpers to fetch the
code in most case. A new target define TARGET_HAS_VLE_INSNS has been
added which is used to handle the case of an instruction that span 2
pages, when the target CPU uses a variable-length instructions encoding.
For pure RISC, the code fetch is done using raw access routines.
--
J. Mayer <l_indien@magic.fr>
Never organized
[-- Attachment #2: code_raw_optim.diff --]
[-- Type: text/x-patch, Size: 57829 bytes --]
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 14 Oct 2007 11:35:53 -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.120
diff -u -d -d -p -r1.120 cpu-exec.c
--- cpu-exec.c 14 Oct 2007 07:07:04 -0000 1.120
+++ cpu-exec.c 14 Oct 2007 11:35:53 -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.18
diff -u -d -d -p -r1.18 softmmu_header.h
--- softmmu_header.h 14 Oct 2007 07:07:05 -0000 1.18
+++ softmmu_header.h 14 Oct 2007 11:35:53 -0000
@@ -289,6 +289,68 @@ 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;
+
+ /* XXX: Target executing code from MMIO ares is not supported for now */
+#if defined(TARGET_HAS_VLE_INSNS) /* || defined(TARGET_MMIO_CODE) */
+ 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 could call get_phys_addr_code(env, pc); and remove the else
+ * condition, here.
+ */
+ //*start_pc = phys_pc;
+ } else
+#endif
+ {
+ 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;
+
+ /* XXX: Target executing code from MMIO ares is not supported for now */
+#if defined(TARGET_HAS_VLE_INSNS) /* || defined(TARGET_MMIO_CODE) */
+ 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 could call get_phys_addr_code(env, pc); and remove the else
+ * condition, here.
+ */
+ //*start_pc = phys_pc;
+ } else
+#endif
+ {
+ opc = glue(glue(ld,USUFFIX),_raw)(phys_pc);
+ }
+
+ return opc;
+}
+
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
#endif /* !asm */
Index: target-alpha/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-alpha/translate.c,v
retrieving revision 1.6
diff -u -d -d -p -r1.6 translate.c
--- target-alpha/translate.c 14 Oct 2007 08:50:17 -0000 1.6
+++ target-alpha/translate.c 14 Oct 2007 11:35:54 -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 14 Oct 2007 11:35:54 -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/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-cris/cpu.h,v
retrieving revision 1.2
diff -u -d -d -p -r1.2 cpu.h
--- target-cris/cpu.h 14 Oct 2007 07:07:06 -0000 1.2
+++ target-cris/cpu.h 14 Oct 2007 11:35:54 -0000
@@ -22,6 +22,8 @@
#define CPU_CRIS_H
#define TARGET_LONG_BITS 32
+/* need explicit support for instructions spanning 2 pages */
+#define TARGET_HAS_VLE_INSNS 1
#include "cpu-defs.h"
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 14 Oct 2007 11:35:55 -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/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-i386/cpu.h,v
retrieving revision 1.51
diff -u -d -d -p -r1.51 cpu.h
--- target-i386/cpu.h 14 Oct 2007 07:07:06 -0000 1.51
+++ target-i386/cpu.h 14 Oct 2007 11:35:55 -0000
@@ -33,6 +33,8 @@
/* support for self modifying code even if the modified instruction is
close to the modifying instruction */
#define TARGET_HAS_PRECISE_SMC
+/* need explicit support for instructions spanning 2 pages */
+#define TARGET_HAS_VLE_INSNS 1
#define TARGET_HAS_ICE 1
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 14 Oct 2007 11:35:55 -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/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/cpu.h,v
retrieving revision 1.14
diff -u -d -d -p -r1.14 cpu.h
--- target-m68k/cpu.h 14 Oct 2007 07:07:06 -0000 1.14
+++ target-m68k/cpu.h 14 Oct 2007 11:35:55 -0000
@@ -22,6 +22,8 @@
#define CPU_M68K_H
#define TARGET_LONG_BITS 32
+/* need explicit support for instructions spanning 2 pages */
+#define TARGET_HAS_VLE_INSNS 1
#include "cpu-defs.h"
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 14 Oct 2007 11:35:55 -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 14 Oct 2007 11:35:56 -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/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-ppc/cpu.h,v
retrieving revision 1.83
diff -u -d -d -p -r1.83 cpu.h
--- target-ppc/cpu.h 14 Oct 2007 10:21:20 -0000 1.83
+++ target-ppc/cpu.h 14 Oct 2007 11:35:56 -0000
@@ -37,6 +37,8 @@ typedef uint64_t ppc_gpr_t;
#define TARGET_GPR_BITS 64
#define TARGET_LONG_BITS 32
#define REGX "%016" PRIx64
+/* need explicit support for instructions spanning 2 pages for VLE code */
+#define TARGET_HAS_VLE_INSNS 1
#if defined(CONFIG_USER_ONLY)
/* It looks like a lot of Linux programs assume page size
* is 4kB long. This is evil, but we have to deal with it...
Index: target-ppc/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-ppc/translate.c,v
retrieving revision 1.93
diff -u -d -d -p -r1.93 translate.c
--- target-ppc/translate.c 14 Oct 2007 07:07:07 -0000 1.93
+++ target-ppc/translate.c 14 Oct 2007 11:35:56 -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;
@@ -6756,7 +6760,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, ctx.nip);
if (msr_le) {
ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
((ctx.opcode & 0x00FF0000) >> 8) |
@@ -6771,6 +6775,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 14 Oct 2007 11:35:56 -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.75
diff -u -d -d -p -r1.75 translate.c
--- target-sparc/translate.c 14 Oct 2007 07:07:08 -0000 1.75
+++ target-sparc/translate.c 14 Oct 2007 11:35:56 -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);
@@ -3376,6 +3378,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)
@@ -3422,6 +3427,7 @@ static inline int gen_intermediate_code_
}
}
last_pc = dc->pc;
+ dc->phys_pc = dc->phys_pc_start + dc->pc - pc_start;
disas_sparc_insn(dc);
if (dc->is_br)
next reply other threads:[~2007-10-14 11:44 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-14 11:44 J. Mayer [this message]
2007-10-15 2:30 ` [Qemu-devel] RFC: Code fetch optimisation Paul Brook
2007-10-15 12:09 ` J. Mayer
2007-10-15 16:01 ` Paul Brook
2007-10-15 16:19 ` Fabrice Bellard
2007-10-15 21:30 ` J. Mayer
2007-10-15 22:42 ` Paul Brook
2007-10-16 20:27 ` J. Mayer
2007-10-16 22:00 ` Paul Brook
2007-10-16 23:38 ` J. Mayer
2007-10-17 0:43 ` Paul Brook
2007-10-16 22:26 ` Paul Brook
-- strict thread matches above, loose matches on Subject: below --
2007-10-12 8:33 J. Mayer
2007-10-12 15:21 ` Blue Swirl
2007-10-12 18:24 ` Jocelyn Mayer
2007-10-12 18:36 ` Fabrice Bellard
2007-10-12 18:39 ` Fabrice Bellard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1192362267.9976.383.camel@rapid \
--to=l_indien@magic.fr \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).