709 |
FORCE_RET(); |
FORCE_RET(); |
710 |
} |
} |
711 |
|
|
712 |
/* string ops */ |
#if defined(__powerpc__) |
713 |
|
|
714 |
|
/* on PowerPC we patch the jump instruction directly */ |
715 |
|
#define JUMP_TB(tbparam, n, eip)\ |
716 |
|
do {\ |
717 |
|
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\ |
718 |
|
asm volatile ("b %0" : : "i" (&__op_jmp ## n));\ |
719 |
|
label ## n:\ |
720 |
|
T0 = (long)(tbparam) + (n);\ |
721 |
|
EIP = eip;\ |
722 |
|
} while (0) |
723 |
|
|
724 |
|
#else |
725 |
|
|
726 |
|
/* jump to next block operations (more portable code, does not need |
727 |
|
cache flushing, but slower because of indirect jump) */ |
728 |
|
#define JUMP_TB(tbparam, n, eip)\ |
729 |
|
do {\ |
730 |
|
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\ |
731 |
|
goto *((TranslationBlock *)tbparam)->tb_next[n];\ |
732 |
|
label ## n:\ |
733 |
|
T0 = (long)(tbparam) + (n);\ |
734 |
|
EIP = eip;\ |
735 |
|
} while (0) |
736 |
|
|
737 |
|
#endif |
738 |
|
|
739 |
|
void OPPROTO op_jmp_tb_next(void) |
740 |
|
{ |
741 |
|
JUMP_TB(PARAM1, 0, PARAM2); |
742 |
|
} |
743 |
|
|
744 |
|
void OPPROTO op_movl_T0_0(void) |
745 |
|
{ |
746 |
|
T0 = 0; |
747 |
|
} |
748 |
|
|
749 |
|
/* multiple size ops */ |
750 |
|
|
751 |
#define ldul ldl |
#define ldul ldl |
752 |
|
|
1236 |
|
|
1237 |
/* flags handling */ |
/* flags handling */ |
1238 |
|
|
1239 |
/* slow jumps cases (compute x86 flags) */ |
/* slow jumps cases : in order to avoid calling a function with a |
1240 |
void OPPROTO op_jo_cc(void) |
pointer (which can generate a stack frame on PowerPC), we use |
1241 |
{ |
op_setcc to set T0 and then call op_jcc. */ |
1242 |
int eflags; |
void OPPROTO op_jcc(void) |
|
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) |
|
|
{ |
|
|
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) |
|
1243 |
{ |
{ |
1244 |
int eflags; |
if (T0) |
1245 |
eflags = cc_table[CC_OP].compute_all(); |
JUMP_TB(PARAM1, 0, PARAM2); |
|
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; |
|
1246 |
else |
else |
1247 |
EIP = PARAM2; |
JUMP_TB(PARAM1, 1, PARAM3); |
1248 |
FORCE_RET(); |
FORCE_RET(); |
1249 |
} |
} |
1250 |
|
|