Hi,
By adding some GCC4 fixes on top of your patch, I was able to get qemu for i386 (on i386) to compile and run. So far, I've only tested a win2k guest.
For op_pshufw(), please keep the temporary destination register as S and D may reference the same register.
FYI, I am experimenting with an alternate gcc4 patch (inlined hereunder). <http://svn.mandriva.com/svn/packages/cooker/qemu/current/SOURCES/qemu-0.9.0-gcc4.patch> I have only tested the following configurations with -no-kvm -no-kqemu - compiler: gcc 4.1.2-1mdv - guest OS: { winXPsp2, linux } - guest CPU: { i386, x86_64 (linux-only) } - host CPU (compiled as): { i386, x86_64 } PS: I have not tested yet on MacOS X. Regards, Gwenole 2007-04-20 Gwenole Beauchesne <[EMAIL PROTECTED]> * gcc4 host support. --- qemu-0.9.0/target-i386/ops_template.h.gcc4 2005-02-21 20:23:59.000000000 +0000 +++ qemu-0.9.0/target-i386/ops_template.h 2007-04-20 14:53:32.000000000 +0000 @@ -268,7 +268,7 @@ static int glue(compute_all_mul, SUFFIX) /* various optimized jumps cases */ -void OPPROTO glue(op_jb_sub, SUFFIX)(void) +DEFINE_OP(glue(op_jb_sub, SUFFIX), { target_long src1, src2; src1 = CC_DST + CC_SRC; @@ -277,23 +277,23 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(voi if ((DATA_TYPE)src1 < (DATA_TYPE)src2) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jz_sub, SUFFIX)(void) +DEFINE_OP(glue(op_jz_sub, SUFFIX), { if ((DATA_TYPE)CC_DST == 0) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jnz_sub, SUFFIX)(void) +DEFINE_OP(glue(op_jnz_sub, SUFFIX), { if ((DATA_TYPE)CC_DST != 0) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jbe_sub, SUFFIX)(void) +DEFINE_OP(glue(op_jbe_sub, SUFFIX), { target_long src1, src2; src1 = CC_DST + CC_SRC; @@ -302,16 +302,16 @@ void OPPROTO glue(op_jbe_sub, SUFFIX)(vo if ((DATA_TYPE)src1 <= (DATA_TYPE)src2) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_js_sub, SUFFIX)(void) +DEFINE_OP(glue(op_js_sub, SUFFIX), { if (CC_DST & SIGN_MASK) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jl_sub, SUFFIX)(void) +DEFINE_OP(glue(op_jl_sub, SUFFIX), { target_long src1, src2; src1 = CC_DST + CC_SRC; @@ -320,10 +320,9 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(voi if ((DATA_STYPE)src1 < (DATA_STYPE)src2) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jle_sub, SUFFIX)(void) -{ +DEFINE_OP(glue(op_jle_sub, SUFFIX), { target_long src1, src2; src1 = CC_DST + CC_SRC; src2 = CC_SRC; @@ -331,39 +330,39 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(vo if ((DATA_STYPE)src1 <= (DATA_STYPE)src2) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) /* oldies */ #if DATA_BITS >= 16 -void OPPROTO glue(op_loopnz, SUFFIX)(void) +DEFINE_OP(glue(op_loopnz, SUFFIX), { if ((DATA_TYPE)ECX != 0 && !(T0 & CC_Z)) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_loopz, SUFFIX)(void) +DEFINE_OP(glue(op_loopz, SUFFIX), { if ((DATA_TYPE)ECX != 0 && (T0 & CC_Z)) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jz_ecx, SUFFIX)(void) +DEFINE_OP(glue(op_jz_ecx, SUFFIX), { if ((DATA_TYPE)ECX == 0) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) -void OPPROTO glue(op_jnz_ecx, SUFFIX)(void) +DEFINE_OP(glue(op_jnz_ecx, SUFFIX), { if ((DATA_TYPE)ECX != 0) GOTO_LABEL_PARAM(1); FORCE_RET(); -} +}) #endif --- qemu-0.9.0/target-i386/op.c.gcc4 2007-02-02 12:45:51.000000000 +0000 +++ qemu-0.9.0/target-i386/op.c 2007-04-20 15:20:55.000000000 +0000 @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if __GNUC__ < 4 #define ASM_SOFTMMU +#endif #include "exec.h" /* n must be a constant to be efficient */ @@ -250,6 +252,7 @@ void OPPROTO op_imulb_AL_T0(void) EAX = (EAX & ~0xffff) | (res & 0xffff); CC_DST = res; CC_SRC = (res != (int8_t)res); + FORCE_RET(); } void OPPROTO op_mulw_AX_T0(void) @@ -270,6 +273,7 @@ void OPPROTO op_imulw_AX_T0(void) EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); CC_DST = res; CC_SRC = (res != (int16_t)res); + FORCE_RET(); } void OPPROTO op_mull_EAX_T0(void) @@ -290,6 +294,7 @@ void OPPROTO op_imull_EAX_T0(void) 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 +304,7 @@ void OPPROTO op_imulw_T0_T1(void) T0 = res; CC_DST = res; CC_SRC = (res != (int16_t)res); + FORCE_RET(); } void OPPROTO op_imull_T0_T1(void) @@ -308,6 +314,7 @@ void OPPROTO op_imull_T0_T1(void) T0 = res; CC_DST = res; CC_SRC = (res != (int32_t)res); + FORCE_RET(); } #ifdef TARGET_X86_64 --- qemu-0.9.0/target-i386/exec.h.gcc4 2006-09-24 18:40:46.000000000 +0000 +++ qemu-0.9.0/target-i386/exec.h 2007-04-20 15:14:38.000000000 +0000 @@ -501,6 +501,7 @@ void update_fp_status(void); void helper_hlt(void); void helper_monitor(void); void helper_mwait(void); +void helper_pshufw(MMXReg *dst, MMXReg *src, int order); extern const uint8_t parity_table[256]; extern const uint8_t rclw_table[32]; --- qemu-0.9.0/target-i386/helper.c.gcc4 2007-04-20 14:49:44.000000000 +0000 +++ qemu-0.9.0/target-i386/helper.c 2007-04-20 15:00:02.000000000 +0000 @@ -3522,8 +3522,15 @@ void helper_fxrstor(target_ulong ptr, in nb_xmm_regs = 8 << data64; addr = ptr + 0xa0; for(i = 0; i < nb_xmm_regs; i++) { +#if __GNUC__ < 4 env->xmm_regs[i].XMM_Q(0) = ldq(addr); env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8); +#else + env->xmm_regs[i].XMM_L(0) = ldl(addr); + env->xmm_regs[i].XMM_L(1) = ldl(addr + 4); + env->xmm_regs[i].XMM_L(2) = ldl(addr + 8); + env->xmm_regs[i].XMM_L(3) = ldl(addr + 12); +#endif addr += 16; } } --- qemu-0.9.0/target-i386/ops_sse.h.gcc4 2007-01-16 19:28:58.000000000 +0000 +++ qemu-0.9.0/target-i386/ops_sse.h 2007-04-20 15:11:19.000000000 +0000 @@ -581,14 +581,9 @@ void OPPROTO glue(op_movq_T0_mm, SUFFIX) void OPPROTO glue(op_pshufw, SUFFIX) (void) { Reg r, *d, *s; - int order; d = (Reg *)((char *)env + PARAM1); s = (Reg *)((char *)env + PARAM2); - order = PARAM3; - r.W(0) = s->W(order & 3); - r.W(1) = s->W((order >> 2) & 3); - r.W(2) = s->W((order >> 4) & 3); - r.W(3) = s->W((order >> 6) & 3); + helper_pshufw(&r, s, PARAM3); *d = r; } #else --- qemu-0.9.0/target-i386/helper2.c.gcc4 2007-04-20 14:49:44.000000000 +0000 +++ qemu-0.9.0/target-i386/helper2.c 2007-04-20 15:15:22.000000000 +0000 @@ -1038,3 +1038,11 @@ void save_native_fp_state(CPUState *env) env->native_fp_regs = 0; } #endif + +void helper_pshufw(MMXReg *dst, MMXReg *src, int order) +{ + dst->MMX_W(0) = src->MMX_W(order & 3); + dst->MMX_W(1) = src->MMX_W((order >> 2) & 3); + dst->MMX_W(2) = src->MMX_W((order >> 4) & 3); + dst->MMX_W(3) = src->MMX_W((order >> 6) & 3); +} --- qemu-0.9.0/dyngen-exec.h.gcc4 2007-04-20 14:49:44.000000000 +0000 +++ qemu-0.9.0/dyngen-exec.h 2007-04-20 14:54:50.000000000 +0000 @@ -279,4 +279,24 @@ extern int __op_jmp0, __op_jmp1, __op_jm #define EXIT_TB() asm volatile ("rts") #endif +#if defined __i386__ || defined __x86_64__ +#define DEFINE_OP(NAME, ...) \ +static void OPPROTO glue(impl_, NAME)(void) __attribute__((used)); \ +void OPPROTO glue(impl_, NAME)(void) \ +{ \ + asm volatile (".globl " ASM_NAME(NAME)); \ + asm volatile (".type " ASM_NAME(NAME) ", @function"); \ + asm volatile (ASM_NAME(NAME) ":"); \ + __VA_ARGS__; \ + asm volatile ("ret"); \ + asm volatile (".size " ASM_NAME(NAME) ", .-" ASM_NAME(NAME)); \ +} +#else +#define DEFINE_OP(NAME, ...) \ +void OPPROTO NAME(void) \ +{ \ + __VA_ARGS__; \ +} +#endif + #endif /* !defined(__DYNGEN_EXEC_H__) */ --- qemu-0.9.0/cpu-all.h.gcc4 2007-04-20 14:49:44.000000000 +0000 +++ qemu-0.9.0/cpu-all.h 2007-04-20 14:58:38.000000000 +0000 @@ -339,7 +339,13 @@ static inline void stl_le_p(void *ptr, i static inline void stq_le_p(void *ptr, uint64_t v) { +#if __GNUC__ < 4 *(uint64_t *)ptr = v; +#else + uint8_t *p = ptr; + stl_le_p(p, (uint32_t)v); + stl_le_p(p + 4, v >> 32); +#endif } /* float access */ --- qemu-0.9.0/cpu-exec.c.gcc4 2007-04-20 15:43:06.000000000 +0000 +++ qemu-0.9.0/cpu-exec.c 2007-04-20 15:50:20.000000000 +0000 @@ -737,6 +737,18 @@ int cpu_exec(CPUState *env1) ); } } +#elif defined(__i386__) || defined(__x86_64__) + asm volatile ("call *%0" + : /* no outputs */ + : "r" (gen_func) + : AREG0, AREG1, AREG2, AREG3 +#ifdef AREG4 + , AREG4 +#endif +#ifdef AREG5 + , AREG5 +#endif + ); #elif defined(__ia64) struct fptr { void *ip;