aboutsummaryrefslogtreecommitdiff
path: root/op-i386.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-05-25 16:46:15 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-05-25 16:46:15 +0000
commitd4e8164f7e9342d692c1d6f1c848ed05f8007ece (patch)
treeca8f3b46553b2674eb5ab3297b39db75d78ba4d4 /op-i386.c
parent08351fb37ae0abe0d0a025ad67709f1f1fd63d59 (diff)
direct chaining for PowerPC and i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@183 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'op-i386.c')
-rw-r--r--op-i386.c128
1 files changed, 45 insertions, 83 deletions
diff --git a/op-i386.c b/op-i386.c
index 64cbe708a5..cfae103639 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -709,7 +709,44 @@ void OPPROTO op_cmpxchg8b(void)
FORCE_RET();
}
-/* string ops */
+#if defined(__powerpc__)
+
+/* on PowerPC we patch the jump instruction directly */
+#define JUMP_TB(tbparam, n, eip)\
+do {\
+ static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
+ asm volatile ("b %0" : : "i" (&__op_jmp ## n));\
+label ## n:\
+ T0 = (long)(tbparam) + (n);\
+ EIP = eip;\
+} while (0)
+
+#else
+
+/* jump to next block operations (more portable code, does not need
+ cache flushing, but slower because of indirect jump) */
+#define JUMP_TB(tbparam, n, eip)\
+do {\
+ static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
+ goto *((TranslationBlock *)tbparam)->tb_next[n];\
+label ## n:\
+ T0 = (long)(tbparam) + (n);\
+ EIP = eip;\
+} while (0)
+
+#endif
+
+void OPPROTO op_jmp_tb_next(void)
+{
+ JUMP_TB(PARAM1, 0, PARAM2);
+}
+
+void OPPROTO op_movl_T0_0(void)
+{
+ T0 = 0;
+}
+
+/* multiple size ops */
#define ldul ldl
@@ -1199,90 +1236,15 @@ void OPPROTO op_lar(void)
/* flags handling */
-/* slow jumps cases (compute x86 flags) */
-void OPPROTO op_jo_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (eflags & CC_O)
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jb_cc(void)
-{
- if (cc_table[CC_OP].compute_c())
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jz_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (eflags & CC_Z)
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jbe_cc(void)
+/* slow jumps cases : in order to avoid calling a function with a
+ pointer (which can generate a stack frame on PowerPC), we use
+ op_setcc to set T0 and then call op_jcc. */
+void OPPROTO op_jcc(void)
{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (eflags & (CC_Z | CC_C))
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_js_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (eflags & CC_S)
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jp_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (eflags & CC_P)
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jl_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if ((eflags ^ (eflags >> 4)) & 0x80)
- EIP = PARAM1;
- else
- EIP = PARAM2;
- FORCE_RET();
-}
-
-void OPPROTO op_jle_cc(void)
-{
- int eflags;
- eflags = cc_table[CC_OP].compute_all();
- if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
- EIP = PARAM1;
+ if (T0)
+ JUMP_TB(PARAM1, 0, PARAM2);
else
- EIP = PARAM2;
+ JUMP_TB(PARAM1, 1, PARAM3);
FORCE_RET();
}