Remove use of global register A0 (now aliased to T0). This makes it possible

to cache the CPU context pointer to a register and thus rendering generated
code CPU context independent. Not useful to SheepShaver, but it is for
another project for threads emulation on plain x86-32.

Note: AltiVec performance may drop a little on x86 but this will be restored
(and even improved) in the future.
This commit is contained in:
gbeauche 2006-07-09 12:15:48 +00:00
parent d0a64733ef
commit abc911eaa7
9 changed files with 290 additions and 443 deletions

View File

@ -397,8 +397,8 @@ int sheepshaver_cpu::compile1(codegen_context_t & cg_context)
if (!FN_field::test(opcode))
cg_context.done_compile = false;
else {
dg.gen_load_A0_LR();
dg.gen_set_PC_A0();
dg.gen_load_T0_LR_aligned();
dg.gen_set_PC_T0();
cg_context.done_compile = true;
}
break;
@ -408,8 +408,8 @@ int sheepshaver_cpu::compile1(codegen_context_t & cg_context)
if (!FN_field::test(opcode))
dg.gen_set_PC_im(cg_context.pc + 4);
else {
dg.gen_load_A0_LR();
dg.gen_set_PC_A0();
dg.gen_load_T0_LR_aligned();
dg.gen_set_PC_T0();
}
dg.gen_mov_32_T0_im(selector);
dg.gen_jmp(native_op_trampoline);

View File

@ -26,21 +26,13 @@
// We need at least 5 general purpose registers
struct basic_cpu;
#ifdef REG_CPU
register basic_cpu *CPU asm(REG_CPU);
#else
#define CPU ((basic_cpu *)CPUPARAM)
#endif
#define DYNGEN_DEFINE_GLOBAL_REGISTER(REG) \
register uintptr reg_##REG asm(REG_##REG); \
register uint32 REG asm(REG_##REG)
DYNGEN_DEFINE_GLOBAL_REGISTER(A0);
DYNGEN_DEFINE_GLOBAL_REGISTER(T0);
DYNGEN_DEFINE_GLOBAL_REGISTER(T1);
DYNGEN_DEFINE_GLOBAL_REGISTER(T2);
#ifdef REG_T3
DYNGEN_DEFINE_GLOBAL_REGISTER(T3);
#endif
register uintptr A##REG asm(REG_T##REG); \
register uint32 T##REG asm(REG_T##REG)
DYNGEN_DEFINE_GLOBAL_REGISTER(0);
DYNGEN_DEFINE_GLOBAL_REGISTER(1);
DYNGEN_DEFINE_GLOBAL_REGISTER(2);
/**
@ -65,6 +57,26 @@ DYNGEN_DEFINE_GLOBAL_REGISTER(T3);
* ALU operations
**/
// XXX update for new 64-bit arches
#if defined __x86_64__
#define DEFINE_REG(REG) asm volatile ("movabsq $__op_param1,%" REG_T##REG)
#else
#define DEFINE_REG(REG) A##REG = PARAM1
#endif
#define DEFINE_OP(REG) \
void OPPROTO op_mov_ad_A##REG##_im(void) \
{ \
DEFINE_REG(REG); \
}
DEFINE_OP(0);
DEFINE_OP(1);
DEFINE_OP(2);
#undef DEFINE_REG
#undef DEFINE_OP
#define DEFINE_OP(NAME, CODE) \
void OPPROTO op_##NAME(void) \
{ \
@ -75,76 +87,45 @@ void OPPROTO op_##NAME(void) \
DEFINE_OP(mov_32_T0_im, T0 = PARAM1);
DEFINE_OP(mov_32_T0_T1, T0 = T1);
DEFINE_OP(mov_32_T0_T2, T0 = T2);
DEFINE_OP(mov_32_T0_A0, T0 = A0);
DEFINE_OP(mov_32_T1_im, T1 = PARAM1);
DEFINE_OP(mov_32_T1_T0, T1 = T0);
DEFINE_OP(mov_32_T1_T2, T1 = T2);
DEFINE_OP(mov_32_T1_A0, T1 = A0);
DEFINE_OP(mov_32_T2_im, T2 = PARAM1);
DEFINE_OP(mov_32_T2_T1, T2 = T1);
DEFINE_OP(mov_32_T2_T0, T2 = T0);
DEFINE_OP(mov_32_T2_A0, T2 = A0);
DEFINE_OP(mov_32_A0_im, A0 = PARAM1);
DEFINE_OP(mov_32_A0_T0, A0 = T0);
DEFINE_OP(mov_32_A0_T1, A0 = T1);
DEFINE_OP(mov_32_A0_T2, A0 = T2);
DEFINE_OP(mov_32_T0_0, T0 = 0);
DEFINE_OP(mov_32_T1_0, T1 = 0);
DEFINE_OP(mov_32_T2_0, T2 = 0);
DEFINE_OP(mov_32_A0_0, A0 = 0);
#if SIZEOF_VOID_P == 8
#if defined(__x86_64__)
#define DEFINE_MOV_AD(REG) asm volatile ("movabsq $__op_param1,%" REG_##REG)
#else
#error "unsupported 64-bit value move in"
#endif
#else
#define DEFINE_MOV_AD(REG) REG = PARAM1
#endif
void OPPROTO op_mov_ad_T0_im(void) { DEFINE_MOV_AD(T0); }
void OPPROTO op_mov_ad_T1_im(void) { DEFINE_MOV_AD(T1); }
void OPPROTO op_mov_ad_T2_im(void) { DEFINE_MOV_AD(T2); }
void OPPROTO op_mov_ad_A0_im(void) { DEFINE_MOV_AD(A0); }
// Arithmetic operations
DEFINE_OP(add_32_T0_T2, T0 += T2);
DEFINE_OP(add_32_T0_T1, T0 += T1);
DEFINE_OP(add_32_T0_im, T0 += PARAM1);
DEFINE_OP(add_32_T0_1, T0 += 1);
DEFINE_OP(add_32_T0_2, T0 += 2);
DEFINE_OP(add_32_T0_4, T0 += 4);
DEFINE_OP(add_32_T0_8, T0 += 8);
DEFINE_OP(sub_32_T0_T2, T0 -= T2);
DEFINE_OP(sub_32_T0_T1, T0 -= T1);
DEFINE_OP(sub_32_T0_im, T0 -= PARAM1);
DEFINE_OP(sub_32_T0_1, T0 -= 1);
DEFINE_OP(sub_32_T0_2, T0 -= 2);
DEFINE_OP(sub_32_T0_4, T0 -= 4);
DEFINE_OP(sub_32_T0_8, T0 -= 8);
DEFINE_OP(add_32_T1_T2, T1 += T2);
DEFINE_OP(add_32_T1_T0, T1 += T0);
DEFINE_OP(add_32_T1_im, T1 += PARAM1);
DEFINE_OP(add_32_T1_1, T1 += 1);
DEFINE_OP(add_32_T1_2, T1 += 2);
DEFINE_OP(add_32_T1_4, T1 += 4);
DEFINE_OP(add_32_T1_8, T1 += 8);
DEFINE_OP(sub_32_T1_T2, T1 -= T2);
DEFINE_OP(sub_32_T1_T0, T1 -= T0);
DEFINE_OP(sub_32_T1_im, T1 -= PARAM1);
DEFINE_OP(sub_32_T1_1, T1 -= 1);
DEFINE_OP(sub_32_T1_2, T1 -= 2);
DEFINE_OP(sub_32_T1_4, T1 -= 4);
DEFINE_OP(sub_32_T1_8, T1 -= 8);
DEFINE_OP(add_32_A0_T1, A0 += T1);
DEFINE_OP(add_32_A0_im, A0 += PARAM1);
DEFINE_OP(add_32_A0_1, A0 += 1);
DEFINE_OP(add_32_A0_2, A0 += 2);
DEFINE_OP(add_32_A0_4, A0 += 4);
DEFINE_OP(add_32_A0_8, A0 += 8);
DEFINE_OP(sub_32_A0_T1, A0 -= T1);
DEFINE_OP(sub_32_A0_im, A0 -= PARAM1);
DEFINE_OP(sub_32_A0_1, A0 -= 1);
DEFINE_OP(sub_32_A0_2, A0 -= 2);
DEFINE_OP(sub_32_A0_4, A0 -= 4);
DEFINE_OP(sub_32_A0_8, A0 -= 8);
DEFINE_OP(umul_32_T0_T1, T0 = (uint32)T0 * (uint32)T1);
DEFINE_OP(smul_32_T0_T1, T0 = (int32)T0 * (int32)T1);
DEFINE_OP(udiv_32_T0_T1, T0 = do_udiv_32(T0, T1));
@ -197,28 +178,28 @@ DEFINE_OP(ze_8_32_T0, T0 = (uint32)(uint8)T0);
#define im PARAM1
#define DEFINE_OP(BITS,REG,SIZE,OFFSET) \
void OPPROTO op_load_u##BITS##_##REG##_A0_##OFFSET(void) \
void OPPROTO op_load_u##BITS##_##REG##_T1_##OFFSET(void) \
{ \
REG = (uint32)(uint##BITS)vm_read_memory_##SIZE(A0 + OFFSET); \
REG = (uint32)(uint##BITS)vm_read_memory_##SIZE(T1 + OFFSET); \
} \
void OPPROTO op_load_s##BITS##_##REG##_A0_##OFFSET(void) \
void OPPROTO op_load_s##BITS##_##REG##_T1_##OFFSET(void) \
{ \
REG = (int32)(int##BITS)vm_read_memory_##SIZE(A0 + OFFSET); \
REG = (int32)(int##BITS)vm_read_memory_##SIZE(T1 + OFFSET); \
} \
void OPPROTO op_store_##BITS##_##REG##_A0_##OFFSET(void) \
void OPPROTO op_store_##BITS##_##REG##_T1_##OFFSET(void) \
{ \
vm_write_memory_##SIZE(A0 + OFFSET, REG); \
vm_write_memory_##SIZE(T1 + OFFSET, REG); \
}
DEFINE_OP(32,T0,4,0);
DEFINE_OP(32,T0,4,im);
DEFINE_OP(32,T0,4,T1);
DEFINE_OP(32,T0,4,T2);
DEFINE_OP(16,T0,2,0);
DEFINE_OP(16,T0,2,im);
DEFINE_OP(16,T0,2,T1);
DEFINE_OP(16,T0,2,T2);
DEFINE_OP(8,T0,1,0);
DEFINE_OP(8,T0,1,im);
DEFINE_OP(8,T0,1,T1);
DEFINE_OP(8,T0,1,T2);
#undef im
#undef DEFINE_OP
@ -274,27 +255,13 @@ void OPPROTO op_execute(uint8 *entry_point, basic_cpu *this_cpu)
{
typedef void (*func_t)(void);
func_t func = (func_t)entry_point;
const int n_slots = 16 + 6; /* 16 stack slots + 6 VCPU registers */
const int n_slots = 16 + 4; /* 16 stack slots + 4 VCPU registers */
volatile uintptr stk[n_slots];
#ifdef REG_CPU
stk[n_slots - 1] = (uintptr)CPU;
stk[n_slots - 2] = A0;
stk[n_slots - 3] = A1;
stk[n_slots - 4] = A2;
CPU = this_cpu;
#endif
#ifdef REG_A0
stk[n_slots - 2] = reg_A0;
#endif
#ifdef REG_T0
stk[n_slots - 3] = reg_T0;
#endif
#ifdef REG_T1
stk[n_slots - 4] = reg_T1;
#endif
#ifdef REG_T2
stk[n_slots - 5] = reg_T2;
#endif
#ifdef REG_T3
stk[n_slots - 6] = reg_T3;
#endif
SLOW_DISPATCH(entry_point);
func(); // NOTE: never called, fake to make compiler save return point
#ifdef ASM_OP_EXEC_RETURN_INSN
@ -308,24 +275,10 @@ void OPPROTO op_execute(uint8 *entry_point, basic_cpu *this_cpu)
asm volatile (ASM_PREVIOUS_SECTION);
asm volatile ("1:");
#endif
#ifdef REG_T3
reg_T3 = stk[n_slots - 6];
#endif
#ifdef REG_T2
reg_T2 = stk[n_slots - 5];
#endif
#ifdef REG_T1
reg_T1 = stk[n_slots - 4];
#endif
#ifdef REG_T0
reg_T0 = stk[n_slots - 3];
#endif
#ifdef REG_A0
reg_A0 = stk[n_slots - 2];
#endif
#ifdef REG_CPU
A2 = stk[n_slots - 4];
A1 = stk[n_slots - 3];
A0 = stk[n_slots - 2];
CPU = (basic_cpu *)stk[n_slots - 1];
#endif
}
void OPPROTO op_jmp_slow(void)
@ -344,7 +297,7 @@ void OPPROTO op_jmp_fast(void)
void OPPROTO op_jmp_A0(void)
{
SLOW_DISPATCH(reg_A0);
SLOW_DISPATCH(A0);
}
// Register calling conventions based arches don't need a stack frame
@ -399,112 +352,123 @@ void OPPROTO NAME(void) \
DEFINE_OP(op_invoke, {
typedef void (*func_t)(void);
CALL(reg_A0,());
func_t func = (func_t)PARAM1;
CALL(func, ());
});
DEFINE_OP(op_invoke_T0, {
typedef void (*func_t)(uint32);
CALL(reg_A0,(T0));
func_t func = (func_t)PARAM1;
CALL(func, (T0));
});
DEFINE_OP(op_invoke_T0_T1, {
typedef void (*func_t)(uint32, uint32);
CALL(reg_A0,(T0, T1));
func_t func = (func_t)PARAM1;
CALL(func, (T0, T1));
});
DEFINE_OP(op_invoke_T0_T1_T2, {
typedef void (*func_t)(uint32, uint32, uint32);
CALL(reg_A0,(T0, T1, T2));
func_t func = (func_t)PARAM1;
CALL(func, (T0, T1, T2));
});
DEFINE_OP(op_invoke_T0_ret_T0, {
typedef uint32 (*func_t)(uint32);
T0 = CALL(reg_A0,(T0));
func_t func = (func_t)PARAM1;
T0 = CALL(func, (T0));
});
DEFINE_OP(op_invoke_im, {
typedef void (*func_t)(uint32);
CALL(reg_A0,(PARAM1));
func_t func = (func_t)PARAM1;
CALL(func, (PARAM2));
});
DEFINE_OP(op_invoke_CPU, {
typedef void (*func_t)(void *);
CALL(reg_A0,(CPU));
func_t func = (func_t)PARAM1;
CALL(func, (CPU));
});
DEFINE_OP(op_invoke_CPU_T0, {
typedef void (*func_t)(void *, uint32);
CALL(reg_A0,(CPU, T0));
func_t func = (func_t)PARAM1;
CALL(func, (CPU, T0));
});
DEFINE_OP(op_invoke_CPU_im, {
typedef void (*func_t)(void *, uint32);
CALL(reg_A0,(CPU, PARAM1));
func_t func = (func_t)PARAM1;
CALL(func, (CPU, PARAM2));
});
DEFINE_OP(op_invoke_CPU_im_im, {
typedef void (*func_t)(void *, uint32, uint32);
CALL(reg_A0,(CPU, PARAM1, PARAM2));
func_t func = (func_t)PARAM1;
CALL(func, (CPU, PARAM2, PARAM3));
});
DEFINE_OP(op_invoke_CPU_A0_ret_A0, {
typedef void *(*func_t)(void *, uintptr);
func_t func = (func_t)PARAM1;
A0 = (uintptr)CALL(func, (CPU, A0));
});
DEFINE_OP(op_invoke_direct, {
typedef void (*func_t)(void);
CALL(PARAM1,());
CALL(PARAM1, ());
});
DEFINE_OP(op_invoke_direct_T0, {
typedef void (*func_t)(uint32);
CALL(PARAM1,(T0));
CALL(PARAM1, (T0));
});
DEFINE_OP(op_invoke_direct_T0_T1, {
typedef void (*func_t)(uint32, uint32);
CALL(PARAM1,(T0, T1));
CALL(PARAM1, (T0, T1));
});
DEFINE_OP(op_invoke_direct_T0_T1_T2, {
typedef void (*func_t)(uint32, uint32, uint32);
CALL(PARAM1,(T0, T1, T2));
CALL(PARAM1, (T0, T1, T2));
});
DEFINE_OP(op_invoke_direct_T0_ret_T0, {
typedef uint32 (*func_t)(uint32);
T0 = CALL(PARAM1,(T0));
T0 = CALL(PARAM1, (T0));
});
DEFINE_OP(op_invoke_direct_im, {
typedef void (*func_t)(uint32);
CALL(PARAM1,(PARAM2));
CALL(PARAM1, (PARAM2));
});
DEFINE_OP(op_invoke_direct_CPU, {
typedef void (*func_t)(void *);
CALL(PARAM1,(CPU));
CALL(PARAM1, (CPU));
});
DEFINE_OP(op_invoke_direct_CPU_T0, {
typedef void (*func_t)(void *, uint32);
CALL(PARAM1,(CPU, T0));
CALL(PARAM1, (CPU, T0));
});
DEFINE_OP(op_invoke_direct_CPU_im, {
typedef void (*func_t)(void *, uint32);
CALL(PARAM1,(CPU, PARAM2));
CALL(PARAM1, (CPU, PARAM2));
});
DEFINE_OP(op_invoke_direct_CPU_im_im, {
typedef void (*func_t)(void *, uint32, uint32);
CALL(PARAM1,(CPU, PARAM2, PARAM3));
CALL(PARAM1, (CPU, PARAM2, PARAM3));
});
DEFINE_OP(op_invoke_CPU_T0_ret_A0, {
DEFINE_OP(op_invoke_direct_CPU_A0_ret_A0, {
typedef void *(*func_t)(void *, uintptr);
reg_A0 = (uintptr)CALL(reg_A0,(CPU, reg_T0));
});
DEFINE_OP(op_invoke_direct_CPU_T0_ret_A0, {
typedef void *(*func_t)(void *, uintptr);
reg_A0 = (uintptr)CALL(PARAM1,(CPU, reg_T0));
A0 = (uintptr)CALL(PARAM1, (CPU, A0));
});
#undef DEFINE_OP

View File

@ -48,121 +48,33 @@ basic_dyngen::basic_dyngen(dyngen_cpu_base cpu, int cache_size)
void
basic_dyngen::gen_invoke(void (*func)())
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke();
}
uintptr funcptr = (uintptr)func;
if (direct_call_possible(funcptr))
gen_op_invoke_direct(funcptr);
else
gen_op_invoke(funcptr);
}
void
basic_dyngen::gen_invoke_T0(void (*func)(uint32))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_T0((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_T0();
}
#define DEFINE_INVOKE(NAME, ARGS, IARGS) \
void \
basic_dyngen::gen_invoke_##NAME ARGS \
{ \
uintptr funcptr = (uintptr)func; \
if (direct_call_possible(funcptr)) \
gen_op_invoke_direct_##NAME IARGS; \
else \
gen_op_invoke_##NAME IARGS; \
}
void
basic_dyngen::gen_invoke_T0_T1(void (*func)(uint32, uint32))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_T0_T1((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_T0_T1();
}
}
void
basic_dyngen::gen_invoke_T0_T1_T2(void (*func)(uint32, uint32, uint32))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_T0_T1_T2((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_T0_T1_T2();
}
}
void
basic_dyngen::gen_invoke_T0_ret_T0(uint32 (*func)(uint32))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_T0_ret_T0((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_T0_ret_T0();
}
}
void
basic_dyngen::gen_invoke_im(void (*func)(uint32), uint32 value)
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_im((uintptr)func, value);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_im(value);
}
}
void
basic_dyngen::gen_invoke_CPU(void (*func)(dyngen_cpu_base))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_CPU((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_CPU();
}
}
void
basic_dyngen::gen_invoke_CPU_T0(void (*func)(dyngen_cpu_base, uint32))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_CPU_T0((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_CPU_T0();
}
}
void
basic_dyngen::gen_invoke_CPU_im(void (*func)(dyngen_cpu_base, uint32), uint32 value)
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_CPU_im((uintptr)func, value);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_CPU_im(value);
}
}
void
basic_dyngen::gen_invoke_CPU_im_im(void (*func)(dyngen_cpu_base, uint32, uint32), uint32 param1, uint32 param2)
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_CPU_im_im((uintptr)func, param1, param2);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_CPU_im_im(param1, param2);
}
}
void
basic_dyngen::gen_invoke_CPU_T0_ret_A0(void *(*func)(dyngen_cpu_base))
{
if (direct_call_possible((uintptr)func))
gen_op_invoke_direct_CPU_T0_ret_A0((uintptr)func);
else {
gen_op_mov_ad_A0_im((uintptr)func);
gen_op_invoke_CPU_T0_ret_A0();
}
}
DEFINE_INVOKE(T0, (void (*func)(uint32)), (funcptr));
DEFINE_INVOKE(T0_T1, (void (*func)(uint32, uint32)), (funcptr));
DEFINE_INVOKE(T0_T1_T2, (void (*func)(uint32, uint32, uint32)), (funcptr));
DEFINE_INVOKE(T0_ret_T0, (uint32 (*func)(uint32)), (funcptr));
DEFINE_INVOKE(im, (void (*func)(uint32), uint32 value), (funcptr, value));
DEFINE_INVOKE(CPU, (void (*func)(dyngen_cpu_base)), (funcptr));
DEFINE_INVOKE(CPU_T0, (void (*func)(dyngen_cpu_base, uint32)), (funcptr));
DEFINE_INVOKE(CPU_im, (void (*func)(dyngen_cpu_base, uint32), uint32 value), (funcptr, value));
DEFINE_INVOKE(CPU_im_im, (void (*func)(dyngen_cpu_base, uint32, uint32), uint32 param1, uint32 param2), (funcptr, param1, param2));
DEFINE_INVOKE(CPU_A0_ret_A0, (void *(*func)(dyngen_cpu_base)), (funcptr));
#undef DEFINE_INVOKE

View File

@ -111,7 +111,7 @@ public:
void gen_invoke_CPU_T0(void (*func)(dyngen_cpu_base, uint32));
void gen_invoke_CPU_im(void (*func)(dyngen_cpu_base, uint32), uint32 value);
void gen_invoke_CPU_im_im(void (*func)(dyngen_cpu_base, uint32, uint32), uint32 param1, uint32 param2);
void gen_invoke_CPU_T0_ret_A0(void *(*func)(dyngen_cpu_base));
void gen_invoke_CPU_A0_ret_A0(void *(*func)(dyngen_cpu_base));
// Raw aliases
#define DEFINE_ALIAS_RAW(NAME, ARGLIST, ARGS) \
@ -127,37 +127,29 @@ public:
void gen_mov_32_T0_im(int32 value);
DEFINE_ALIAS(mov_32_T0_T1,0);
DEFINE_ALIAS(mov_32_T0_T2,0);
DEFINE_ALIAS(mov_32_T0_A0,0);
void gen_mov_32_T1_im(int32 value);
DEFINE_ALIAS(mov_32_T1_T0,0);
DEFINE_ALIAS(mov_32_T1_T2,0);
DEFINE_ALIAS(mov_32_T1_A0,0);
void gen_mov_32_T2_im(int32 value);
DEFINE_ALIAS(mov_32_T2_T0,0);
DEFINE_ALIAS(mov_32_T2_T1,0);
DEFINE_ALIAS(mov_32_T2_A0,0);
void gen_mov_32_A0_im(int32 value);
DEFINE_ALIAS(mov_32_A0_T0,0);
DEFINE_ALIAS(mov_32_A0_T1,0);
DEFINE_ALIAS(mov_32_A0_T2,0);
DEFINE_ALIAS(mov_ad_T0_im,1);
DEFINE_ALIAS(mov_ad_T1_im,1);
DEFINE_ALIAS(mov_ad_T2_im,1);
DEFINE_ALIAS(mov_ad_A0_im,1);
DEFINE_ALIAS(mov_ad_A1_im,1);
DEFINE_ALIAS(mov_ad_A2_im,1);
// Arithmetic operations
DEFINE_ALIAS(add_32_T0_T1,0);
DEFINE_ALIAS(add_32_T0_T2,0);
void gen_add_32_T0_im(int32 value);
DEFINE_ALIAS(sub_32_T0_T1,0);
DEFINE_ALIAS(sub_32_T0_T2,0);
void gen_sub_32_T0_im(int32 value);
DEFINE_ALIAS(add_32_T1_T0,0);
DEFINE_ALIAS(add_32_T1_T2,0);
void gen_add_32_T1_im(int32 value);
DEFINE_ALIAS(sub_32_T1_T0,0);
DEFINE_ALIAS(sub_32_T1_T2,0);
void gen_sub_32_T1_im(int32 value);
DEFINE_ALIAS(add_32_A0_T1,0);
void gen_add_32_A0_im(int32 value);
DEFINE_ALIAS(sub_32_A0_T1,0);
void gen_sub_32_A0_im(int32 value);
DEFINE_ALIAS(umul_32_T0_T1,0);
DEFINE_ALIAS(smul_32_T0_T1,0);
DEFINE_ALIAS(udiv_32_T0_T1,0);
@ -207,24 +199,24 @@ public:
DEFINE_ALIAS(jmp_A0,0);
// Load/Store instructions
DEFINE_ALIAS(load_u32_T0_A0_T1,0);
void gen_load_u32_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_s32_T0_A0_T1,0);
void gen_load_s32_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_u16_T0_A0_T1,0);
void gen_load_u16_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_s16_T0_A0_T1,0);
void gen_load_s16_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_u8_T0_A0_T1,0);
void gen_load_u8_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_s8_T0_A0_T1,0);
void gen_load_s8_T0_A0_im(int32 offset);
DEFINE_ALIAS(store_32_T0_A0_T1,0);
void gen_store_32_T0_A0_im(int32 offset);
DEFINE_ALIAS(store_16_T0_A0_T1,0);
void gen_store_16_T0_A0_im(int32 offset);
DEFINE_ALIAS(store_8_T0_A0_T1,0);
void gen_store_8_T0_A0_im(int32 offset);
DEFINE_ALIAS(load_u32_T0_T1_T2,0);
void gen_load_u32_T0_T1_im(int32 offset);
DEFINE_ALIAS(load_s32_T0_T1_T2,0);
void gen_load_s32_T0_T1_im(int32 offset);
DEFINE_ALIAS(load_u16_T0_T1_T2,0);
void gen_load_u16_T0_T1_im(int32 offset);
DEFINE_ALIAS(load_s16_T0_T1_T2,0);
void gen_load_s16_T0_T1_im(int32 offset);
DEFINE_ALIAS(load_u8_T0_T1_T2,0);
void gen_load_u8_T0_T1_im(int32 offset);
DEFINE_ALIAS(load_s8_T0_T1_T2,0);
void gen_load_s8_T0_T1_im(int32 offset);
DEFINE_ALIAS(store_32_T0_T1_T2,0);
void gen_store_32_T0_T1_im(int32 offset);
DEFINE_ALIAS(store_16_T0_T1_T2,0);
void gen_store_16_T0_T1_im(int32 offset);
DEFINE_ALIAS(store_8_T0_T1_T2,0);
void gen_store_8_T0_T1_im(int32 offset);
#undef DEFINE_ALIAS
#undef DEFINE_ALIAS_0
@ -335,13 +327,12 @@ basic_dyngen::gen_mov_32_##REG##_im(int32 value) \
DEFINE_OP(T0);
DEFINE_OP(T1);
DEFINE_OP(T2);
DEFINE_OP(A0);
#undef DEFINE_OP
#define DEFINE_OP(OP,REG) \
inline void \
basic_dyngen::gen_##OP##_32_##REG##_im(int32 value) \
basic_dyngen::gen_##OP##_32_##REG##_im(int32 value) \
{ \
if (value == 0) return; \
else if (value == 1) gen_op_##OP##_32_##REG##_1(); \
@ -351,23 +342,21 @@ basic_dyngen::gen_##OP##_32_##REG##_im(int32 value) \
else gen_op_##OP##_32_##REG##_im(value); \
}
DEFINE_OP(add,A0);
DEFINE_OP(add,T0);
DEFINE_OP(add,T1);
DEFINE_OP(sub,A0);
DEFINE_OP(sub,T0);
DEFINE_OP(sub,T1);
#undef DEFINE_OP
#define DEFINE_OP(NAME,REG,SIZE) \
inline void \
basic_dyngen::gen_##NAME##_##SIZE##_##REG##_A0_im(int32 offset) \
{ \
if (offset == 0) \
gen_op_##NAME##_##SIZE##_##REG##_A0_0(); \
else \
gen_op_##NAME##_##SIZE##_##REG##_A0_im(offset); \
#define DEFINE_OP(NAME,REG,SIZE) \
inline void \
basic_dyngen::gen_##NAME##_##SIZE##_##REG##_T1_im(int32 offset) \
{ \
if (offset == 0) \
gen_op_##NAME##_##SIZE##_##REG##_T1_0(); \
else \
gen_op_##NAME##_##SIZE##_##REG##_T1_im(offset); \
}
DEFINE_OP(load,T0,u32);

View File

@ -27,8 +27,8 @@
#include "cpu/jit/jit-target-dispatch.h"
/* define virtual register set */
#define REG_A0 AREG0
#define REG_A0_ID AREG0_ID
#define REG_CPU AREG0
#define REG_CPU_ID AREG0_ID
#define REG_T0 AREG1
#define REG_T0_ID AREG1_ID
#define REG_T1 AREG2
@ -39,10 +39,6 @@
#define REG_T3 AREG4
#define REG_T3_ID AREG4_ID
#endif
#ifdef AREG5
#define REG_CPU AREG5
#define REG_CPU_ID AREG5_ID
#endif
#ifdef FREG0
#define REG_F0 FREG0
#define REG_F0_ID FREG0_ID

View File

@ -28,43 +28,41 @@
#include "cpu/ppc/ppc-operations.hpp"
// We need at least 4 general purpose registers
#ifdef REG_CPU
register struct powerpc_cpu *CPU asm(REG_CPU);
#else
#define CPU ((powerpc_cpu *)CPUPARAM)
#endif
#define DYNGEN_DEFINE_GLOBAL_REGISTER(REG) \
register uintptr reg_##REG asm(REG_##REG); \
register uint32 REG asm(REG_##REG)
DYNGEN_DEFINE_GLOBAL_REGISTER(A0);
DYNGEN_DEFINE_GLOBAL_REGISTER(T0);
DYNGEN_DEFINE_GLOBAL_REGISTER(T1);
DYNGEN_DEFINE_GLOBAL_REGISTER(T2);
register uintptr A##REG asm(REG_T##REG); \
register uint32 T##REG asm(REG_T##REG)
DYNGEN_DEFINE_GLOBAL_REGISTER(0);
DYNGEN_DEFINE_GLOBAL_REGISTER(1);
DYNGEN_DEFINE_GLOBAL_REGISTER(2);
#ifdef REG_T3
DYNGEN_DEFINE_GLOBAL_REGISTER(T3);
DYNGEN_DEFINE_GLOBAL_REGISTER(3);
#else
#define A3 powerpc_dyngen_helper::reg_T3()
#define T3 powerpc_dyngen_helper::reg_T3()
#endif
// Floating-point registers
#define FPREG(X) ((powerpc_fpr *)(X))
#define F0 FPREG(reg_T0)->d
#define F0_dw FPREG(reg_T0)->j
#define F1 FPREG(reg_T1)->d
#define F1_dw FPREG(reg_T1)->j
#define F2 FPREG(reg_T2)->d
#define F2_dw FPREG(reg_T2)->j
#define F0 FPREG(A0)->d
#define F0_dw FPREG(A0)->j
#define F1 FPREG(A1)->d
#define F1_dw FPREG(A1)->j
#define F2 FPREG(A2)->d
#define F2_dw FPREG(A2)->j
#define FD powerpc_dyngen_helper::fp_result()
#define FD_dw powerpc_dyngen_helper::fp_result_dw()
// Vector registers
#define VREG(X) ((powerpc_vr *)(X))[0]
#define VD VREG(reg_VD)
#define reg_VD reg_A0
#define V0 VREG(reg_V0)
#define reg_V0 reg_T0
#define reg_V0 A0
#define V1 VREG(reg_V1)
#define reg_V1 reg_T1
#define reg_V1 A1
#define V2 VREG(reg_V2)
#define reg_V2 reg_T2
#define reg_V2 A2
#define VD VREG(reg_VD)
#define reg_VD A3
/**
* Helper class to access protected CPU context
@ -96,6 +94,10 @@ struct powerpc_dyngen_helper {
static uint64 & fp_result_dw() { return CPU->fp_result_dw(); }
static inline void set_cr(int crfd, int v) { CPU->cr().set(crfd, v); }
#ifndef REG_T3
static inline uintptr & reg_T3() { return CPU->codegen.reg_T3; }
#endif
static inline powerpc_block_info *find_block(uint32 pc) { return CPU->block_cache.fast_find(pc); }
};
@ -118,7 +120,6 @@ void OPPROTO op_store_##REG##_GPR##N(void) \
CPU->gpr(N) = REG; \
}
#define DEFINE_REG(N) \
DEFINE_OP(A0,N); \
DEFINE_OP(T0,N); \
DEFINE_OP(T1,N); \
DEFINE_OP(T2,N);
@ -167,7 +168,7 @@ DEFINE_REG(31);
#define DEFINE_OP(REG, N) \
void OPPROTO op_load_F##REG##_FPR##N(void) \
{ \
reg_T##REG = (uintptr)&CPU->fpr(N); \
A##REG = (uintptr)&CPU->fpr(N); \
} \
void OPPROTO op_store_F##REG##_FPR##N(void) \
{ \
@ -254,26 +255,26 @@ DEFINE_REG(31);
#define im PARAM1
#define DEFINE_OP(OFFSET) \
void OPPROTO op_load_double_FD_A0_##OFFSET(void) \
void OPPROTO op_load_double_FD_T1_##OFFSET(void) \
{ \
do_load_double(FD, A0 + OFFSET); \
do_load_double(FD, T1 + OFFSET); \
} \
void OPPROTO op_load_single_FD_A0_##OFFSET(void) \
void OPPROTO op_load_single_FD_T1_##OFFSET(void) \
{ \
do_load_single(FD, A0 + OFFSET); \
do_load_single(FD, T1 + OFFSET); \
} \
void OPPROTO op_store_double_F0_A0_##OFFSET(void) \
void OPPROTO op_store_double_F0_T1_##OFFSET(void) \
{ \
do_store_double(F0, A0 + OFFSET); \
do_store_double(F0, T1 + OFFSET); \
} \
void OPPROTO op_store_single_F0_A0_##OFFSET(void) \
void OPPROTO op_store_single_F0_T1_##OFFSET(void) \
{ \
do_store_single(F0, A0 + OFFSET); \
do_store_single(F0, T1 + OFFSET); \
}
DEFINE_OP(0);
DEFINE_OP(im);
DEFINE_OP(T1);
DEFINE_OP(T2);
#undef im
#undef DEFINE_OP
@ -516,9 +517,9 @@ void OPPROTO op_set_PC_im(void)
powerpc_dyngen_helper::set_pc(PARAM1);
}
void OPPROTO op_set_PC_A0(void)
void OPPROTO op_set_PC_T0(void)
{
powerpc_dyngen_helper::set_pc(A0);
powerpc_dyngen_helper::set_pc(T0);
}
void OPPROTO op_inc_PC(void)
@ -546,29 +547,19 @@ void OPPROTO op_store_T0_CTR(void)
powerpc_dyngen_helper::set_ctr(T0);
}
void OPPROTO op_store_T1_CTR(void)
{
powerpc_dyngen_helper::set_ctr(T1);
}
void OPPROTO op_load_T1_PC(void)
{
T1 = powerpc_dyngen_helper::get_pc();
}
void OPPROTO op_store_im_LR(void)
{
powerpc_dyngen_helper::set_lr(PARAM1);
}
void OPPROTO op_load_A0_CTR(void)
void OPPROTO op_load_T0_CTR_aligned(void)
{
A0 = powerpc_dyngen_helper::get_ctr() & -4;
T0 = powerpc_dyngen_helper::get_ctr() & -4;
}
void OPPROTO op_load_A0_LR(void)
void OPPROTO op_load_T0_LR_aligned(void)
{
A0 = powerpc_dyngen_helper::get_lr() & -4;
T0 = powerpc_dyngen_helper::get_lr() & -4;
}
void OPPROTO op_spcflags_init(void)
@ -610,21 +601,21 @@ static inline void do_prep_branch_bo(void)
if (BO_CONDITIONAL_BRANCH(bo)) {
if (BO_BRANCH_IF_TRUE(bo))
cond_ok = T0;
cond_ok = T1;
else
cond_ok = !T0;
cond_ok = !T1;
}
if (BO_DECREMENT_CTR(bo)) {
T1 = powerpc_dyngen_helper::get_ctr() - 1;
powerpc_dyngen_helper::set_ctr(T1);
T2 = powerpc_dyngen_helper::get_ctr() - 1;
powerpc_dyngen_helper::set_ctr(T2);
if (BO_BRANCH_IF_CTR_ZERO(bo))
ctr_ok = !T1;
ctr_ok = !T2;
else
ctr_ok = T1;
ctr_ok = T2;
}
T0 = ctr_ok && cond_ok;
T1 = ctr_ok && cond_ok;
dyngen_barrier();
}
@ -660,14 +651,14 @@ static inline void do_execute_branch_1(uint32 tpc)
dyngen_barrier();
}
void op_branch_1_A0(void)
void op_branch_1_T0(void)
{
do_execute_branch_1<0>(A0);
do_execute_branch_1<0>(T0);
}
void op_branch_chain_1_A0(void)
void op_branch_chain_1_T0(void)
{
do_execute_branch_1<1>(A0);
do_execute_branch_1<1>(T0);
}
void op_branch_1_im(void)
@ -685,32 +676,32 @@ static inline void do_execute_branch_2(uint32 tpc, uint32 npc)
{
#ifdef DYNGEN_FAST_DISPATCH
if (chain) {
T1 = powerpc_dyngen_helper::spcflags().get();
if (T0) {
FAST_COMPARE_SPECFLAGS_DISPATCH(T1, __op_jmp0);
A0 = tpc;
T2 = powerpc_dyngen_helper::spcflags().get();
if (T1) {
FAST_COMPARE_SPECFLAGS_DISPATCH(T2, __op_jmp0);
T0 = tpc;
}
else {
FAST_COMPARE_SPECFLAGS_DISPATCH(T1, __op_jmp1);
A0 = npc;
FAST_COMPARE_SPECFLAGS_DISPATCH(T2, __op_jmp1);
T0 = npc;
}
}
else
#endif
A0 = T0 ? tpc : npc;
powerpc_dyngen_helper::set_pc(A0);
T0 = T1 ? tpc : npc;
powerpc_dyngen_helper::set_pc(T0);
dyngen_barrier();
}
void op_branch_2_A0_im(void)
void op_branch_2_T0_im(void)
{
do_execute_branch_2<0>(A0, PARAM1);
do_execute_branch_2<0>(T0, PARAM1);
}
void op_branch_chain_2_A0_im(void)
void op_branch_chain_2_T0_im(void)
{
do_execute_branch_2<1>(A0, PARAM1);
do_execute_branch_2<1>(T0, PARAM1);
}
void op_branch_2_im_im(void)
@ -1371,7 +1362,7 @@ void OPPROTO op_jump_next_A0(void)
{
// Make sure there is no pending interrupt request
if (likely(powerpc_dyngen_helper::spcflags().empty())) {
powerpc_block_info *bi = (powerpc_block_info *)reg_A0;
powerpc_block_info *bi = (powerpc_block_info *)A0;
uint32 pc = powerpc_dyngen_helper::get_pc();
if (likely(bi->pc == pc) || likely((bi = powerpc_dyngen_helper::find_block(pc)) != NULL))
goto *(bi->entry_point);
@ -1447,17 +1438,16 @@ DEFINE_OP(31);
* Load/store addresses to vector registers
**/
#define reg_TD reg_A0
#define DEFINE_OP(REG, N) \
void OPPROTO op_load_ad_V##REG##_VR##N(void) \
{ \
reg_T##REG = (uintptr)&CPU->vr(N); \
reg_V##REG = (uintptr)&CPU->vr(N); \
}
#define DEFINE_REG(N) \
DEFINE_OP(D,N); \
DEFINE_OP(0,N); \
DEFINE_OP(1,N); \
DEFINE_OP(2,N); \
DEFINE_OP(2,N)
DEFINE_REG(0);
DEFINE_REG(1);
@ -1494,7 +1484,7 @@ DEFINE_REG(31);
#undef DEFINE_REG
#undef DEFINE_OP
#undef reg_TD
#undef AD
void op_load_word_VD_T0(void)
{

View File

@ -219,11 +219,9 @@ void powerpc_dyngen::gen_##OP##_##REG##_##REGT(int i) \
}
// General purpose registers
DEFINE_INSN(load, A0, GPR);
DEFINE_INSN(load, T0, GPR);
DEFINE_INSN(load, T1, GPR);
DEFINE_INSN(load, T2, GPR);
DEFINE_INSN(store, A0, GPR);
DEFINE_INSN(store, T0, GPR);
DEFINE_INSN(store, T1, GPR);
DEFINE_INSN(store, T2, GPR);
@ -249,12 +247,12 @@ DEFINE_INSN(store, T1, crb);
// Floating point load store
#define DEFINE_OP(NAME, REG, TYPE) \
void powerpc_dyngen::gen_##NAME##_##TYPE##_##REG##_A0_im(int32 offset) \
void powerpc_dyngen::gen_##NAME##_##TYPE##_##REG##_T1_im(int32 offset) \
{ \
if (offset == 0) \
gen_op_##NAME##_##TYPE##_##REG##_A0_0(); \
gen_op_##NAME##_##TYPE##_##REG##_T1_0(); \
else \
gen_op_##NAME##_##TYPE##_##REG##_A0_im(offset); \
gen_op_##NAME##_##TYPE##_##REG##_T1_im(offset); \
}
DEFINE_OP(load, FD, double);
@ -287,10 +285,8 @@ DEFINE_INSN(store, T0);
void powerpc_dyngen::gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_chaining)
{
if (BO_CONDITIONAL_BRANCH(bo)) {
gen_load_T0_CR();
gen_and_32_T0_im(1 << (31 - bi));
}
if (BO_CONDITIONAL_BRANCH(bo))
gen_load_T1_crb(bi);
switch (bo >> 1) {
#define _(A,B,C,D) (((A) << 3)| ((B) << 2) | ((C) << 1) | (D))
@ -324,9 +320,9 @@ void powerpc_dyngen::gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_
}
else {
if (direct_chaining)
gen_op_branch_chain_2_A0_im(npc);
gen_op_branch_chain_2_T0_im(npc);
else
gen_op_branch_2_A0_im(npc);
gen_op_branch_2_T0_im(npc);
}
}
else {
@ -339,9 +335,9 @@ void powerpc_dyngen::gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_
}
else {
if (direct_chaining)
gen_op_branch_chain_1_A0();
gen_op_branch_chain_1_T0();
else
gen_op_branch_1_A0();
gen_op_branch_1_T0();
}
}
}

View File

@ -38,6 +38,10 @@ class powerpc_dyngen
# include "ppc-dyngen-ops.hpp"
#endif
#ifndef REG_T3
uintptr reg_T3;
#endif
public:
// Make rc_cache accessible to codegen helper
@ -50,11 +54,9 @@ public:
powerpc_dyngen(dyngen_cpu_base cpu, int cache_size = -1);
// Load/store registers
void gen_load_A0_GPR(int i);
void gen_load_T0_GPR(int i);
void gen_load_T1_GPR(int i);
void gen_load_T2_GPR(int i);
void gen_store_A0_GPR(int i);
void gen_store_T0_GPR(int i);
void gen_store_T1_GPR(int i);
void gen_store_T2_GPR(int i);
@ -108,16 +110,14 @@ public:
DEFINE_ALIAS(load_T0_PC,0);
DEFINE_ALIAS(store_T0_PC,0);
DEFINE_ALIAS(set_PC_im,1);
DEFINE_ALIAS(set_PC_A0,0);
DEFINE_ALIAS(set_PC_T0,0);
DEFINE_ALIAS(inc_PC,1);
DEFINE_ALIAS(load_T0_LR,0);
DEFINE_ALIAS(store_T0_LR,0);
DEFINE_ALIAS(load_T0_CTR,0);
DEFINE_ALIAS(load_A0_CTR,0);
DEFINE_ALIAS(load_T0_CTR_aligned,0);
DEFINE_ALIAS(store_T0_CTR,0);
DEFINE_ALIAS(store_T1_CTR,0);
DEFINE_ALIAS(load_T1_PC,0);
DEFINE_ALIAS(load_A0_LR,0);
DEFINE_ALIAS(load_T0_LR_aligned,0);
DEFINE_ALIAS(store_im_LR,1);
DEFINE_ALIAS(spcflags_init,1);
@ -211,14 +211,14 @@ public:
DEFINE_ALIAS(fnmsubs_FD_F0_F1_F2,0);
// Load/store floating point data
DEFINE_ALIAS(load_double_FD_A0_T1,0);
void gen_load_double_FD_A0_im(int32 offset);
DEFINE_ALIAS(load_single_FD_A0_T1,0);
void gen_load_single_FD_A0_im(int32 offset);
DEFINE_ALIAS(store_double_F0_A0_T1,0);
void gen_store_double_F0_A0_im(int32 offset);
DEFINE_ALIAS(store_single_F0_A0_T1,0);
void gen_store_single_F0_A0_im(int32 offset);
DEFINE_ALIAS(load_double_FD_T1_T2,0);
void gen_load_double_FD_T1_im(int32 offset);
DEFINE_ALIAS(load_single_FD_T1_T2,0);
void gen_load_single_FD_T1_im(int32 offset);
DEFINE_ALIAS(store_double_F0_T1_T2,0);
void gen_store_double_F0_T1_im(int32 offset);
DEFINE_ALIAS(store_single_F0_T1_T2,0);
void gen_store_single_F0_T1_im(int32 offset);
// Branch instructions
void gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_chaining);

View File

@ -288,43 +288,43 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Extract RZ operand
const int rA = rA_field::extract(opcode);
if (rA == 0 && !op.mem.do_update)
dg.gen_mov_32_A0_im(0);
dg.gen_mov_32_T1_im(0);
else
dg.gen_load_A0_GPR(rA);
dg.gen_load_T1_GPR(rA);
// Extract index operand
if (op.mem.do_indexed)
dg.gen_load_T1_GPR(rB_field::extract(opcode));
dg.gen_load_T2_GPR(rB_field::extract(opcode));
switch (op.mem.size) {
case 1:
if (op.mem.do_indexed)
dg.gen_load_u8_T0_A0_T1();
dg.gen_load_u8_T0_T1_T2();
else
dg.gen_load_u8_T0_A0_im(operand_D::get(this, opcode));
dg.gen_load_u8_T0_T1_im(operand_D::get(this, opcode));
break;
case 2:
if (op.mem.do_indexed) {
if (op.mem.sign)
dg.gen_load_s16_T0_A0_T1();
dg.gen_load_s16_T0_T1_T2();
else
dg.gen_load_u16_T0_A0_T1();
dg.gen_load_u16_T0_T1_T2();
}
else {
const int32 offset = operand_D::get(this, opcode);
if (op.mem.sign)
dg.gen_load_s16_T0_A0_im(offset);
dg.gen_load_s16_T0_T1_im(offset);
else
dg.gen_load_u16_T0_A0_im(offset);
dg.gen_load_u16_T0_T1_im(offset);
}
break;
case 4:
if (op.mem.do_indexed) {
dg.gen_load_u32_T0_A0_T1();
dg.gen_load_u32_T0_T1_T2();
}
else {
const int32 offset = operand_D::get(this, opcode);
dg.gen_load_u32_T0_A0_im(offset);
dg.gen_load_u32_T0_T1_im(offset);
}
break;
}
@ -335,10 +335,10 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Update RA
if (op.mem.do_update) {
if (op.mem.do_indexed)
dg.gen_add_32_A0_T1();
dg.gen_add_32_T1_T2();
else
dg.gen_add_32_A0_im(operand_D::get(this, opcode));
dg.gen_store_A0_GPR(rA);
dg.gen_add_32_T1_im(operand_D::get(this, opcode));
dg.gen_store_T1_GPR(rA);
}
break;
}
@ -407,13 +407,13 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Extract RZ operand
const int rA = rA_field::extract(opcode);
if (rA == 0 && !op.mem.do_update)
dg.gen_mov_32_A0_im(0);
dg.gen_mov_32_T1_im(0);
else
dg.gen_load_A0_GPR(rA);
dg.gen_load_T1_GPR(rA);
// Extract index operand
if (op.mem.do_indexed)
dg.gen_load_T1_GPR(rB_field::extract(opcode));
dg.gen_load_T2_GPR(rB_field::extract(opcode));
// Load register to commit to memory
dg.gen_load_T0_GPR(rS_field::extract(opcode));
@ -421,31 +421,31 @@ powerpc_cpu::compile_block(uint32 entry_point)
switch (op.mem.size) {
case 1:
if (op.mem.do_indexed)
dg.gen_store_8_T0_A0_T1();
dg.gen_store_8_T0_T1_T2();
else
dg.gen_store_8_T0_A0_im(operand_D::get(this, opcode));
dg.gen_store_8_T0_T1_im(operand_D::get(this, opcode));
break;
case 2:
if (op.mem.do_indexed)
dg.gen_store_16_T0_A0_T1();
dg.gen_store_16_T0_T1_T2();
else
dg.gen_store_16_T0_A0_im(operand_D::get(this, opcode));
dg.gen_store_16_T0_T1_im(operand_D::get(this, opcode));
break;
case 4:
if (op.mem.do_indexed)
dg.gen_store_32_T0_A0_T1();
dg.gen_store_32_T0_T1_T2();
else
dg.gen_store_32_T0_A0_im(operand_D::get(this, opcode));
dg.gen_store_32_T0_T1_im(operand_D::get(this, opcode));
break;
}
// Update RA
if (op.mem.do_update) {
if (op.mem.do_indexed)
dg.gen_add_32_A0_T1();
dg.gen_add_32_T1_T2();
else
dg.gen_add_32_A0_im(operand_D::get(this, opcode));
dg.gen_store_A0_GPR(rA);
dg.gen_add_32_T1_im(operand_D::get(this, opcode));
dg.gen_store_T1_GPR(rA);
}
break;
}
@ -500,10 +500,10 @@ powerpc_cpu::compile_block(uint32 entry_point)
break;
}
case PPC_I(BCCTR): // Branch Conditional to Count Register
dg.gen_load_A0_CTR();
dg.gen_load_T0_CTR_aligned();
goto do_branch;
case PPC_I(BCLR): // Branch Conditional to Link Register
dg.gen_load_A0_LR();
dg.gen_load_T0_LR_aligned();
goto do_branch;
{
do_branch:
@ -1156,26 +1156,26 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Extract RZ operand
const int rA = rA_field::extract(opcode);
if (rA == 0 && !op.mem.do_update)
dg.gen_mov_32_A0_im(0);
dg.gen_mov_32_T1_im(0);
else
dg.gen_load_A0_GPR(rA);
dg.gen_load_T1_GPR(rA);
// Extract index operand
if (op.mem.do_indexed)
dg.gen_load_T1_GPR(rB_field::extract(opcode));
dg.gen_load_T2_GPR(rB_field::extract(opcode));
// Load floating point data
if (op.mem.size == 8) {
if (op.mem.do_indexed)
dg.gen_load_double_FD_A0_T1();
dg.gen_load_double_FD_T1_T2();
else
dg.gen_load_double_FD_A0_im(operand_D::get(this, opcode));
dg.gen_load_double_FD_T1_im(operand_D::get(this, opcode));
}
else {
if (op.mem.do_indexed)
dg.gen_load_single_FD_A0_T1();
dg.gen_load_single_FD_T1_T2();
else
dg.gen_load_single_FD_A0_im(operand_D::get(this, opcode));
dg.gen_load_single_FD_T1_im(operand_D::get(this, opcode));
}
// Commit result
@ -1184,10 +1184,10 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Update RA
if (op.mem.do_update) {
if (op.mem.do_indexed)
dg.gen_add_32_A0_T1();
dg.gen_add_32_T1_T2();
else
dg.gen_add_32_A0_im(operand_D::get(this, opcode));
dg.gen_store_A0_GPR(rA);
dg.gen_add_32_T1_im(operand_D::get(this, opcode));
dg.gen_store_T1_GPR(rA);
}
break;
}
@ -1236,13 +1236,13 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Extract RZ operand
const int rA = rA_field::extract(opcode);
if (rA == 0 && !op.mem.do_update)
dg.gen_mov_32_A0_im(0);
dg.gen_mov_32_T1_im(0);
else
dg.gen_load_A0_GPR(rA);
dg.gen_load_T1_GPR(rA);
// Extract index operand
if (op.mem.do_indexed)
dg.gen_load_T1_GPR(rB_field::extract(opcode));
dg.gen_load_T2_GPR(rB_field::extract(opcode));
// Load register to commit to memory
dg.gen_load_F0_FPR(frS_field::extract(opcode));
@ -1250,24 +1250,24 @@ powerpc_cpu::compile_block(uint32 entry_point)
// Store floating point data
if (op.mem.size == 8) {
if (op.mem.do_indexed)
dg.gen_store_double_F0_A0_T1();
dg.gen_store_double_F0_T1_T2();
else
dg.gen_store_double_F0_A0_im(operand_D::get(this, opcode));
dg.gen_store_double_F0_T1_im(operand_D::get(this, opcode));
}
else {
if (op.mem.do_indexed)
dg.gen_store_single_F0_A0_T1();
dg.gen_store_single_F0_T1_T2();
else
dg.gen_store_single_F0_A0_im(operand_D::get(this, opcode));
dg.gen_store_single_F0_T1_im(operand_D::get(this, opcode));
}
// Update RA
if (op.mem.do_update) {
if (op.mem.do_indexed)
dg.gen_add_32_A0_T1();
dg.gen_add_32_T1_T2();
else
dg.gen_add_32_A0_im(operand_D::get(this, opcode));
dg.gen_store_A0_GPR(rA);
dg.gen_add_32_T1_im(operand_D::get(this, opcode));
dg.gen_store_T1_GPR(rA);
}
break;
}
@ -1555,8 +1555,8 @@ powerpc_cpu::compile_block(uint32 entry_point)
for (int i = 0; i < block_info::MAX_TARGETS; i++) {
if (bi->li[i].jmp_pc != block_info::INVALID_PC) {
uint8 *p = dg.gen_align(16);
dg.gen_mov_ad_T0_im(((uintptr)bi) | i);
dg.gen_invoke_CPU_T0_ret_A0(func);
dg.gen_mov_ad_A0_im(((uintptr)bi) | i);
dg.gen_invoke_CPU_A0_ret_A0(func);
dg.gen_jmp_A0();
assert(dg.jmp_addr[i] != NULL);
bi->li[i].jmp_addr = dg.jmp_addr[i];