mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-27 01:29:29 +00:00
Translate LMW, STMW and DCBZ instructions.
This commit is contained in:
parent
b0aae35951
commit
619aa9b319
|
@ -1261,6 +1261,13 @@ void OPPROTO op_nego_T0(void)
|
|||
T0 = -T0;
|
||||
}
|
||||
|
||||
void OPPROTO op_dcbz_T0(void)
|
||||
{
|
||||
T0 &= -32; // align T0 on cache line boundaries
|
||||
uint64 * block = (uint64 *) vm_do_get_real_address(T0);
|
||||
block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible call to next basic block without going
|
||||
* through register state restore & full cache lookup
|
||||
|
@ -1278,6 +1285,70 @@ void OPPROTO op_jump_next_A0(void)
|
|||
dyngen_barrier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load/store multiple
|
||||
**/
|
||||
|
||||
template< int N >
|
||||
static inline void do_lmw(void)
|
||||
{
|
||||
CPU->gpr(N) = vm_read_memory_4(T0);
|
||||
T0 += 4;
|
||||
do_lmw<N + 1>();
|
||||
}
|
||||
|
||||
template<>
|
||||
static inline void do_lmw<31>(void)
|
||||
{
|
||||
CPU->gpr(31) = vm_read_memory_4(T0);
|
||||
}
|
||||
|
||||
template<>
|
||||
static inline void do_lmw<32>(void)
|
||||
{
|
||||
for (uint32 r = PARAM1, ad = T0; r <= 31; r++, ad += 4)
|
||||
CPU->gpr(r) = vm_read_memory_4(ad);
|
||||
dyngen_barrier();
|
||||
}
|
||||
|
||||
template< int N >
|
||||
static inline void do_stmw(void)
|
||||
{
|
||||
vm_write_memory_4(T0, CPU->gpr(N));
|
||||
T0 += 4;
|
||||
do_stmw<N + 1>();
|
||||
}
|
||||
|
||||
template<>
|
||||
static inline void do_stmw<31>(void)
|
||||
{
|
||||
vm_write_memory_4(T0, CPU->gpr(31));
|
||||
}
|
||||
|
||||
template<>
|
||||
static inline void do_stmw<32>(void)
|
||||
{
|
||||
for (uint32 r = PARAM1, ad = T0; r <= 31; r++, ad += 4)
|
||||
vm_write_memory_4(ad, CPU->gpr(r));
|
||||
dyngen_barrier();
|
||||
}
|
||||
|
||||
#define im 32
|
||||
#define DEFINE_OP(N) \
|
||||
void op_lmw_T0_## N(void) { do_lmw <N>(); } \
|
||||
void op_stmw_T0_##N(void) { do_stmw<N>(); }
|
||||
|
||||
DEFINE_OP(im);
|
||||
DEFINE_OP(26);
|
||||
DEFINE_OP(27);
|
||||
DEFINE_OP(28);
|
||||
DEFINE_OP(29);
|
||||
DEFINE_OP(30);
|
||||
DEFINE_OP(31);
|
||||
|
||||
#undef im
|
||||
#undef DEFINE_OP
|
||||
|
||||
/**
|
||||
* Load/store addresses to vector registers
|
||||
**/
|
||||
|
|
|
@ -125,6 +125,30 @@ void powerpc_dyngen::gen_mtcrf_T0_im(uint32 mask)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load/store multiple words
|
||||
**/
|
||||
|
||||
#define DEFINE_INSN(OP) \
|
||||
void powerpc_dyngen::gen_##OP##_T0(int r) \
|
||||
{ \
|
||||
switch (r) { \
|
||||
case 26: gen_op_##OP##_T0_26(); break; \
|
||||
case 27: gen_op_##OP##_T0_27(); break; \
|
||||
case 28: gen_op_##OP##_T0_28(); break; \
|
||||
case 29: gen_op_##OP##_T0_29(); break; \
|
||||
case 30: gen_op_##OP##_T0_30(); break; \
|
||||
case 31: gen_op_##OP##_T0_31(); break; \
|
||||
default: gen_op_##OP##_T0_im(r); break; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFINE_INSN(lmw);
|
||||
DEFINE_INSN(stmw);
|
||||
|
||||
#undef DEFINE_INSN
|
||||
|
||||
|
||||
/**
|
||||
* Load/store registers
|
||||
**/
|
||||
|
|
|
@ -66,6 +66,10 @@ public:
|
|||
void gen_store_F1_FPR(int i);
|
||||
void gen_store_F2_FPR(int i);
|
||||
|
||||
// Load/store multiple words
|
||||
void gen_lmw_T0(int r);
|
||||
void gen_stmw_T0(int r);
|
||||
|
||||
// Raw aliases
|
||||
#define DEFINE_ALIAS_RAW(NAME, PRE, POST, ARGLIST, ARGS) \
|
||||
void gen_##NAME ARGLIST { PRE; gen_op_##NAME ARGS; POST; }
|
||||
|
@ -83,6 +87,7 @@ public:
|
|||
// Misc instructions
|
||||
DEFINE_ALIAS(inc_32_mem,1);
|
||||
DEFINE_ALIAS(nego_T0,0);
|
||||
DEFINE_ALIAS(dcbz_T0,0);
|
||||
|
||||
// Condition registers
|
||||
DEFINE_ALIAS(load_T0_CR,0);
|
||||
|
|
|
@ -447,6 +447,22 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PPC_I(LMW): // Load Multiple Word
|
||||
case PPC_I(STMW): // Store Multiple Word
|
||||
{
|
||||
const int rA = rA_field::extract(opcode);
|
||||
if (rA == 0)
|
||||
dg.gen_mov_32_T0_im(operand_D::get(this, opcode));
|
||||
else {
|
||||
dg.gen_load_T0_GPR(rA);
|
||||
dg.gen_add_32_T0_im(operand_D::get(this, opcode));
|
||||
}
|
||||
switch (ii->mnemo) {
|
||||
case PPC_I(LMW): dg.gen_lmw_T0(rD_field::extract(opcode)); break;
|
||||
case PPC_I(STMW): dg.gen_stmw_T0(rS_field::extract(opcode)); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PPC_I(BC): // Branch Conditional
|
||||
{
|
||||
const int bo = BO_field::extract(opcode);
|
||||
|
@ -1044,6 +1060,20 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||
dg.gen_store_T0_GPR(rD_field::extract(opcode));
|
||||
break;
|
||||
}
|
||||
case PPC_I(DCBZ): // Data Cache Block Clear to Zero
|
||||
{
|
||||
const int rA = rA_field::extract(opcode);
|
||||
const int rB = rB_field::extract(opcode);
|
||||
if (rA == 0)
|
||||
dg.gen_load_T0_GPR(rB);
|
||||
else {
|
||||
dg.gen_load_T0_GPR(rA);
|
||||
dg.gen_load_T1_GPR(rB);
|
||||
dg.gen_add_32_T0_T1();
|
||||
}
|
||||
dg.gen_dcbz_T0();
|
||||
break;
|
||||
}
|
||||
case PPC_I(DCBA): // Data Cache Block Allocate
|
||||
case PPC_I(DCBF): // Data Cache Block Flush
|
||||
case PPC_I(DCBI): // Data Cache Block Invalidate
|
||||
|
|
Loading…
Reference in New Issue
Block a user