mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-20 15:29:48 +00:00
Fix decrement the CTR, then branch conditional if decremented CTR != 0.
Remove CR cache for now. Remove BC & MODE_68K hacks for SheepShaver, that was a colateral damage of wrong branch emulation of the former.
This commit is contained in:
parent
dc79320904
commit
04214f3820
@ -216,7 +216,11 @@ public:
|
|||||||
|
|
||||||
// Initialization & finalization
|
// Initialization & finalization
|
||||||
void initialize();
|
void initialize();
|
||||||
|
#ifdef SHEEPSHAVER
|
||||||
powerpc_cpu();
|
powerpc_cpu();
|
||||||
|
#else
|
||||||
|
powerpc_cpu(task_struct *parent_task);
|
||||||
|
#endif
|
||||||
~powerpc_cpu();
|
~powerpc_cpu();
|
||||||
|
|
||||||
// Handle flight recorder
|
// Handle flight recorder
|
||||||
|
@ -36,7 +36,6 @@ register struct powerpc_cpu *CPU asm(REG_CPU);
|
|||||||
register uint32 A0 asm(REG_A0);
|
register uint32 A0 asm(REG_A0);
|
||||||
register uint32 T0 asm(REG_T0);
|
register uint32 T0 asm(REG_T0);
|
||||||
register uint32 T1 asm(REG_T1);
|
register uint32 T1 asm(REG_T1);
|
||||||
register uint32 RC asm(REG_T2);
|
|
||||||
|
|
||||||
// Semantic action templates
|
// Semantic action templates
|
||||||
#define DYNGEN_OPS
|
#define DYNGEN_OPS
|
||||||
@ -134,25 +133,16 @@ void OPPROTO op_store_T0_CR(void)
|
|||||||
powerpc_dyngen_helper::set_cr(T0);
|
powerpc_dyngen_helper::set_cr(T0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_load_T0_XER(void)
|
|
||||||
{
|
|
||||||
T0 = powerpc_dyngen_helper::get_xer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_store_T0_XER(void)
|
|
||||||
{
|
|
||||||
powerpc_dyngen_helper::set_xer(T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_OP(REG, N) \
|
#define DEFINE_OP(REG, N) \
|
||||||
void OPPROTO op_load_##REG##_crb##N(void) \
|
void OPPROTO op_load_##REG##_crb##N(void) \
|
||||||
{ \
|
{ \
|
||||||
REG = bit_field<N,N>::extract(powerpc_dyngen_helper::get_cr()); \
|
const uint32 cr = powerpc_dyngen_helper::get_cr(); \
|
||||||
|
REG = (cr >> (31 - N)) & 1; \
|
||||||
} \
|
} \
|
||||||
void OPPROTO op_store_##REG##_crb##N(void) \
|
void OPPROTO op_store_##REG##_crb##N(void) \
|
||||||
{ \
|
{ \
|
||||||
uint32 cr = powerpc_dyngen_helper::get_cr(); \
|
uint32 cr = powerpc_dyngen_helper::get_cr() & ~(1 << (31 - N)); \
|
||||||
bit_field<N,N>::insert(cr, REG); \
|
cr |= ((REG & 1) << (31 - N)); \
|
||||||
powerpc_dyngen_helper::set_cr(cr); \
|
powerpc_dyngen_helper::set_cr(cr); \
|
||||||
}
|
}
|
||||||
#define DEFINE_REG(N) \
|
#define DEFINE_REG(N) \
|
||||||
@ -195,48 +185,49 @@ DEFINE_REG(31);
|
|||||||
#undef DEFINE_REG
|
#undef DEFINE_REG
|
||||||
#undef DEFINE_OP
|
#undef DEFINE_OP
|
||||||
|
|
||||||
#define DEFINE_OP(CRF, REG) \
|
#define DEFINE_OP(CRF, REG) \
|
||||||
void OPPROTO op_load_##REG##_cr##CRF(void) \
|
void OPPROTO op_load_##REG##_cr##CRF(void) \
|
||||||
{ \
|
{ \
|
||||||
REG = powerpc_dyngen_helper::cr().get(CRF); \
|
REG = powerpc_dyngen_helper::cr().get(CRF); \
|
||||||
} \
|
} \
|
||||||
void OPPROTO op_store_##REG##_cr##CRF(void) \
|
void OPPROTO op_store_##REG##_cr##CRF(void) \
|
||||||
{ \
|
{ \
|
||||||
powerpc_dyngen_helper::cr().set(CRF, REG); \
|
powerpc_dyngen_helper::cr().set(CRF, REG); \
|
||||||
} \
|
|
||||||
void OPPROTO op_commit_so_cache_cr##CRF(void) \
|
|
||||||
{ \
|
|
||||||
uint32 cr = powerpc_dyngen_helper::get_cr(); \
|
|
||||||
const uint32 cr_mask = CR_SO_field<CRF>::mask(); \
|
|
||||||
cr = (cr & ~cr_mask) | ((RC << (28 - 4 * CRF)) & cr_mask); \
|
|
||||||
powerpc_dyngen_helper::set_cr(cr); \
|
|
||||||
} \
|
|
||||||
void OPPROTO op_commit_rc_cache_cr##CRF(void) \
|
|
||||||
{ \
|
|
||||||
uint32 cr = powerpc_dyngen_helper::get_cr(); \
|
|
||||||
const uint32 cr_mask = (CR_LT_field<CRF>::mask() | \
|
|
||||||
CR_GT_field<CRF>::mask() | \
|
|
||||||
CR_EQ_field<CRF>::mask()); \
|
|
||||||
cr = (cr & ~cr_mask) | ((RC << (28 - 4 * CRF)) & cr_mask); \
|
|
||||||
powerpc_dyngen_helper::set_cr(cr); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_OP(0, RC);
|
DEFINE_OP(0, T0);
|
||||||
DEFINE_OP(1, RC);
|
DEFINE_OP(1, T0);
|
||||||
DEFINE_OP(2, RC);
|
DEFINE_OP(2, T0);
|
||||||
DEFINE_OP(3, RC);
|
DEFINE_OP(3, T0);
|
||||||
DEFINE_OP(4, RC);
|
DEFINE_OP(4, T0);
|
||||||
DEFINE_OP(5, RC);
|
DEFINE_OP(5, T0);
|
||||||
DEFINE_OP(6, RC);
|
DEFINE_OP(6, T0);
|
||||||
DEFINE_OP(7, RC);
|
DEFINE_OP(7, T0);
|
||||||
|
|
||||||
#undef DEFINE_OP
|
#undef DEFINE_OP
|
||||||
|
|
||||||
|
void OPPROTO op_mtcrf_T0_im(void)
|
||||||
|
{
|
||||||
|
const uint32 mask = PARAM1;
|
||||||
|
const uint32 cr = powerpc_dyngen_helper::get_cr();
|
||||||
|
powerpc_dyngen_helper::set_cr((cr & ~mask) | (T0 & mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special purpose registers
|
* Special purpose registers
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
void OPPROTO op_load_T0_XER(void)
|
||||||
|
{
|
||||||
|
T0 = powerpc_dyngen_helper::get_xer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_store_T0_XER(void)
|
||||||
|
{
|
||||||
|
powerpc_dyngen_helper::set_xer(T0);
|
||||||
|
}
|
||||||
|
|
||||||
void OPPROTO op_load_T0_PC(void)
|
void OPPROTO op_load_T0_PC(void)
|
||||||
{
|
{
|
||||||
T0 = powerpc_dyngen_helper::get_pc();
|
T0 = powerpc_dyngen_helper::get_pc();
|
||||||
@ -346,36 +337,18 @@ static inline void do_execute_branch(uint32 tpc, uint32 npc)
|
|||||||
dyngen_barrier();
|
dyngen_barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int crb >
|
struct branch_if_T0_condition {
|
||||||
struct RC_comparator {
|
|
||||||
static inline bool test() {
|
static inline bool test() {
|
||||||
return (RC & crb);
|
return T0 != 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template< bool br_true, class comparator >
|
struct branch_if_not_T0_condition {
|
||||||
struct bool_condition {
|
|
||||||
static inline bool test() {
|
static inline bool test() {
|
||||||
return comparator::test();
|
return T0 == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template< class comparator >
|
|
||||||
struct bool_condition< false, comparator > {
|
|
||||||
static inline bool test() {
|
|
||||||
return !comparator::test();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef bool_condition< true, RC_comparator<8> > blt_condition;
|
|
||||||
typedef bool_condition<false, RC_comparator<8> > bnlt_condition;
|
|
||||||
typedef bool_condition< true, RC_comparator<4> > bgt_condition;
|
|
||||||
typedef bool_condition<false, RC_comparator<4> > bngt_condition;
|
|
||||||
typedef bool_condition< true, RC_comparator<2> > beq_condition;
|
|
||||||
typedef bool_condition<false, RC_comparator<2> > bneq_condition;
|
|
||||||
typedef bool_condition< true, RC_comparator<1> > bso_condition;
|
|
||||||
typedef bool_condition<false, RC_comparator<1> > bnso_condition;
|
|
||||||
|
|
||||||
struct ctr_0x_condition {
|
struct ctr_0x_condition {
|
||||||
static inline bool test() {
|
static inline bool test() {
|
||||||
return true;
|
return true;
|
||||||
@ -399,7 +372,7 @@ struct ctr_11_condition {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_OP_CTR(COND,CTR) \
|
#define DEFINE_OP_CTR(COND,CTR) \
|
||||||
void OPPROTO op_##COND##_##CTR(void) \
|
void OPPROTO op_##COND##_ctr_##CTR(void) \
|
||||||
{ \
|
{ \
|
||||||
do_execute_branch<COND##_condition, ctr_##CTR##_condition>(A0, PARAM1); \
|
do_execute_branch<COND##_condition, ctr_##CTR##_condition>(A0, PARAM1); \
|
||||||
}
|
}
|
||||||
@ -408,40 +381,93 @@ DEFINE_OP_CTR(COND,0x); \
|
|||||||
DEFINE_OP_CTR(COND,10); \
|
DEFINE_OP_CTR(COND,10); \
|
||||||
DEFINE_OP_CTR(COND,11);
|
DEFINE_OP_CTR(COND,11);
|
||||||
|
|
||||||
DEFINE_OP(blt);
|
DEFINE_OP(branch_if_T0);
|
||||||
DEFINE_OP(bgt);
|
DEFINE_OP(branch_if_not_T0);
|
||||||
DEFINE_OP(beq);
|
|
||||||
DEFINE_OP(bso);
|
|
||||||
DEFINE_OP(bnlt);
|
|
||||||
DEFINE_OP(bngt);
|
|
||||||
DEFINE_OP(bneq);
|
|
||||||
DEFINE_OP(bnso);
|
|
||||||
|
|
||||||
#undef DEFINE_OP
|
#undef DEFINE_OP
|
||||||
#undef DEFINE_OP_CTR
|
#undef DEFINE_OP_CTR
|
||||||
|
|
||||||
|
template< int bo >
|
||||||
|
static inline void do_execute_branch_bo(uint32 tpc, uint32 npc)
|
||||||
|
{
|
||||||
|
bool ctr_ok = true;
|
||||||
|
bool cond_ok = true;
|
||||||
|
|
||||||
|
if (BO_CONDITIONAL_BRANCH(bo)) {
|
||||||
|
if (BO_BRANCH_IF_TRUE(bo))
|
||||||
|
cond_ok = T0;
|
||||||
|
else
|
||||||
|
cond_ok = !T0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BO_DECREMENT_CTR(bo)) {
|
||||||
|
uint32 ctr = powerpc_dyngen_helper::get_ctr() - 1;
|
||||||
|
if (BO_BRANCH_IF_CTR_ZERO(bo))
|
||||||
|
ctr_ok = ctr == 0;
|
||||||
|
else
|
||||||
|
ctr_ok = ctr != 0;
|
||||||
|
powerpc_dyngen_helper::set_ctr(ctr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctr_ok && cond_ok)
|
||||||
|
powerpc_dyngen_helper::set_pc(tpc);
|
||||||
|
else
|
||||||
|
powerpc_dyngen_helper::set_pc(npc);
|
||||||
|
|
||||||
|
dyngen_barrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BO(A,B,C,D) (((A) << 4)| ((B) << 3) | ((C) << 2) | ((D) << 1))
|
||||||
|
#define DEFINE_OP(BO_SUFFIX, BO_VALUE) \
|
||||||
|
void OPPROTO op_branch_A0_bo_##BO_SUFFIX(void) \
|
||||||
|
{ \
|
||||||
|
do_execute_branch_bo<BO BO_VALUE>(A0, PARAM1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_OP(0000,(0,0,0,0));
|
||||||
|
DEFINE_OP(0001,(0,0,0,1));
|
||||||
|
DEFINE_OP(001x,(0,0,1,0));
|
||||||
|
DEFINE_OP(0100,(0,1,0,0));
|
||||||
|
DEFINE_OP(0101,(0,1,0,1));
|
||||||
|
DEFINE_OP(011x,(0,1,1,0));
|
||||||
|
DEFINE_OP(1x00,(1,0,0,0));
|
||||||
|
DEFINE_OP(1x01,(1,0,0,1));
|
||||||
|
// NOTE: the compiler is expected to optimize out the use of PARAM1
|
||||||
|
DEFINE_OP(1x1x,(1,0,1,0));
|
||||||
|
|
||||||
|
#undef DEFINE_OP
|
||||||
|
#undef BO
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare & Record instructions
|
* Compare & Record instructions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
void OPPROTO op_record_nego_T0(void)
|
void OPPROTO op_record_cr0_T0(void)
|
||||||
{
|
{
|
||||||
powerpc_dyngen_helper::xer().set_ov(T0 == 0x80000000);
|
uint32 cr = powerpc_dyngen_helper::get_cr() & ~CR_field<0>::mask();
|
||||||
|
cr |= powerpc_dyngen_helper::xer().get_so() << 28;
|
||||||
|
if ((int32)T0 < 0)
|
||||||
|
cr |= CR_LT_field<0>::mask();
|
||||||
|
else if ((int32)T0 > 0)
|
||||||
|
cr |= CR_GT_field<0>::mask();
|
||||||
|
else
|
||||||
|
cr |= CR_EQ_field<0>::mask();
|
||||||
|
powerpc_dyngen_helper::set_cr(cr);
|
||||||
dyngen_barrier();
|
dyngen_barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define im PARAM1
|
#define im PARAM1
|
||||||
|
|
||||||
#if DYNGEN_ASM_OPTS && defined(__powerpc__)
|
#if DYNGEN_ASM_OPTS && defined(__powerpc__) && 0
|
||||||
|
|
||||||
#define DEFINE_OP(NAME, COMP, LHS, RHST, RHS) \
|
#define DEFINE_OP(NAME, COMP, LHS, RHST, RHS) \
|
||||||
void OPPROTO op_##NAME##_##LHS##_##RHS(void) \
|
void OPPROTO op_##NAME##_##LHS##_##RHS(void) \
|
||||||
{ \
|
{ \
|
||||||
RC = powerpc_dyngen_helper::xer().get_so(); \
|
T0 = powerpc_dyngen_helper::xer().get_so(); \
|
||||||
uint32 v; \
|
uint32 v; \
|
||||||
asm volatile (COMP " 7,%1,%2 ; mfcr %0" : "=r" (v) : "r" (LHS), RHST (RHS) : "cr7"); \
|
asm volatile (COMP " 7,%1,%2 ; mfcr %0" : "=r" (v) : "r" (LHS), RHST (RHS) : "cr7"); \
|
||||||
RC |= (v & 0xe); \
|
T0 |= (v & 0xe); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_OP(compare,"cmpw",T0,"r",T1);
|
DEFINE_OP(compare,"cmpw",T0,"r",T1);
|
||||||
@ -453,17 +479,17 @@ DEFINE_OP(compare_logical,"cmplwi",T0,"i",0);
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define DEFINE_OP(NAME, TYPE, LHS, RHS) \
|
#define DEFINE_OP(NAME, TYPE, LHS, RHS) \
|
||||||
void OPPROTO op_##NAME##_##LHS##_##RHS(void) \
|
void OPPROTO op_##NAME##_##LHS##_##RHS(void) \
|
||||||
{ \
|
{ \
|
||||||
RC = powerpc_dyngen_helper::xer().get_so(); \
|
const uint32 SO = powerpc_dyngen_helper::xer().get_so(); \
|
||||||
if ((TYPE)LHS < (TYPE)RHS) \
|
if ((TYPE)LHS < (TYPE)RHS) \
|
||||||
RC |= standalone_CR_LT_field::mask(); \
|
T0 = SO | standalone_CR_LT_field::mask(); \
|
||||||
else if ((TYPE)LHS > (TYPE)RHS) \
|
else if ((TYPE)LHS > (TYPE)RHS) \
|
||||||
RC |= standalone_CR_GT_field::mask(); \
|
T0 = SO | standalone_CR_GT_field::mask(); \
|
||||||
else \
|
else \
|
||||||
RC |= standalone_CR_EQ_field::mask(); \
|
T0 = SO | standalone_CR_EQ_field::mask(); \
|
||||||
dyngen_barrier(); \
|
dyngen_barrier(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_OP(compare,int32,T0,T1);
|
DEFINE_OP(compare,int32,T0,T1);
|
||||||
@ -842,10 +868,9 @@ void OPPROTO op_inc_32_mem(void)
|
|||||||
*m += 1;
|
*m += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_mtcrf_T0_im(void)
|
void OPPROTO op_nego_T0(void)
|
||||||
{
|
{
|
||||||
const uint32 mask = PARAM1;
|
powerpc_dyngen_helper::xer().set_ov(T0 == 0x80000000);
|
||||||
uint32 cr = powerpc_dyngen_helper::get_cr() & ~mask;
|
T0 = -T0;
|
||||||
cr |= T0 & mask;
|
|
||||||
powerpc_dyngen_helper::set_cr(cr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,87 +29,42 @@
|
|||||||
#define DEFINE_GEN(NAME,ARGS) void powerpc_dyngen::NAME ARGS
|
#define DEFINE_GEN(NAME,ARGS) void powerpc_dyngen::NAME ARGS
|
||||||
#include "ppc-dyngen-ops.hpp"
|
#include "ppc-dyngen-ops.hpp"
|
||||||
|
|
||||||
void powerpc_dyngen::invalidate_so_cache()
|
|
||||||
{
|
|
||||||
rc_cache.set_so_status(RC_cache::STATUS_TRASH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerpc_dyngen::invalidate_cr_cache()
|
|
||||||
{
|
|
||||||
invalidate_so_cache();
|
|
||||||
rc_cache.set_val_status(RC_cache::STATUS_TRASH);
|
|
||||||
rc_cache.set_crf(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerpc_dyngen::gen_commit_cr()
|
|
||||||
{
|
|
||||||
if (rc_cache.val_status() == RC_cache::STATUS_VALID &&
|
|
||||||
rc_cache.so_status() == RC_cache::STATUS_VALID) {
|
|
||||||
const int crf = rc_cache.crf();
|
|
||||||
assert(crf != -1);
|
|
||||||
gen_store_RC_cr(crf);
|
|
||||||
invalidate_cr_cache();
|
|
||||||
}
|
|
||||||
else if (rc_cache.val_status() == RC_cache::STATUS_VALID) {
|
|
||||||
const int crf = rc_cache.crf();
|
|
||||||
assert(crf != -1);
|
|
||||||
gen_commit_rc_cache_cr(crf);
|
|
||||||
invalidate_cr_cache();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Maybe only SO field left to spill
|
|
||||||
gen_commit_so();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerpc_dyngen::gen_commit_so()
|
|
||||||
{
|
|
||||||
if (rc_cache.so_status() == RC_cache::STATUS_VALID) {
|
|
||||||
const int crf = rc_cache.crf();
|
|
||||||
assert(crf != -1);
|
|
||||||
gen_commit_so_cache_cr(crf);
|
|
||||||
invalidate_so_cache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerpc_dyngen::gen_compare_T0_T1(int crf)
|
void powerpc_dyngen::gen_compare_T0_T1(int crf)
|
||||||
{
|
{
|
||||||
if (!rc_cache.has_field(crf))
|
|
||||||
gen_commit_cr();
|
|
||||||
gen_op_compare_T0_T1();
|
gen_op_compare_T0_T1();
|
||||||
rc_cache.cache_field(crf);
|
gen_store_T0_crf(crf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void powerpc_dyngen::gen_compare_T0_im(int crf, int32 value)
|
void powerpc_dyngen::gen_compare_T0_im(int crf, int32 value)
|
||||||
{
|
{
|
||||||
if (!rc_cache.has_field(crf))
|
|
||||||
gen_commit_cr();
|
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
gen_op_compare_T0_0();
|
gen_op_compare_T0_0();
|
||||||
else
|
else
|
||||||
gen_op_compare_T0_im(value);
|
gen_op_compare_T0_im(value);
|
||||||
rc_cache.cache_field(crf);
|
gen_store_T0_crf(crf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void powerpc_dyngen::gen_compare_logical_T0_T1(int crf)
|
void powerpc_dyngen::gen_compare_logical_T0_T1(int crf)
|
||||||
{
|
{
|
||||||
if (!rc_cache.has_field(crf))
|
|
||||||
gen_commit_cr();
|
|
||||||
gen_op_compare_logical_T0_T1();
|
gen_op_compare_logical_T0_T1();
|
||||||
rc_cache.cache_field(crf);
|
gen_store_T0_crf(crf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void powerpc_dyngen::gen_compare_logical_T0_im(int crf, int32 value)
|
void powerpc_dyngen::gen_compare_logical_T0_im(int crf, int32 value)
|
||||||
{
|
{
|
||||||
if (!rc_cache.has_field(crf))
|
|
||||||
gen_commit_cr();
|
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
gen_op_compare_logical_T0_0();
|
gen_op_compare_logical_T0_0();
|
||||||
else
|
else
|
||||||
gen_op_compare_logical_T0_im(value);
|
gen_op_compare_logical_T0_im(value);
|
||||||
rc_cache.cache_field(crf);
|
gen_store_T0_crf(crf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void powerpc_dyngen::gen_mtcrf_T0_im(uint32 mask)
|
||||||
|
{
|
||||||
|
gen_op_mtcrf_T0_im(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load/store registers
|
* Load/store registers
|
||||||
**/
|
**/
|
||||||
@ -170,112 +125,75 @@ DEFINE_INSN(store, T1, crb);
|
|||||||
|
|
||||||
#undef DEFINE_INSN
|
#undef DEFINE_INSN
|
||||||
|
|
||||||
#define DEFINE_INSN(OP, REG) \
|
#define DEFINE_INSN(OP, REG) \
|
||||||
void powerpc_dyngen::gen_##OP##_##REG##_cr(int crf) \
|
void powerpc_dyngen::gen_##OP##_##REG##_crf(int crf) \
|
||||||
{ \
|
{ \
|
||||||
switch (crf) { \
|
switch (crf) { \
|
||||||
case 0: gen_op_##OP##_##REG##_cr0(); break; \
|
case 0: gen_op_##OP##_##REG##_cr0(); break; \
|
||||||
case 1: gen_op_##OP##_##REG##_cr1(); break; \
|
case 1: gen_op_##OP##_##REG##_cr1(); break; \
|
||||||
case 2: gen_op_##OP##_##REG##_cr2(); break; \
|
case 2: gen_op_##OP##_##REG##_cr2(); break; \
|
||||||
case 3: gen_op_##OP##_##REG##_cr3(); break; \
|
case 3: gen_op_##OP##_##REG##_cr3(); break; \
|
||||||
case 4: gen_op_##OP##_##REG##_cr4(); break; \
|
case 4: gen_op_##OP##_##REG##_cr4(); break; \
|
||||||
case 5: gen_op_##OP##_##REG##_cr5(); break; \
|
case 5: gen_op_##OP##_##REG##_cr5(); break; \
|
||||||
case 6: gen_op_##OP##_##REG##_cr6(); break; \
|
case 6: gen_op_##OP##_##REG##_cr6(); break; \
|
||||||
case 7: gen_op_##OP##_##REG##_cr7(); break; \
|
case 7: gen_op_##OP##_##REG##_cr7(); break; \
|
||||||
default: abort(); \
|
default: abort(); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_INSN(load, RC);
|
DEFINE_INSN(load, T0);
|
||||||
DEFINE_INSN(store, RC);
|
DEFINE_INSN(store, T0);
|
||||||
DEFINE_INSN(commit, so_cache);
|
|
||||||
DEFINE_INSN(commit, rc_cache);
|
|
||||||
|
|
||||||
#undef DEFINE_INSN
|
#undef DEFINE_INSN
|
||||||
|
|
||||||
void powerpc_dyngen::gen_record_cr0_T0(void)
|
|
||||||
{
|
|
||||||
gen_compare_T0_im(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare condition register cache for branch
|
|
||||||
*
|
|
||||||
* This was meant to be a CR caching system but gain is almost
|
|
||||||
* zero. However, this shows the ability to handle a CR cache
|
|
||||||
* forwards and actually, a superblock-level (traces) optimizer
|
|
||||||
* with proper code generation will benefit from it.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#define USE_CR_CACHE 1
|
|
||||||
|
|
||||||
void powerpc_dyngen::gen_prepare_RC(int bi)
|
|
||||||
{
|
|
||||||
const int crf = bi / 4;
|
|
||||||
const int crb = bi % 4;
|
|
||||||
|
|
||||||
#if USE_CR_CACHE
|
|
||||||
if (rc_cache.crf() == crf) {
|
|
||||||
if (crb != 3) {
|
|
||||||
// Rematerialize (LT, GT, EQ) if they are not live
|
|
||||||
if (rc_cache.val_status() == RC_cache::STATUS_VALID)
|
|
||||||
gen_commit_rc_cache_cr(crf);
|
|
||||||
else
|
|
||||||
gen_load_RC_cr(crf);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Rematerialize SO if it is not in cache
|
|
||||||
if (rc_cache.so_status() == RC_cache::STATUS_VALID)
|
|
||||||
gen_commit_so_cache_cr(crf);
|
|
||||||
else
|
|
||||||
gen_load_RC_cr(crf);
|
|
||||||
}
|
|
||||||
invalidate_cr_cache();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Reload flags from memory
|
|
||||||
gen_commit_cr();
|
|
||||||
gen_load_RC_cr(crf);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
gen_commit_cr();
|
|
||||||
gen_load_RC_cr(crf);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerpc_dyngen::gen_bc_A0(int bo, int bi, uint32 npc)
|
void powerpc_dyngen::gen_bc_A0(int bo, int bi, uint32 npc)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
if (BO_CONDITIONAL_BRANCH(bo)) {
|
if (BO_CONDITIONAL_BRANCH(bo)) {
|
||||||
enum { lt, gt, eq, so };
|
gen_load_T0_CR();
|
||||||
gen_prepare_RC(bi);
|
gen_and_32_T0_im(1 << (31 - bi));
|
||||||
const int n = ((bi % 4) << 2) | ((bo >> 1) & 3);
|
}
|
||||||
#define _(CR,DCTR,CTR0) (((CR) << 2) | ((DCTR) ? 0 : 2) | ((CTR0) ? 1 : 0))
|
switch (bo >> 1) {
|
||||||
if (BO_BRANCH_IF_TRUE(bo)) {
|
#define _(A,B,C,D) (((A) << 3)| ((B) << 2) | ((C) << 1) | (D))
|
||||||
switch (n) {
|
case _(0,0,0,0): gen_op_branch_A0_bo_0000(npc); break;
|
||||||
#define C(CR) \
|
case _(0,0,0,1): gen_op_branch_A0_bo_0001(npc); break;
|
||||||
case _(CR,0,0): gen_b##CR##_0x(npc); break; \
|
case _(0,0,1,0):
|
||||||
case _(CR,0,1): gen_b##CR##_0x(npc); break; \
|
case _(0,0,1,1): gen_op_branch_A0_bo_001x(npc); break;
|
||||||
case _(CR,1,0): gen_b##CR##_10(npc); break; \
|
case _(0,1,0,0): gen_op_branch_A0_bo_0100(npc); break;
|
||||||
case _(CR,1,1): gen_b##CR##_11(npc); break;
|
case _(0,1,0,1): gen_op_branch_A0_bo_0101(npc); break;
|
||||||
C(lt); C(gt); C(eq); C(so);
|
case _(0,1,1,0):
|
||||||
#undef C
|
case _(0,1,1,1): gen_op_branch_A0_bo_011x(npc); break;
|
||||||
}
|
case _(1,0,0,0):
|
||||||
}
|
case _(1,1,0,0): gen_op_branch_A0_bo_1x00(npc); break;
|
||||||
else {
|
case _(1,0,0,1):
|
||||||
switch (n) {
|
case _(1,1,0,1): gen_op_branch_A0_bo_1x01(npc); break;
|
||||||
#define C(CR) \
|
case _(1,0,1,0):
|
||||||
case _(CR,0,0): gen_bn##CR##_0x(npc); break; \
|
case _(1,0,1,1):
|
||||||
case _(CR,0,1): gen_bn##CR##_0x(npc); break; \
|
case _(1,1,1,0):
|
||||||
case _(CR,1,0): gen_bn##CR##_10(npc); break; \
|
case _(1,1,1,1): gen_op_branch_A0_bo_1x1x(); break;
|
||||||
case _(CR,1,1): gen_bn##CR##_11(npc); break;
|
|
||||||
C(lt); C(gt); C(eq); C(so);
|
|
||||||
#undef C
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#undef _
|
#undef _
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (BO_CONDITIONAL_BRANCH(bo)) {
|
||||||
|
gen_load_T0_CR();
|
||||||
|
gen_and_32_T0_im(1 << (31 - bi));
|
||||||
|
const int n = (bo >> 1) & 7;
|
||||||
|
switch (n) {
|
||||||
|
#define _(TRUE,DCTR,CTR0) (((TRUE) ? 4 : 0) | ((DCTR) ? 0 : 2) | ((CTR0) ? 1 : 0))
|
||||||
|
case _(0,0,0): gen_op_branch_if_not_T0_ctr_0x(npc); break;
|
||||||
|
case _(0,0,1): gen_op_branch_if_not_T0_ctr_0x(npc); break;
|
||||||
|
case _(0,1,0): gen_op_branch_if_not_T0_ctr_10(npc); break;
|
||||||
|
case _(0,1,1): gen_op_branch_if_not_T0_ctr_11(npc); break;
|
||||||
|
case _(1,0,0): gen_op_branch_if_T0_ctr_0x(npc); break;
|
||||||
|
case _(1,0,1): gen_op_branch_if_T0_ctr_0x(npc); break;
|
||||||
|
case _(1,1,0): gen_op_branch_if_T0_ctr_10(npc); break;
|
||||||
|
case _(1,1,1): gen_op_branch_if_T0_ctr_11(npc); break;
|
||||||
|
#undef _
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gen_commit_cr();
|
|
||||||
if (BO_DECREMENT_CTR(bo)) {
|
if (BO_DECREMENT_CTR(bo)) {
|
||||||
gen_decrement_ctr_T0();
|
gen_decrement_ctr_T0();
|
||||||
if (BO_BRANCH_IF_CTR_ZERO(bo))
|
if (BO_BRANCH_IF_CTR_ZERO(bo))
|
||||||
@ -288,4 +206,5 @@ void powerpc_dyngen::gen_bc_A0(int bo, int bi, uint32 npc)
|
|||||||
gen_set_PC_A0();
|
gen_set_PC_A0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -37,36 +37,6 @@ class powerpc_dyngen
|
|||||||
# include "ppc-dyngen-ops.hpp"
|
# include "ppc-dyngen-ops.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class RC_cache {
|
|
||||||
int m_val_status;
|
|
||||||
int m_so_status;
|
|
||||||
int m_crf;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int crf() const { return m_crf; }
|
|
||||||
int val_status() const { return m_val_status; }
|
|
||||||
int so_status() const { return m_so_status; }
|
|
||||||
void set_crf(int v) { m_crf = v; }
|
|
||||||
void set_val_status(int v) { m_val_status = v; }
|
|
||||||
void set_so_status(int v) { m_so_status = v; }
|
|
||||||
|
|
||||||
enum {
|
|
||||||
STATUS_TRASH,
|
|
||||||
STATUS_VALID,
|
|
||||||
};
|
|
||||||
|
|
||||||
RC_cache()
|
|
||||||
: m_val_status(STATUS_TRASH), m_so_status(STATUS_TRASH), m_crf(-1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool has_field(int crf) const
|
|
||||||
{ return m_crf == crf; }
|
|
||||||
|
|
||||||
void cache_field(int crf)
|
|
||||||
{ m_val_status = m_so_status = STATUS_VALID; m_crf = crf; }
|
|
||||||
};
|
|
||||||
RC_cache rc_cache;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Make rc_cache accessible to codegen helper
|
// Make rc_cache accessible to codegen helper
|
||||||
@ -95,40 +65,28 @@ public:
|
|||||||
#define DEFINE_ALIAS_3(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(long p1,long p2,long p3),(p1,p2,p3))
|
#define DEFINE_ALIAS_3(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(long p1,long p2,long p3),(p1,p2,p3))
|
||||||
#ifdef NO_DEFINE_ALIAS
|
#ifdef NO_DEFINE_ALIAS
|
||||||
#define DEFINE_ALIAS(NAME,N)
|
#define DEFINE_ALIAS(NAME,N)
|
||||||
#define DEFINE_ALIAS_CLOBBER_SO(NAME,N)
|
|
||||||
#define DEFINE_ALIAS_CLOBBER_CR(NAME,N)
|
|
||||||
#else
|
#else
|
||||||
#define DEFINE_ALIAS(NAME,N) DEFINE_ALIAS_##N(NAME,,)
|
#define DEFINE_ALIAS(NAME,N) DEFINE_ALIAS_##N(NAME,,)
|
||||||
#define DEFINE_ALIAS_CLOBBER_CR(NAME,N) DEFINE_ALIAS_##N(NAME,gen_commit_cr(),)
|
|
||||||
#define DEFINE_ALIAS_CLOBBER_SO(NAME,N) DEFINE_ALIAS_##N(NAME,gen_commit_so(),)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Misc instructions
|
// Misc instructions
|
||||||
DEFINE_ALIAS(inc_32_mem,1);
|
DEFINE_ALIAS(inc_32_mem,1);
|
||||||
DEFINE_ALIAS(mtcrf_T0_im,1);
|
DEFINE_ALIAS(nego_T0,0);
|
||||||
|
|
||||||
// Condition registers
|
// Condition registers
|
||||||
private:
|
DEFINE_ALIAS(load_T0_CR,0);
|
||||||
void gen_commit_so_cache_cr(int crf);
|
DEFINE_ALIAS(store_T0_CR,0);
|
||||||
void gen_commit_rc_cache_cr(int crf);
|
void gen_load_T0_crf(int crf);
|
||||||
public:
|
void gen_store_T0_crf(int crf);
|
||||||
void invalidate_so_cache();
|
|
||||||
void invalidate_cr_cache();
|
|
||||||
void gen_commit_so();
|
|
||||||
void gen_commit_cr();
|
|
||||||
DEFINE_ALIAS_CLOBBER_CR(load_T0_CR,0);
|
|
||||||
DEFINE_ALIAS_CLOBBER_CR(store_T0_CR,0);
|
|
||||||
DEFINE_ALIAS(load_T0_XER,0);
|
|
||||||
DEFINE_ALIAS(store_T0_XER,0);
|
|
||||||
void gen_load_T0_crb(int i);
|
void gen_load_T0_crb(int i);
|
||||||
void gen_load_T1_crb(int i);
|
void gen_load_T1_crb(int i);
|
||||||
void gen_store_T0_crb(int i);
|
void gen_store_T0_crb(int i);
|
||||||
void gen_store_T1_crb(int i);
|
void gen_store_T1_crb(int i);
|
||||||
void gen_load_RC_cr(int crf);
|
void gen_mtcrf_T0_im(uint32 mask);
|
||||||
void gen_store_RC_cr(int crf);
|
|
||||||
void gen_prepare_RC(int bi);
|
|
||||||
|
|
||||||
// Special purpose registers
|
// Special purpose registers
|
||||||
|
DEFINE_ALIAS(load_T0_XER,0);
|
||||||
|
DEFINE_ALIAS(store_T0_XER,0);
|
||||||
DEFINE_ALIAS(load_T0_PC,0);
|
DEFINE_ALIAS(load_T0_PC,0);
|
||||||
DEFINE_ALIAS(store_T0_PC,0);
|
DEFINE_ALIAS(store_T0_PC,0);
|
||||||
DEFINE_ALIAS(set_PC_im,1);
|
DEFINE_ALIAS(set_PC_im,1);
|
||||||
@ -150,11 +108,7 @@ public:
|
|||||||
DEFINE_ALIAS(branch_A0_if_not_T0,1);
|
DEFINE_ALIAS(branch_A0_if_not_T0,1);
|
||||||
|
|
||||||
// Compare & Record instructions
|
// Compare & Record instructions
|
||||||
DEFINE_ALIAS_CLOBBER_SO(record_nego_T0,0);
|
DEFINE_ALIAS(record_cr0_T0,0);
|
||||||
void gen_record_cr0_T0();
|
|
||||||
DEFINE_ALIAS(compare_T0_T1,0);
|
|
||||||
DEFINE_ALIAS(compare_T0_0,0);
|
|
||||||
DEFINE_ALIAS(compare_T0_im,1);
|
|
||||||
void gen_compare_T0_T1(int crf);
|
void gen_compare_T0_T1(int crf);
|
||||||
void gen_compare_T0_im(int crf, int32 value);
|
void gen_compare_T0_im(int crf, int32 value);
|
||||||
void gen_compare_logical_T0_T1(int crf);
|
void gen_compare_logical_T0_T1(int crf);
|
||||||
@ -164,11 +118,11 @@ public:
|
|||||||
DEFINE_ALIAS(mulhw_T0_T1,0);
|
DEFINE_ALIAS(mulhw_T0_T1,0);
|
||||||
DEFINE_ALIAS(mulhwu_T0_T1,0);
|
DEFINE_ALIAS(mulhwu_T0_T1,0);
|
||||||
DEFINE_ALIAS(mulli_T0_im,1);
|
DEFINE_ALIAS(mulli_T0_im,1);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(mullwo_T0_T1,0);
|
DEFINE_ALIAS(mullwo_T0_T1,0);
|
||||||
DEFINE_ALIAS(divw_T0_T1,0);
|
DEFINE_ALIAS(divw_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(divwo_T0_T1,0);
|
DEFINE_ALIAS(divwo_T0_T1,0);
|
||||||
DEFINE_ALIAS(divwu_T0_T1,0);
|
DEFINE_ALIAS(divwu_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(divwuo_T0_T1,0);
|
DEFINE_ALIAS(divwuo_T0_T1,0);
|
||||||
|
|
||||||
// Shift/Rotate instructions
|
// Shift/Rotate instructions
|
||||||
DEFINE_ALIAS(slw_T0_T1,0);
|
DEFINE_ALIAS(slw_T0_T1,0);
|
||||||
@ -184,40 +138,27 @@ public:
|
|||||||
DEFINE_ALIAS(addo_T0_T1,0);
|
DEFINE_ALIAS(addo_T0_T1,0);
|
||||||
DEFINE_ALIAS(addc_T0_im,1);
|
DEFINE_ALIAS(addc_T0_im,1);
|
||||||
DEFINE_ALIAS(addc_T0_T1,0);
|
DEFINE_ALIAS(addc_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(addco_T0_T1,0);
|
DEFINE_ALIAS(addco_T0_T1,0);
|
||||||
DEFINE_ALIAS(adde_T0_T1,0);
|
DEFINE_ALIAS(adde_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(addeo_T0_T1,0);
|
DEFINE_ALIAS(addeo_T0_T1,0);
|
||||||
DEFINE_ALIAS(addme_T0,0);
|
DEFINE_ALIAS(addme_T0,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(addmeo_T0,0);
|
DEFINE_ALIAS(addmeo_T0,0);
|
||||||
DEFINE_ALIAS(addze_T0,0);
|
DEFINE_ALIAS(addze_T0,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(addzeo_T0,0);
|
DEFINE_ALIAS(addzeo_T0,0);
|
||||||
DEFINE_ALIAS(subf_T0_T1,0);
|
DEFINE_ALIAS(subf_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(subfo_T0_T1,0);
|
DEFINE_ALIAS(subfo_T0_T1,0);
|
||||||
DEFINE_ALIAS(subfc_T0_im,1);
|
DEFINE_ALIAS(subfc_T0_im,1);
|
||||||
DEFINE_ALIAS(subfc_T0_T1,0);
|
DEFINE_ALIAS(subfc_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(subfco_T0_T1,0);
|
DEFINE_ALIAS(subfco_T0_T1,0);
|
||||||
DEFINE_ALIAS(subfe_T0_T1,0);
|
DEFINE_ALIAS(subfe_T0_T1,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(subfeo_T0_T1,0);
|
DEFINE_ALIAS(subfeo_T0_T1,0);
|
||||||
DEFINE_ALIAS(subfme_T0,0);
|
DEFINE_ALIAS(subfme_T0,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(subfmeo_T0,0);
|
DEFINE_ALIAS(subfmeo_T0,0);
|
||||||
DEFINE_ALIAS(subfze_T0,0);
|
DEFINE_ALIAS(subfze_T0,0);
|
||||||
DEFINE_ALIAS_CLOBBER_SO(subfzeo_T0,0);
|
DEFINE_ALIAS(subfzeo_T0,0);
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
void gen_bc_A0(int bo, int bi, uint32 npc);
|
void gen_bc_A0(int bo, int bi, uint32 npc);
|
||||||
#define DEFINE_ALIAS_GRP_1(CR,CTR) \
|
|
||||||
DEFINE_ALIAS(b##CR##_##CTR,1); \
|
|
||||||
DEFINE_ALIAS(bn##CR##_##CTR,1);
|
|
||||||
#define DEFINE_ALIAS_GRP_2(CR) \
|
|
||||||
DEFINE_ALIAS_GRP_1(CR,0x); \
|
|
||||||
DEFINE_ALIAS_GRP_1(CR,10); \
|
|
||||||
DEFINE_ALIAS_GRP_1(CR,11);
|
|
||||||
DEFINE_ALIAS_GRP_2(lt);
|
|
||||||
DEFINE_ALIAS_GRP_2(gt);
|
|
||||||
DEFINE_ALIAS_GRP_2(eq);
|
|
||||||
DEFINE_ALIAS_GRP_2(so);
|
|
||||||
#undef DEFINE_ALAIS_GRP_2
|
|
||||||
#undef DEFINE_ALIAS_GRP_1
|
|
||||||
|
|
||||||
#undef DEFINE_ALIAS
|
#undef DEFINE_ALIAS
|
||||||
#undef DEFINE_ALIAS_0
|
#undef DEFINE_ALIAS_0
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "cpu/ppc/ppc-operands.hpp"
|
#include "cpu/ppc/ppc-operands.hpp"
|
||||||
|
|
||||||
#ifdef SHEEPSHAVER
|
#ifdef SHEEPSHAVER
|
||||||
#include "xlowmem.h"
|
|
||||||
#include "cpu_emulation.h"
|
#include "cpu_emulation.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -445,16 +444,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
const int bo = BO_field::extract(opcode);
|
const int bo = BO_field::extract(opcode);
|
||||||
const int bi = BI_field::extract(opcode);
|
const int bi = BI_field::extract(opcode);
|
||||||
|
|
||||||
#ifdef SHEEPSHAVER
|
|
||||||
if (BO_CONDITIONAL_BRANCH(bo)) {
|
|
||||||
// FIXME: use the slow way if we expect to clobber CR
|
|
||||||
// in m68k emulator. In that case, we should merge CR
|
|
||||||
// flags, not commit cached one to memory.
|
|
||||||
if (vm_read_memory_4(XLM_RUN_MODE) == MODE_68K)
|
|
||||||
goto do_generic;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint32 npc = dpc + 4;
|
const uint32 npc = dpc + 4;
|
||||||
if (LK_field::test(opcode))
|
if (LK_field::test(opcode))
|
||||||
dg.gen_store_im_LR(npc);
|
dg.gen_store_im_LR(npc);
|
||||||
@ -531,7 +520,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
case PPC_I(CRORC): // Condition Register OR with Complement
|
case PPC_I(CRORC): // Condition Register OR with Complement
|
||||||
case PPC_I(CRXOR): // Condition Register XOR
|
case PPC_I(CRXOR): // Condition Register XOR
|
||||||
{
|
{
|
||||||
dg.gen_commit_cr();
|
|
||||||
dg.gen_load_T0_crb(crbA_field::extract(opcode));
|
dg.gen_load_T0_crb(crbA_field::extract(opcode));
|
||||||
dg.gen_load_T1_crb(crbB_field::extract(opcode));
|
dg.gen_load_T1_crb(crbB_field::extract(opcode));
|
||||||
switch (ii->mnemo) {
|
switch (ii->mnemo) {
|
||||||
@ -660,8 +648,9 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
{
|
{
|
||||||
dg.gen_load_T0_GPR(rA_field::extract(opcode));
|
dg.gen_load_T0_GPR(rA_field::extract(opcode));
|
||||||
if (OE_field::test(opcode))
|
if (OE_field::test(opcode))
|
||||||
dg.gen_record_nego_T0();
|
dg.gen_nego_T0();
|
||||||
dg.gen_neg_32_T0();
|
else
|
||||||
|
dg.gen_neg_32_T0();
|
||||||
if (Rc_field::test(opcode))
|
if (Rc_field::test(opcode))
|
||||||
dg.gen_record_cr0_T0();
|
dg.gen_record_cr0_T0();
|
||||||
dg.gen_store_T0_GPR(rD_field::extract(opcode));
|
dg.gen_store_T0_GPR(rD_field::extract(opcode));
|
||||||
@ -669,7 +658,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
}
|
}
|
||||||
case PPC_I(MFCR): // Move from Condition Register
|
case PPC_I(MFCR): // Move from Condition Register
|
||||||
{
|
{
|
||||||
dg.gen_commit_cr();
|
|
||||||
dg.gen_load_T0_CR();
|
dg.gen_load_T0_CR();
|
||||||
dg.gen_store_T0_GPR(rD_field::extract(opcode));
|
dg.gen_store_T0_GPR(rD_field::extract(opcode));
|
||||||
break;
|
break;
|
||||||
@ -1003,16 +991,14 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
}
|
}
|
||||||
case PPC_I(MTCRF): // Move to Condition Register Fields
|
case PPC_I(MTCRF): // Move to Condition Register Fields
|
||||||
{
|
{
|
||||||
dg.gen_commit_cr();
|
|
||||||
dg.gen_load_T0_GPR(rS_field::extract(opcode));
|
dg.gen_load_T0_GPR(rS_field::extract(opcode));
|
||||||
dg.gen_mtcrf_T0_im(field2mask[CRM_field::extract(opcode)]);
|
dg.gen_mtcrf_T0_im(field2mask[CRM_field::extract(opcode)]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PPC_I(MCRF): // Move Condition Register Field
|
case PPC_I(MCRF): // Move Condition Register Field
|
||||||
{
|
{
|
||||||
dg.gen_commit_cr();
|
dg.gen_load_T0_crf(crfS_field::extract(opcode));
|
||||||
dg.gen_load_RC_cr(crfS_field::extract(opcode));
|
dg.gen_store_T0_crf(crfD_field::extract(opcode));
|
||||||
dg.gen_store_RC_cr(crfD_field::extract(opcode));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: // Direct call to instruction handler
|
default: // Direct call to instruction handler
|
||||||
@ -1043,7 +1029,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
dg.gen_set_PC_im(dpc);
|
dg.gen_set_PC_im(dpc);
|
||||||
}
|
}
|
||||||
sync_pc_offset += 4;
|
sync_pc_offset += 4;
|
||||||
dg.gen_commit_cr();
|
|
||||||
dg.gen_invoke_CPU_im(func, opcode);
|
dg.gen_invoke_CPU_im(func, opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1054,7 +1039,6 @@ powerpc_cpu::compile_block(uint32 entry_point)
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dg.gen_commit_cr();
|
|
||||||
dg.gen_exec_return();
|
dg.gen_exec_return();
|
||||||
dg.gen_end();
|
dg.gen_end();
|
||||||
bi->end_pc = dpc;
|
bi->end_pc = dpc;
|
||||||
|
Loading…
Reference in New Issue
Block a user