From 04214f3820531324f522b30688d45672ad2e89ad Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Tue, 2 Dec 2003 22:49:18 +0000 Subject: [PATCH] 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. --- .../src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp | 4 + .../kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp | 221 ++++++++++-------- .../src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp | 219 ++++++----------- .../src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp | 101 ++------ .../src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp | 26 +-- 5 files changed, 222 insertions(+), 349 deletions(-) diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp index a60ab898..146a11a8 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -216,7 +216,11 @@ public: // Initialization & finalization void initialize(); +#ifdef SHEEPSHAVER powerpc_cpu(); +#else + powerpc_cpu(task_struct *parent_task); +#endif ~powerpc_cpu(); // Handle flight recorder diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp index 6593e996..9c3330c2 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp @@ -36,7 +36,6 @@ register struct powerpc_cpu *CPU asm(REG_CPU); register uint32 A0 asm(REG_A0); register uint32 T0 asm(REG_T0); register uint32 T1 asm(REG_T1); -register uint32 RC asm(REG_T2); // Semantic action templates #define DYNGEN_OPS @@ -134,25 +133,16 @@ void OPPROTO op_store_T0_CR(void) 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) \ void OPPROTO op_load_##REG##_crb##N(void) \ { \ - REG = bit_field::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) \ { \ - uint32 cr = powerpc_dyngen_helper::get_cr(); \ - bit_field::insert(cr, REG); \ + uint32 cr = powerpc_dyngen_helper::get_cr() & ~(1 << (31 - N)); \ + cr |= ((REG & 1) << (31 - N)); \ powerpc_dyngen_helper::set_cr(cr); \ } #define DEFINE_REG(N) \ @@ -195,48 +185,49 @@ DEFINE_REG(31); #undef DEFINE_REG #undef DEFINE_OP -#define DEFINE_OP(CRF, REG) \ -void OPPROTO op_load_##REG##_cr##CRF(void) \ -{ \ - REG = powerpc_dyngen_helper::cr().get(CRF); \ -} \ -void OPPROTO op_store_##REG##_cr##CRF(void) \ -{ \ - 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::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::mask() | \ - CR_GT_field::mask() | \ - CR_EQ_field::mask()); \ - cr = (cr & ~cr_mask) | ((RC << (28 - 4 * CRF)) & cr_mask); \ - powerpc_dyngen_helper::set_cr(cr); \ +#define DEFINE_OP(CRF, REG) \ +void OPPROTO op_load_##REG##_cr##CRF(void) \ +{ \ + REG = powerpc_dyngen_helper::cr().get(CRF); \ +} \ +void OPPROTO op_store_##REG##_cr##CRF(void) \ +{ \ + powerpc_dyngen_helper::cr().set(CRF, REG); \ } -DEFINE_OP(0, RC); -DEFINE_OP(1, RC); -DEFINE_OP(2, RC); -DEFINE_OP(3, RC); -DEFINE_OP(4, RC); -DEFINE_OP(5, RC); -DEFINE_OP(6, RC); -DEFINE_OP(7, RC); +DEFINE_OP(0, T0); +DEFINE_OP(1, T0); +DEFINE_OP(2, T0); +DEFINE_OP(3, T0); +DEFINE_OP(4, T0); +DEFINE_OP(5, T0); +DEFINE_OP(6, T0); +DEFINE_OP(7, T0); #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 **/ +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) { T0 = powerpc_dyngen_helper::get_pc(); @@ -346,36 +337,18 @@ static inline void do_execute_branch(uint32 tpc, uint32 npc) dyngen_barrier(); } -template< int crb > -struct RC_comparator { +struct branch_if_T0_condition { static inline bool test() { - return (RC & crb); + return T0 != 0; } }; -template< bool br_true, class comparator > -struct bool_condition { +struct branch_if_not_T0_condition { 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 > bnlt_condition; -typedef bool_condition< true, RC_comparator<4> > bgt_condition; -typedef bool_condition > bngt_condition; -typedef bool_condition< true, RC_comparator<2> > beq_condition; -typedef bool_condition > bneq_condition; -typedef bool_condition< true, RC_comparator<1> > bso_condition; -typedef bool_condition > bnso_condition; - struct ctr_0x_condition { static inline bool test() { return true; @@ -399,7 +372,7 @@ struct ctr_11_condition { }; #define DEFINE_OP_CTR(COND,CTR) \ -void OPPROTO op_##COND##_##CTR(void) \ +void OPPROTO op_##COND##_ctr_##CTR(void) \ { \ do_execute_branch(A0, PARAM1); \ } @@ -408,40 +381,93 @@ DEFINE_OP_CTR(COND,0x); \ DEFINE_OP_CTR(COND,10); \ DEFINE_OP_CTR(COND,11); -DEFINE_OP(blt); -DEFINE_OP(bgt); -DEFINE_OP(beq); -DEFINE_OP(bso); -DEFINE_OP(bnlt); -DEFINE_OP(bngt); -DEFINE_OP(bneq); -DEFINE_OP(bnso); +DEFINE_OP(branch_if_T0); +DEFINE_OP(branch_if_not_T0); #undef DEFINE_OP #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(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 **/ -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(); } #define im PARAM1 -#if DYNGEN_ASM_OPTS && defined(__powerpc__) +#if DYNGEN_ASM_OPTS && defined(__powerpc__) && 0 #define DEFINE_OP(NAME, COMP, LHS, RHST, RHS) \ void OPPROTO op_##NAME##_##LHS##_##RHS(void) \ { \ - RC = powerpc_dyngen_helper::xer().get_so(); \ + T0 = powerpc_dyngen_helper::xer().get_so(); \ uint32 v; \ 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); @@ -453,17 +479,17 @@ DEFINE_OP(compare_logical,"cmplwi",T0,"i",0); #else -#define DEFINE_OP(NAME, TYPE, LHS, RHS) \ -void OPPROTO op_##NAME##_##LHS##_##RHS(void) \ -{ \ - RC = powerpc_dyngen_helper::xer().get_so(); \ - if ((TYPE)LHS < (TYPE)RHS) \ - RC |= standalone_CR_LT_field::mask(); \ - else if ((TYPE)LHS > (TYPE)RHS) \ - RC |= standalone_CR_GT_field::mask(); \ - else \ - RC |= standalone_CR_EQ_field::mask(); \ - dyngen_barrier(); \ +#define DEFINE_OP(NAME, TYPE, LHS, RHS) \ +void OPPROTO op_##NAME##_##LHS##_##RHS(void) \ +{ \ + const uint32 SO = powerpc_dyngen_helper::xer().get_so(); \ + if ((TYPE)LHS < (TYPE)RHS) \ + T0 = SO | standalone_CR_LT_field::mask(); \ + else if ((TYPE)LHS > (TYPE)RHS) \ + T0 = SO | standalone_CR_GT_field::mask(); \ + else \ + T0 = SO | standalone_CR_EQ_field::mask(); \ + dyngen_barrier(); \ } DEFINE_OP(compare,int32,T0,T1); @@ -842,10 +868,9 @@ void OPPROTO op_inc_32_mem(void) *m += 1; } -void OPPROTO op_mtcrf_T0_im(void) +void OPPROTO op_nego_T0(void) { - const uint32 mask = PARAM1; - uint32 cr = powerpc_dyngen_helper::get_cr() & ~mask; - cr |= T0 & mask; - powerpc_dyngen_helper::set_cr(cr); + powerpc_dyngen_helper::xer().set_ov(T0 == 0x80000000); + T0 = -T0; } + diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp index 5214c6ee..b5629f72 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp @@ -29,87 +29,42 @@ #define DEFINE_GEN(NAME,ARGS) void powerpc_dyngen::NAME ARGS #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) { - if (!rc_cache.has_field(crf)) - gen_commit_cr(); 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) { - if (!rc_cache.has_field(crf)) - gen_commit_cr(); if (value == 0) gen_op_compare_T0_0(); else 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) { - if (!rc_cache.has_field(crf)) - gen_commit_cr(); 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) { - if (!rc_cache.has_field(crf)) - gen_commit_cr(); if (value == 0) gen_op_compare_logical_T0_0(); else 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 **/ @@ -170,112 +125,75 @@ DEFINE_INSN(store, T1, crb); #undef DEFINE_INSN -#define DEFINE_INSN(OP, REG) \ -void powerpc_dyngen::gen_##OP##_##REG##_cr(int crf) \ -{ \ - switch (crf) { \ - case 0: gen_op_##OP##_##REG##_cr0(); break; \ - case 1: gen_op_##OP##_##REG##_cr1(); break; \ - case 2: gen_op_##OP##_##REG##_cr2(); break; \ - case 3: gen_op_##OP##_##REG##_cr3(); break; \ - case 4: gen_op_##OP##_##REG##_cr4(); break; \ - case 5: gen_op_##OP##_##REG##_cr5(); break; \ - case 6: gen_op_##OP##_##REG##_cr6(); break; \ - case 7: gen_op_##OP##_##REG##_cr7(); break; \ - default: abort(); \ - } \ +#define DEFINE_INSN(OP, REG) \ +void powerpc_dyngen::gen_##OP##_##REG##_crf(int crf) \ +{ \ + switch (crf) { \ + case 0: gen_op_##OP##_##REG##_cr0(); break; \ + case 1: gen_op_##OP##_##REG##_cr1(); break; \ + case 2: gen_op_##OP##_##REG##_cr2(); break; \ + case 3: gen_op_##OP##_##REG##_cr3(); break; \ + case 4: gen_op_##OP##_##REG##_cr4(); break; \ + case 5: gen_op_##OP##_##REG##_cr5(); break; \ + case 6: gen_op_##OP##_##REG##_cr6(); break; \ + case 7: gen_op_##OP##_##REG##_cr7(); break; \ + default: abort(); \ + } \ } -DEFINE_INSN(load, RC); -DEFINE_INSN(store, RC); -DEFINE_INSN(commit, so_cache); -DEFINE_INSN(commit, rc_cache); +DEFINE_INSN(load, T0); +DEFINE_INSN(store, T0); #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) { +#if 1 if (BO_CONDITIONAL_BRANCH(bo)) { - enum { lt, gt, eq, so }; - gen_prepare_RC(bi); - const int n = ((bi % 4) << 2) | ((bo >> 1) & 3); -#define _(CR,DCTR,CTR0) (((CR) << 2) | ((DCTR) ? 0 : 2) | ((CTR0) ? 1 : 0)) - if (BO_BRANCH_IF_TRUE(bo)) { - switch (n) { -#define C(CR) \ - case _(CR,0,0): gen_b##CR##_0x(npc); break; \ - case _(CR,0,1): gen_b##CR##_0x(npc); break; \ - case _(CR,1,0): gen_b##CR##_10(npc); break; \ - case _(CR,1,1): gen_b##CR##_11(npc); break; - C(lt); C(gt); C(eq); C(so); -#undef C - } - } - else { - switch (n) { -#define C(CR) \ - case _(CR,0,0): gen_bn##CR##_0x(npc); break; \ - case _(CR,0,1): gen_bn##CR##_0x(npc); break; \ - case _(CR,1,0): gen_bn##CR##_10(npc); break; \ - case _(CR,1,1): gen_bn##CR##_11(npc); break; - C(lt); C(gt); C(eq); C(so); -#undef C - } - } + gen_load_T0_CR(); + gen_and_32_T0_im(1 << (31 - bi)); + } + switch (bo >> 1) { +#define _(A,B,C,D) (((A) << 3)| ((B) << 2) | ((C) << 1) | (D)) + case _(0,0,0,0): gen_op_branch_A0_bo_0000(npc); break; + case _(0,0,0,1): gen_op_branch_A0_bo_0001(npc); break; + case _(0,0,1,0): + case _(0,0,1,1): gen_op_branch_A0_bo_001x(npc); break; + case _(0,1,0,0): gen_op_branch_A0_bo_0100(npc); break; + case _(0,1,0,1): gen_op_branch_A0_bo_0101(npc); break; + case _(0,1,1,0): + 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; + case _(1,0,0,1): + case _(1,1,0,1): gen_op_branch_A0_bo_1x01(npc); break; + case _(1,0,1,0): + case _(1,0,1,1): + case _(1,1,1,0): + case _(1,1,1,1): gen_op_branch_A0_bo_1x1x(); break; #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 { - gen_commit_cr(); if (BO_DECREMENT_CTR(bo)) { gen_decrement_ctr_T0(); 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(); } } +#endif } diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp index a1c13617..95dbc981 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp @@ -37,36 +37,6 @@ class powerpc_dyngen # include "ppc-dyngen-ops.hpp" #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: // 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)) #ifdef NO_DEFINE_ALIAS #define DEFINE_ALIAS(NAME,N) -#define DEFINE_ALIAS_CLOBBER_SO(NAME,N) -#define DEFINE_ALIAS_CLOBBER_CR(NAME,N) #else #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 // Misc instructions DEFINE_ALIAS(inc_32_mem,1); - DEFINE_ALIAS(mtcrf_T0_im,1); + DEFINE_ALIAS(nego_T0,0); // Condition registers -private: - void gen_commit_so_cache_cr(int crf); - void gen_commit_rc_cache_cr(int crf); -public: - 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); + DEFINE_ALIAS(load_T0_CR,0); + DEFINE_ALIAS(store_T0_CR,0); + void gen_load_T0_crf(int crf); + void gen_store_T0_crf(int crf); void gen_load_T0_crb(int i); void gen_load_T1_crb(int i); void gen_store_T0_crb(int i); void gen_store_T1_crb(int i); - void gen_load_RC_cr(int crf); - void gen_store_RC_cr(int crf); - void gen_prepare_RC(int bi); + void gen_mtcrf_T0_im(uint32 mask); // Special purpose registers + DEFINE_ALIAS(load_T0_XER,0); + DEFINE_ALIAS(store_T0_XER,0); DEFINE_ALIAS(load_T0_PC,0); DEFINE_ALIAS(store_T0_PC,0); DEFINE_ALIAS(set_PC_im,1); @@ -150,11 +108,7 @@ public: DEFINE_ALIAS(branch_A0_if_not_T0,1); // Compare & Record instructions - DEFINE_ALIAS_CLOBBER_SO(record_nego_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); + DEFINE_ALIAS(record_cr0_T0,0); void gen_compare_T0_T1(int crf); void gen_compare_T0_im(int crf, int32 value); void gen_compare_logical_T0_T1(int crf); @@ -164,11 +118,11 @@ public: DEFINE_ALIAS(mulhw_T0_T1,0); DEFINE_ALIAS(mulhwu_T0_T1,0); 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_CLOBBER_SO(divwo_T0_T1,0); + DEFINE_ALIAS(divwo_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 DEFINE_ALIAS(slw_T0_T1,0); @@ -184,40 +138,27 @@ public: DEFINE_ALIAS(addo_T0_T1,0); DEFINE_ALIAS(addc_T0_im,1); 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_CLOBBER_SO(addeo_T0_T1,0); + DEFINE_ALIAS(addeo_T0_T1,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_CLOBBER_SO(addzeo_T0,0); + DEFINE_ALIAS(addzeo_T0,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_T1,0); - DEFINE_ALIAS_CLOBBER_SO(subfco_T0_T1,0); + DEFINE_ALIAS(subfco_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_CLOBBER_SO(subfmeo_T0,0); + DEFINE_ALIAS(subfmeo_T0,0); DEFINE_ALIAS(subfze_T0,0); - DEFINE_ALIAS_CLOBBER_SO(subfzeo_T0,0); + DEFINE_ALIAS(subfzeo_T0,0); // Branch instructions 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_0 diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp index aec2f35b..796a0c93 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp @@ -24,7 +24,6 @@ #include "cpu/ppc/ppc-operands.hpp" #ifdef SHEEPSHAVER -#include "xlowmem.h" #include "cpu_emulation.h" #endif @@ -445,16 +444,6 @@ powerpc_cpu::compile_block(uint32 entry_point) const int bo = BO_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; if (LK_field::test(opcode)) 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(CRXOR): // Condition Register XOR { - dg.gen_commit_cr(); dg.gen_load_T0_crb(crbA_field::extract(opcode)); dg.gen_load_T1_crb(crbB_field::extract(opcode)); switch (ii->mnemo) { @@ -660,8 +648,9 @@ powerpc_cpu::compile_block(uint32 entry_point) { dg.gen_load_T0_GPR(rA_field::extract(opcode)); if (OE_field::test(opcode)) - dg.gen_record_nego_T0(); - dg.gen_neg_32_T0(); + dg.gen_nego_T0(); + else + dg.gen_neg_32_T0(); if (Rc_field::test(opcode)) dg.gen_record_cr0_T0(); 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 { - dg.gen_commit_cr(); dg.gen_load_T0_CR(); dg.gen_store_T0_GPR(rD_field::extract(opcode)); break; @@ -1003,16 +991,14 @@ powerpc_cpu::compile_block(uint32 entry_point) } case PPC_I(MTCRF): // Move to Condition Register Fields { - dg.gen_commit_cr(); dg.gen_load_T0_GPR(rS_field::extract(opcode)); dg.gen_mtcrf_T0_im(field2mask[CRM_field::extract(opcode)]); break; } case PPC_I(MCRF): // Move Condition Register Field { - dg.gen_commit_cr(); - dg.gen_load_RC_cr(crfS_field::extract(opcode)); - dg.gen_store_RC_cr(crfD_field::extract(opcode)); + dg.gen_load_T0_crf(crfS_field::extract(opcode)); + dg.gen_store_T0_crf(crfD_field::extract(opcode)); break; } default: // Direct call to instruction handler @@ -1043,7 +1029,6 @@ powerpc_cpu::compile_block(uint32 entry_point) dg.gen_set_PC_im(dpc); } sync_pc_offset += 4; - dg.gen_commit_cr(); dg.gen_invoke_CPU_im(func, opcode); } } @@ -1054,7 +1039,6 @@ powerpc_cpu::compile_block(uint32 entry_point) goto again; } } - dg.gen_commit_cr(); dg.gen_exec_return(); dg.gen_end(); bi->end_pc = dpc;