Translate LMW, STMW and DCBZ instructions.

This commit is contained in:
gbeauche 2004-05-23 16:34:38 +00:00
parent b0aae35951
commit 619aa9b319
4 changed files with 130 additions and 0 deletions

View File

@ -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
**/

View File

@ -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
**/

View File

@ -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);

View File

@ -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