commit 4b74fe1f0013c622693b26141c0ed031a284a45a
Author: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Mon Mar 3 23:23:09 2003 +0000

    many fixes
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@19 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/op-i386.c b/op-i386.c
index 849e508..f7f1a98 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -10,7 +10,18 @@ typedef signed short int16_t;
 typedef signed int int32_t;
 typedef signed long long int64_t;
 
+#define bswap32(x) \
+({ \
+	uint32_t __x = (x); \
+	((uint32_t)( \
+		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
+		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
+		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
+})
+
 #define NULL 0
+#include <fenv.h>
 
 typedef struct FILE FILE;
 extern FILE *logfile;
@@ -18,41 +29,39 @@ extern int loglevel;
 extern int fprintf(FILE *, const char *, ...);
 
 #ifdef __i386__
-register int T0 asm("esi");
-register int T1 asm("ebx");
-register int A0 asm("edi");
+register unsigned int T0 asm("ebx");
+register unsigned int T1 asm("esi");
+register unsigned int A0 asm("edi");
 register struct CPUX86State *env asm("ebp");
-#define FORCE_RET() asm volatile ("ret");
 #endif
 #ifdef __powerpc__
-register int T0 asm("r24");
-register int T1 asm("r25");
-register int A0 asm("r26");
+register unsigned int T0 asm("r24");
+register unsigned int T1 asm("r25");
+register unsigned int A0 asm("r26");
 register struct CPUX86State *env asm("r27");
-#define FORCE_RET() asm volatile ("blr");
 #endif
 #ifdef __arm__
-register int T0 asm("r4");
-register int T1 asm("r5");
-register int A0 asm("r6");
+register unsigned int T0 asm("r4");
+register unsigned int T1 asm("r5");
+register unsigned int A0 asm("r6");
 register struct CPUX86State *env asm("r7");
-#define FORCE_RET() asm volatile ("mov pc, lr");
 #endif
 #ifdef __mips__
-register int T0 asm("s0");
-register int T1 asm("s1");
-register int A0 asm("s2");
+register unsigned int T0 asm("s0");
+register unsigned int T1 asm("s1");
+register unsigned int A0 asm("s2");
 register struct CPUX86State *env asm("s3");
-#define FORCE_RET() asm volatile ("jr $31");
 #endif
 #ifdef __sparc__
-register int T0 asm("l0");
-register int T1 asm("l1");
-register int A0 asm("l2");
+register unsigned int T0 asm("l0");
+register unsigned int T1 asm("l1");
+register unsigned int A0 asm("l2");
 register struct CPUX86State *env asm("l3");
-#define FORCE_RET() asm volatile ("retl ; nop");
 #endif
 
+/* force GCC to generate only one epilog at the end of the function */
+#define FORCE_RET() asm volatile ("");
+
 #ifndef OPPROTO
 #define OPPROTO
 #endif
@@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void)
     CC_DST = T0;
 }
 
-void OPPROTO op_adcl_T0_T1_cc(void)
-{
-    CC_SRC = T0;
-    T0 = T0 + T1 + cc_table[CC_OP].compute_c();
-    CC_DST = T0;
-}
-
-void OPPROTO op_sbbl_T0_T1_cc(void)
-{
-    CC_SRC = T0;
-    T0 = T0 - T1 - cc_table[CC_OP].compute_c();
-    CC_DST = T0;
-}
-
 void OPPROTO op_andl_T0_T1_cc(void)
 {
     T0 &= T1;
@@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void)
 
 void OPPROTO op_incl_T0_cc(void)
 {
+    CC_SRC = cc_table[CC_OP].compute_c();
     T0++;
     CC_DST = T0;
 }
 
 void OPPROTO op_decl_T0_cc(void)
 {
+    CC_SRC = cc_table[CC_OP].compute_c();
     T0--;
     CC_DST = T0;
 }
@@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void)
     CC_DST = T0 & T1;
 }
 
+void OPPROTO op_bswapl_T0(void)
+{
+    T0 = bswap32(T0);
+}
+
 /* multiply/divide */
 void OPPROTO op_mulb_AL_T0(void)
 {
@@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void)
 void OPPROTO op_imull_T0_T1(void)
 {
     int64_t res;
-    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1);
+    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
     T0 = res;
     CC_SRC = (res != (int32_t)res);
 }
@@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void)
 void OPPROTO op_idivl_EAX_T0(void)
 {
     int den, q, r;
-    int16_t num;
+    int64_t num;
     
     num = EAX | ((uint64_t)EDX << 32);
-    den = (int16_t)T0;
+    den = T0;
     q = (num / den);
     r = (num % den);
     EAX = q;
@@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void)
     A0 = PARAM1;
 }
 
+void OPPROTO op_addl_A0_im(void)
+{
+    A0 += PARAM1;
+}
+
+void OPPROTO op_andl_A0_ffff(void)
+{
+    A0 = A0 & 0xffff;
+}
+
 /* memory access */
 
 void OPPROTO op_ldub_T0_A0(void)
@@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void)
     stl((uint8_t *)A0, T0);
 }
 
-/* jumps */
+/* used for bit operations */
+
+void OPPROTO op_add_bitw_A0_T1(void)
+{
+    A0 += ((int32_t)T1 >> 4) << 1;
+}
+
+void OPPROTO op_add_bitl_A0_T1(void)
+{
+    A0 += ((int32_t)T1 >> 5) << 2;
+}
 
 /* indirect jump */
 
@@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = {
     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
 
+    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
+    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
+    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
+
     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
     
+    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
+    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
+    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
+    
     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
     
-    [CC_OP_INCB] = { compute_all_incb, compute_c_incb },
-    [CC_OP_INCW] = { compute_all_incw, compute_c_incw },
+    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
+    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
     
-    [CC_OP_DECB] = { compute_all_decb, compute_c_incb },
-    [CC_OP_DECW] = { compute_all_decw, compute_c_incw },
+    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
+    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
     
-    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
-    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
+    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
+    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
+
+    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
+    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
+    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
 };
 
 /* floating point support */
@@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void)
     helper_fcos();
 }
 
+void OPPROTO op_fnstsw_A0(void)
+{
+    int fpus;
+    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+    stw((void *)A0, fpus);
+}
+
+void OPPROTO op_fnstcw_A0(void)
+{
+    stw((void *)A0, env->fpuc);
+}
+
+void OPPROTO op_fldcw_A0(void)
+{
+    int rnd_type;
+    env->fpuc = lduw((void *)A0);
+    /* set rounding mode */
+    switch(env->fpuc & RC_MASK) {
+    default:
+    case RC_NEAR:
+        rnd_type = FE_TONEAREST;
+        break;
+    case RC_DOWN:
+        rnd_type = FE_DOWNWARD;
+        break;
+    case RC_UP:
+        rnd_type = FE_UPWARD;
+        break;
+    case RC_CHOP:
+        rnd_type = FE_TOWARDZERO;
+        break;
+    }
+    fesetround(rnd_type);
+}
+
 /* main execution loop */
 uint8_t code_gen_buffer[65536];
 
@@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = {
     "ADDB",
     "ADDW",
     "ADDL",
+    "ADCB",
+    "ADCW",
+    "ADCL",
     "SUBB",
     "SUBW",
     "SUBL",
+    "SBBB",
+    "SBBW",
+    "SBBL",
     "LOGICB",
     "LOGICW",
     "LOGICL",
@@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = {
     "SHLB",
     "SHLW",
     "SHLL",
+    "SARB",
+    "SARW",
+    "SARL",
 };
 #endif
 
@@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1)
         for(;;) {
 #ifdef DEBUG_EXEC
             if (loglevel) {
+                int eflags;
+                eflags = cc_table[CC_OP].compute_all();
+                eflags |= (DF & DIRECTION_FLAG);
                 fprintf(logfile, 
                         "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
-                        "ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n"
-                        "CCS=%08x CCD=%08x CCOP=%s\n",
+                        "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
+                        "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
                         env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
                         env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
-                        env->cc_src, env->cc_dst, cc_op_str[env->cc_op]);
+                        env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
+                        eflags & DIRECTION_FLAG ? 'D' : '-',
+                        eflags & CC_O ? 'O' : '-',
+                        eflags & CC_S ? 'S' : '-',
+                        eflags & CC_Z ? 'Z' : '-',
+                        eflags & CC_A ? 'A' : '-',
+                        eflags & CC_P ? 'P' : '-',
+                        eflags & CC_C ? 'C' : '-'
+                        );
             }
 #endif
             cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
