349 lines
12 KiB
Diff
349 lines
12 KiB
Diff
|
diff -Naur qemu-0.9.1.orig/configure qemu-0.9.1/configure
|
||
|
--- qemu-0.9.1.orig/configure 2008-01-06 20:38:42.000000000 +0100
|
||
|
+++ qemu-0.9.1/configure 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -790,6 +790,12 @@
|
||
|
if test "$cpu" = "i386" ; then
|
||
|
echo "ARCH=i386" >> $config_mak
|
||
|
echo "#define HOST_I386 1" >> $config_h
|
||
|
+
|
||
|
+ # add check for gcc4 breakage
|
||
|
+ echo "#if (__GNUC__ > 3)" >> $config_h
|
||
|
+ echo "#define GCC_BREAKS_T_REGISTER" >> $config_h
|
||
|
+ echo "#endif" >> $config_h
|
||
|
+
|
||
|
elif test "$cpu" = "x86_64" ; then
|
||
|
echo "ARCH=x86_64" >> $config_mak
|
||
|
echo "#define HOST_X86_64 1" >> $config_h
|
||
|
diff -Naur qemu-0.9.1.orig/dyngen.c qemu-0.9.1/dyngen.c
|
||
|
--- qemu-0.9.1.orig/dyngen.c 2008-01-06 20:38:42.000000000 +0100
|
||
|
+++ qemu-0.9.1/dyngen.c 2008-02-06 10:31:41.000000000 +0100
|
||
|
@@ -1488,6 +1488,16 @@
|
||
|
if (get32((uint32_t *)p) != 0x4e800020)
|
||
|
error("blr expected at the end of %s", name);
|
||
|
copy_size = p - p_start;
|
||
|
+
|
||
|
+/* blr check for inline returns */
|
||
|
+
|
||
|
+ if(strstart(name, "op_", NULL) && !strstart(name, "op_exit", NULL)) {
|
||
|
+ for(p=p_start; p < p_end - 4; p+=4) {
|
||
|
+ if ((get32((uint32_t *)p) & 0xfc00fff0) == 0x4c000020) {
|
||
|
+ error("Inline blr detected in %s. Please append FORCE_RET to the function.", name);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
#elif defined(HOST_S390)
|
||
|
{
|
||
|
@@ -1931,6 +1941,17 @@
|
||
|
type = ELF32_R_TYPE(rel->r_info);
|
||
|
addend = rel->r_addend;
|
||
|
reloc_offset = rel->r_offset - start_offset;
|
||
|
+ if (strstart(sym_name, "__op_jmp", &p)) {
|
||
|
+ int n;
|
||
|
+ n = strtol(p, NULL, 10);
|
||
|
+ /* __op_jmp relocations are done at
|
||
|
+ runtime to do translated block
|
||
|
+ chaining: the offset of the instruction
|
||
|
+ needs to be stored */
|
||
|
+ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
|
||
|
+ n, reloc_offset);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
switch(type) {
|
||
|
case R_X86_64_32:
|
||
|
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
|
||
|
diff -Naur qemu-0.9.1.orig/exec-all.h qemu-0.9.1/exec-all.h
|
||
|
--- qemu-0.9.1.orig/exec-all.h 2008-01-06 20:38:42.000000000 +0100
|
||
|
+++ qemu-0.9.1/exec-all.h 2008-02-06 10:31:41.000000000 +0100
|
||
|
@@ -142,6 +142,9 @@
|
||
|
#if defined(__i386__) && !defined(_WIN32)
|
||
|
#define USE_DIRECT_JUMP
|
||
|
#endif
|
||
|
+#if defined(__x86_64__)
|
||
|
+#define USE_DIRECT_JUMP
|
||
|
+#endif
|
||
|
|
||
|
typedef struct TranslationBlock {
|
||
|
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
|
||
|
@@ -228,7 +231,7 @@
|
||
|
asm volatile ("sync" : : : "memory");
|
||
|
asm volatile ("isync" : : : "memory");
|
||
|
}
|
||
|
-#elif defined(__i386__)
|
||
|
+#elif defined(__i386__) || defined(__x86_64__)
|
||
|
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
|
||
|
{
|
||
|
/* patch the branch destination */
|
||
|
@@ -320,6 +323,18 @@
|
||
|
"1:\n");\
|
||
|
} while (0)
|
||
|
|
||
|
+#elif defined(__x86_64__) && defined(USE_DIRECT_JUMP)
|
||
|
+
|
||
|
+#define GOTO_TB(opname, tbparam, n)\
|
||
|
+do {\
|
||
|
+ asm volatile (ASM_DATA_SECTION\
|
||
|
+ ASM_OP_LABEL_NAME(n, opname) ":\n"\
|
||
|
+ ".quad 1f\n"\
|
||
|
+ ASM_PREVIOUS_SECTION \
|
||
|
+ "jmp " ASM_NAME(__op_jmp) #n "\n"\
|
||
|
+ "1:\n");\
|
||
|
+} while (0)
|
||
|
+
|
||
|
#else
|
||
|
|
||
|
/* jump to next block operations (more portable code, does not need
|
||
|
diff -Naur qemu-0.9.1.orig/softmmu_header.h qemu-0.9.1/softmmu_header.h
|
||
|
--- qemu-0.9.1.orig/softmmu_header.h 2008-01-06 20:38:42.000000000 +0100
|
||
|
+++ qemu-0.9.1/softmmu_header.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -189,9 +189,15 @@
|
||
|
#else
|
||
|
#error unsupported size
|
||
|
#endif
|
||
|
+#ifdef GCC_BREAKS_T_REGISTER
|
||
|
+ "pushl %%ecx\n"
|
||
|
+#endif
|
||
|
"pushl %6\n"
|
||
|
"call %7\n"
|
||
|
"popl %%eax\n"
|
||
|
+#ifdef GCC_BREAKS_T_REGISTER
|
||
|
+ "popl %%ecx\n"
|
||
|
+#endif
|
||
|
"jmp 2f\n"
|
||
|
"1:\n"
|
||
|
"addl 8(%%edx), %%eax\n"
|
||
|
@@ -209,14 +215,22 @@
|
||
|
: "r" (ptr),
|
||
|
/* NOTE: 'q' would be needed as constraint, but we could not use it
|
||
|
with T1 ! */
|
||
|
+#if (DATA_SIZE == 1 || DATA_SIZE == 2) && defined(GCC_BREAKS_T_REGISTER)
|
||
|
+ "q" (v),
|
||
|
+#else
|
||
|
"r" (v),
|
||
|
+#endif
|
||
|
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
|
||
|
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
|
||
|
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
|
||
|
"m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
|
||
|
"i" (CPU_MMU_INDEX),
|
||
|
"m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
|
||
|
+#ifdef GCC_BREAKS_T_REGISTER
|
||
|
+ : "%eax", "%edx", "memory", "cc");
|
||
|
+#else
|
||
|
: "%eax", "%ecx", "%edx", "memory", "cc");
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
diff -Naur qemu-0.9.1.orig/target-alpha/cpu.h qemu-0.9.1/target-alpha/cpu.h
|
||
|
--- qemu-0.9.1.orig/target-alpha/cpu.h 2008-01-06 20:38:44.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-alpha/cpu.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -275,6 +275,8 @@
|
||
|
* used to emulate 64 bits target on 32 bits hosts
|
||
|
*/
|
||
|
target_ulong t0, t1, t2;
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+ target_ulong t2;
|
||
|
#endif
|
||
|
/* */
|
||
|
double ft0, ft1, ft2;
|
||
|
diff -Naur qemu-0.9.1.orig/target-alpha/exec.h qemu-0.9.1/target-alpha/exec.h
|
||
|
--- qemu-0.9.1.orig/target-alpha/exec.h 2008-01-06 20:38:44.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-alpha/exec.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -36,6 +36,12 @@
|
||
|
#define T1 (env->t1)
|
||
|
#define T2 (env->t2)
|
||
|
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+
|
||
|
+register uint64_t T0 asm(AREG1);
|
||
|
+register uint64_t T1 asm(AREG2);
|
||
|
+#define T2 (env->t2)
|
||
|
+
|
||
|
#else
|
||
|
|
||
|
register uint64_t T0 asm(AREG1);
|
||
|
diff -Naur qemu-0.9.1.orig/target-alpha/op_template.h qemu-0.9.1/target-alpha/op_template.h
|
||
|
--- qemu-0.9.1.orig/target-alpha/op_template.h 2008-01-06 20:38:44.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-alpha/op_template.h 2008-02-06 10:31:23.000000000 +0100
|
||
|
@@ -29,7 +29,26 @@
|
||
|
#if !defined(HOST_SPARC) && !defined(HOST_SPARC64)
|
||
|
void OPPROTO glue(op_reset_FT, REG) (void)
|
||
|
{
|
||
|
+#ifdef HOST_PPC
|
||
|
+ /* We have a problem with HOST_PPC here:
|
||
|
+ We want this code:
|
||
|
+ glue(FT, REG) = 0;
|
||
|
+ unfortunately GCC4 notices that this stores (double)0.0 into
|
||
|
+ env->ft0 and emits that constant into the .rodata, and instructions
|
||
|
+ to load that zero from there. But that construct can't be parsed by dyngen.
|
||
|
+ We could add -ffast-math for compiling op.c, that would just make it generate
|
||
|
+ two stores of zeros into both words of ft0. But -ffast-math may have other
|
||
|
+ side-effects regarding the emulation. We could use __builtin_memset,
|
||
|
+ which perhaps would be the sanest. That relies on -O2 and our other options
|
||
|
+ to inline that memset, which currently it does, but who knows for how long.
|
||
|
+ So, we simply do that by hand, and a barely typesafe way :-/ */
|
||
|
+ union baeh { double d; unsigned int i[2];};
|
||
|
+ union baeh *p = (union baeh*)&(glue(FT, REG));
|
||
|
+ p->i[0] = 0;
|
||
|
+ p->i[1] = 0;
|
||
|
+#else
|
||
|
glue(FT, REG) = 0;
|
||
|
+#endif
|
||
|
RETURN();
|
||
|
}
|
||
|
#else
|
||
|
diff -Naur qemu-0.9.1.orig/target-arm/cpu.h qemu-0.9.1/target-arm/cpu.h
|
||
|
--- qemu-0.9.1.orig/target-arm/cpu.h 2008-01-06 20:38:44.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-arm/cpu.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -66,6 +66,9 @@
|
||
|
*/
|
||
|
|
||
|
typedef struct CPUARMState {
|
||
|
+#if defined(GCC_BREAKS_T_REGISTER)
|
||
|
+ uint32_t t2;
|
||
|
+#endif
|
||
|
/* Regs for current mode. */
|
||
|
uint32_t regs[16];
|
||
|
/* Frequently accessed CPSR bits are stored separately for efficiently.
|
||
|
diff -Naur qemu-0.9.1.orig/target-arm/exec.h qemu-0.9.1/target-arm/exec.h
|
||
|
--- qemu-0.9.1.orig/target-arm/exec.h 2008-01-06 20:38:44.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-arm/exec.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -23,7 +23,12 @@
|
||
|
register struct CPUARMState *env asm(AREG0);
|
||
|
register uint32_t T0 asm(AREG1);
|
||
|
register uint32_t T1 asm(AREG2);
|
||
|
+#if defined(GCC_BREAKS_T_REGISTER)
|
||
|
+#define T2 (env->t2)
|
||
|
+#else
|
||
|
register uint32_t T2 asm(AREG3);
|
||
|
+#endif
|
||
|
+
|
||
|
|
||
|
/* TODO: Put these in FP regs on targets that have such things. */
|
||
|
/* It is ok for FT0s and FT0d to overlap. Likewise FT1s and FT1d. */
|
||
|
diff -Naur qemu-0.9.1.orig/target-i386/cpu.h qemu-0.9.1/target-i386/cpu.h
|
||
|
--- qemu-0.9.1.orig/target-i386/cpu.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-i386/cpu.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -470,6 +470,8 @@
|
||
|
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
||
|
/* temporaries if we cannot store them in host registers */
|
||
|
target_ulong t0, t1, t2;
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+ target_ulong t1;
|
||
|
#endif
|
||
|
|
||
|
/* standard registers */
|
||
|
diff -Naur qemu-0.9.1.orig/target-i386/exec.h qemu-0.9.1/target-i386/exec.h
|
||
|
--- qemu-0.9.1.orig/target-i386/exec.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-i386/exec.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -39,6 +39,12 @@
|
||
|
#define T1 (env->t1)
|
||
|
#define T2 (env->t2)
|
||
|
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+
|
||
|
+register target_ulong T0 asm(AREG1);
|
||
|
+#define T1 (env->t1)
|
||
|
+register target_ulong T2 asm(AREG3);
|
||
|
+
|
||
|
#else
|
||
|
|
||
|
/* XXX: use unsigned long instead of target_ulong - better code will
|
||
|
diff -Naur qemu-0.9.1.orig/target-i386/op.c qemu-0.9.1/target-i386/op.c
|
||
|
--- qemu-0.9.1.orig/target-i386/op.c 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-i386/op.c 2008-02-06 10:31:17.000000000 +0100
|
||
|
@@ -290,6 +290,7 @@
|
||
|
EDX = (uint32_t)(res >> 32);
|
||
|
CC_DST = res;
|
||
|
CC_SRC = (res != (int32_t)res);
|
||
|
+ FORCE_RET();
|
||
|
}
|
||
|
|
||
|
void OPPROTO op_imulw_T0_T1(void)
|
||
|
@@ -299,6 +300,7 @@
|
||
|
T0 = res;
|
||
|
CC_DST = res;
|
||
|
CC_SRC = (res != (int16_t)res);
|
||
|
+ FORCE_RET();
|
||
|
}
|
||
|
|
||
|
void OPPROTO op_imull_T0_T1(void)
|
||
|
@@ -308,6 +310,7 @@
|
||
|
T0 = res;
|
||
|
CC_DST = res;
|
||
|
CC_SRC = (res != (int32_t)res);
|
||
|
+ FORCE_RET();
|
||
|
}
|
||
|
|
||
|
#ifdef TARGET_X86_64
|
||
|
diff -Naur qemu-0.9.1.orig/target-i386/ops_template.h qemu-0.9.1/target-i386/ops_template.h
|
||
|
--- qemu-0.9.1.orig/target-i386/ops_template.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-i386/ops_template.h 2008-02-06 10:31:17.000000000 +0100
|
||
|
@@ -467,6 +467,7 @@
|
||
|
int count;
|
||
|
count = T1 & SHIFT_MASK;
|
||
|
CC_SRC = T0 >> count;
|
||
|
+ FORCE_RET();
|
||
|
}
|
||
|
|
||
|
void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
|
||
|
diff -Naur qemu-0.9.1.orig/target-mips/cpu.h qemu-0.9.1/target-mips/cpu.h
|
||
|
--- qemu-0.9.1.orig/target-mips/cpu.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-mips/cpu.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -149,6 +149,8 @@
|
||
|
target_ulong t0;
|
||
|
target_ulong t1;
|
||
|
target_ulong t2;
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+ target_ulong t2;
|
||
|
#endif
|
||
|
target_ulong HI[MIPS_DSP_ACC][MIPS_TC_MAX];
|
||
|
target_ulong LO[MIPS_DSP_ACC][MIPS_TC_MAX];
|
||
|
diff -Naur qemu-0.9.1.orig/target-mips/exec.h qemu-0.9.1/target-mips/exec.h
|
||
|
--- qemu-0.9.1.orig/target-mips/exec.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-mips/exec.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -14,6 +14,10 @@
|
||
|
#define T0 (env->t0)
|
||
|
#define T1 (env->t1)
|
||
|
#define T2 (env->t2)
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+register target_ulong T0 asm(AREG1);
|
||
|
+register target_ulong T1 asm(AREG2);
|
||
|
+#define T2 (env->t2)
|
||
|
#else
|
||
|
register target_ulong T0 asm(AREG1);
|
||
|
register target_ulong T1 asm(AREG2);
|
||
|
diff -Naur qemu-0.9.1.orig/target-ppc/exec.h qemu-0.9.1/target-ppc/exec.h
|
||
|
--- qemu-0.9.1.orig/target-ppc/exec.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-ppc/exec.h 2008-02-06 10:29:35.000000000 +0100
|
||
|
@@ -38,6 +38,10 @@
|
||
|
#define T1 (env->t1)
|
||
|
#define T2 (env->t2)
|
||
|
#define TDX "%016" PRIx64
|
||
|
+#elif defined(GCC_BREAKS_T_REGISTER)
|
||
|
+register unsigned long T0 asm(AREG1);
|
||
|
+register unsigned long T1 asm(AREG2);
|
||
|
+#define T2 (env->t2)
|
||
|
#else
|
||
|
register unsigned long T0 asm(AREG1);
|
||
|
register unsigned long T1 asm(AREG2);
|
||
|
diff -Naur qemu-0.9.1.orig/target-sparc/exec.h qemu-0.9.1/target-sparc/exec.h
|
||
|
--- qemu-0.9.1.orig/target-sparc/exec.h 2008-01-06 20:38:45.000000000 +0100
|
||
|
+++ qemu-0.9.1/target-sparc/exec.h 2008-02-06 10:19:59.000000000 +0100
|
||
|
@@ -32,9 +32,13 @@
|
||
|
|
||
|
#else
|
||
|
#define REGWPTR env->regwptr
|
||
|
+#if !defined(GCC_BREAKS_T_REGISTER)
|
||
|
register uint32_t T2 asm(AREG3);
|
||
|
-#endif
|
||
|
#define reg_T2
|
||
|
+#else
|
||
|
+#define T2 (env->t2)
|
||
|
+#endif
|
||
|
+#endif
|
||
|
#endif
|
||
|
|
||
|
#define FT0 (env->ft0)
|