qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [patch] Remove switch statements from op.c


From: Paul Brook
Subject: [Qemu-devel] [patch] Remove switch statements from op.c
Date: Sat, 23 Apr 2005 22:09:47 +0100
User-agent: KMail/1.7.2

The i386 target uses switch statements in op.c. GCC implements these with jump 
tables on arm hosts. Dyngen can't grok jump tables. There's no easy way to 
figure out what is a jump table entry and what is an instruction.

The attached patch replaces the switch statements with a direct table lookup.

Paul
Index: target-i386/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/op.c,v
retrieving revision 1.36
diff -u -p -r1.36 op.c
--- target-i386/op.c    20 Mar 2005 10:39:24 -0000      1.36
+++ target-i386/op.c    23 Apr 2005 20:59:45 -0000
@@ -1952,94 +1952,48 @@ void OPPROTO op_fxchg_ST0_STN(void)
 
 /* FPU operations */
 
+const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
+
 void OPPROTO op_fcom_ST0_FT0(void)
 {
-    int cc;
-    switch(floatx_compare(ST0, FT0, &env->fp_status)) {
-    case -1:
-        cc = 0x0100;
-        break;
-    case 0:
-        cc = 0x4000;
-        break;
-    case 1:
-        cc = 0x0000;
-        break;
-    case 2:
-    default:
-        cc = 0x4500;
-        break;
-    }
-    env->fpus = (env->fpus & ~0x4500) | cc;
+    int ret;
+
+    ret = floatx_compare(ST0, FT0, &env->fp_status);
+    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
     FORCE_RET();
 }
 
 void OPPROTO op_fucom_ST0_FT0(void)
 {
-    int cc;
-    switch(floatx_compare_quiet(ST0, FT0, &env->fp_status)) {
-    case -1:
-        cc = 0x0100;
-        break;
-    case 0:
-        cc = 0x4000;
-        break;
-    case 1:
-        cc = 0x0000;
-        break;
-    case 2:
-    default:
-        cc = 0x4500;
-        break;
-    }
-    env->fpus = (env->fpus & ~0x4500) | cc;
+    int ret;
+
+    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
+    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
     FORCE_RET();
 }
 
+const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
+
 void OPPROTO op_fcomi_ST0_FT0(void)
 {
-    int eflags, cc;
-    switch(floatx_compare(ST0, FT0, &env->fp_status)) {
-    case -1:
-        cc = CC_C;
-        break;
-    case 0:
-        cc = CC_Z;
-        break;
-    case 1:
-        cc = 0;
-        break;
-    case 2:
-    default:
-        cc = CC_Z | CC_P | CC_C;
-        break;
-    }
+    int eflags;
+    int ret;
+
+    ret = floatx_compare(ST0, FT0, &env->fp_status);
     eflags = cc_table[CC_OP].compute_all();
-    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | cc;
+    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
     CC_SRC = eflags;
     FORCE_RET();
 }
 
 void OPPROTO op_fucomi_ST0_FT0(void)
 {
-    int eflags, cc;
-    switch(floatx_compare_quiet(ST0, FT0, &env->fp_status)) {
-    case -1:
-        cc = CC_C;
-        break;
-    case 0:
-        cc = CC_Z;
-        break;
-    case 1:
-        cc = 0;
-        break;
-    case 2:
-    default:
-        cc = CC_Z | CC_P | CC_C;
-        break;
-    }
+    int eflags;
+    int ret;
+
+    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
     eflags = cc_table[CC_OP].compute_all();
-    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | cc;
+    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
     CC_SRC = eflags;
     FORCE_RET();
 }
Index: target-i386/ops_sse.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/ops_sse.h,v
retrieving revision 1.5
diff -u -p -r1.5 ops_sse.h
--- target-i386/ops_sse.h       20 Mar 2005 10:39:24 -0000      1.5
+++ target-i386/ops_sse.h       23 Apr 2005 20:59:45 -0000
@@ -1079,9 +1079,11 @@ SSE_OP_CMP(cmpnlt, FPU_CMPNLT)
 SSE_OP_CMP(cmpnle, FPU_CMPNLE)
 SSE_OP_CMP(cmpord, FPU_CMPORD)
 
+const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
+
 void OPPROTO op_ucomiss(void)
 {
-    int eflags;
+    int ret;
     float32 s0, s1;
     Reg *d, *s;
     d = (Reg *)((char *)env + PARAM1);
@@ -1089,28 +1091,14 @@ void OPPROTO op_ucomiss(void)
 
     s0 = d->XMM_S(0);
     s1 = s->XMM_S(0);
-    switch(float32_compare_quiet(s0, s1, &env->sse_status)) {
-    case -1:
-        eflags = CC_C;
-        break;
-    case 0:
-        eflags = CC_Z;
-        break;
-    case 1:
-        eflags = 0;
-        break;
-    case 2:
-    default:
-        eflags = CC_Z | CC_P | CC_C;
-        break;
-    }
-    CC_SRC = eflags;
+    ret = float32_compare_quiet(s0, s1, &env->sse_status);
+    CC_SRC = comis_eflags[ret + 1];
     FORCE_RET();
 }
 
 void OPPROTO op_comiss(void)
 {
-    int eflags;
+    int ret;
     float32 s0, s1;
     Reg *d, *s;
     d = (Reg *)((char *)env + PARAM1);
@@ -1118,28 +1106,14 @@ void OPPROTO op_comiss(void)
 
     s0 = d->XMM_S(0);
     s1 = s->XMM_S(0);
-    switch(float32_compare(s0, s1, &env->sse_status)) {
-    case -1:
-        eflags = CC_C;
-        break;
-    case 0:
-        eflags = CC_Z;
-        break;
-    case 1:
-        eflags = 0;
-        break;
-    case 2:
-    default:
-        eflags = CC_Z | CC_P | CC_C;
-        break;
-    }
-    CC_SRC = eflags;
+    ret = float32_compare(s0, s1, &env->sse_status);
+    CC_SRC = comis_eflags[ret + 1];
     FORCE_RET();
 }
 
 void OPPROTO op_ucomisd(void)
 {
-    int eflags;
+    int ret;
     float64 d0, d1;
     Reg *d, *s;
     d = (Reg *)((char *)env + PARAM1);
@@ -1147,28 +1121,14 @@ void OPPROTO op_ucomisd(void)
 
     d0 = d->XMM_D(0);
     d1 = s->XMM_D(0);
-    switch(float64_compare_quiet(d0, d1, &env->sse_status)) {
-    case -1:
-        eflags = CC_C;
-        break;
-    case 0:
-        eflags = CC_Z;
-        break;
-    case 1:
-        eflags = 0;
-        break;
-    case 2:
-    default:
-        eflags = CC_Z | CC_P | CC_C;
-        break;
-    }
-    CC_SRC = eflags;
+    ret = float64_compare_quiet(d0, d1, &env->sse_status);
+    CC_SRC = comis_eflags[ret + 1];
     FORCE_RET();
 }
 
 void OPPROTO op_comisd(void)
 {
-    int eflags;
+    int ret;
     float64 d0, d1;
     Reg *d, *s;
     d = (Reg *)((char *)env + PARAM1);
@@ -1176,22 +1136,8 @@ void OPPROTO op_comisd(void)
 
     d0 = d->XMM_D(0);
     d1 = s->XMM_D(0);
-    switch(float64_compare(d0, d1, &env->sse_status)) {
-    case -1:
-        eflags = CC_C;
-        break;
-    case 0:
-        eflags = CC_Z;
-        break;
-    case 1:
-        eflags = 0;
-        break;
-    case 2:
-    default:
-        eflags = CC_Z | CC_P | CC_C;
-        break;
-    }
-    CC_SRC = eflags;
+    ret = float64_compare(d0, d1, &env->sse_status);
+    CC_SRC = comis_eflags[ret + 1];
     FORCE_RET();
 }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]