Merge pull request #80 from dingusdev/cpu-refactor2

Use templating for interpreter
This commit is contained in:
dingusdev 2024-03-25 08:01:51 -07:00 committed by GitHub
commit c7ca4d9b97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1126 additions and 921 deletions

View File

@ -44,24 +44,30 @@ static inline uint32_t power_rot_mask(unsigned rot_mb, unsigned rot_me) {
return ((rot_mb <= rot_me) ? m2 & m1 : m1 | m2);
}
template <bool rec, bool ov>
void dppc_interpreter::power_abs() {
uint32_t ppc_result_d;
ppc_grab_regsda(ppc_cur_instruction);
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
if (oe_flag)
if (ov)
ppc_state.spr[SPR::XER] |= 0xC0000000;
} else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_abs<RC0, OV0>();
template void dppc_interpreter::power_abs<RC0, OV1>();
template void dppc_interpreter::power_abs<RC1, OV0>();
template void dppc_interpreter::power_abs<RC1, OV1>();
void dppc_interpreter::power_clcs() {
uint32_t ppc_result_d;
ppc_grab_regsda(ppc_cur_instruction);
@ -79,6 +85,7 @@ void dppc_interpreter::power_clcs() {
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template <bool rec, bool ov>
void dppc_interpreter::power_div() {
uint32_t ppc_result_d;
ppc_grab_regsdab(ppc_cur_instruction);
@ -94,40 +101,57 @@ void dppc_interpreter::power_div() {
ppc_state.spr[SPR::MQ] = dividend % divisor;
}
if (oe_flag)
if (ov)
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_div<RC0, OV0>();
template void dppc_interpreter::power_div<RC0, OV1>();
template void dppc_interpreter::power_div<RC1, OV0>();
template void dppc_interpreter::power_div<RC1, OV1>();
template <bool rec, bool ov>
void dppc_interpreter::power_divs() {
ppc_grab_regsdab(ppc_cur_instruction);
uint32_t ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
if (oe_flag)
if (ov)
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_divs<RC0, OV0>();
template void dppc_interpreter::power_divs<RC0, OV1>();
template void dppc_interpreter::power_divs<RC1, OV0>();
template void dppc_interpreter::power_divs<RC1, OV1>();
template <bool rec, bool ov>
void dppc_interpreter::power_doz() {
ppc_grab_regsdab(ppc_cur_instruction);
uint32_t ppc_result_d = (int32_t(ppc_result_a) >= int32_t(ppc_result_b))\
? 0 : ppc_result_b - ppc_result_a;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
if (oe_flag)
if (ov)
power_setsoov(ppc_result_a, ppc_result_b, ppc_result_d);
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_doz<RC0, OV0>();
template void dppc_interpreter::power_doz<RC0, OV1>();
template void dppc_interpreter::power_doz<RC1, OV0>();
template void dppc_interpreter::power_doz<RC1, OV1>();
void dppc_interpreter::power_dozi() {
uint32_t ppc_result_d;
ppc_grab_regsdasimm(ppc_cur_instruction);
@ -139,6 +163,7 @@ void dppc_interpreter::power_dozi() {
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template <bool rec>
void dppc_interpreter::power_lscbx() {
ppc_grab_regsdab(ppc_cur_instruction);
ppc_effective_address = ppc_result_b + (reg_a ? ppc_result_a : 0);
@ -182,10 +207,14 @@ void dppc_interpreter::power_lscbx() {
ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & ~0x7F) | bytes_copied;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
}
template void dppc_interpreter::power_lscbx<RC0>();
template void dppc_interpreter::power_lscbx<RC1>();
template <bool rec>
void dppc_interpreter::power_maskg() {
ppc_grab_regssab(ppc_cur_instruction);
uint32_t mask_start = ppc_result_d & 31;
@ -204,22 +233,30 @@ void dppc_interpreter::power_maskg() {
ppc_result_a = insert_mask;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_maskg<RC0>();
template void dppc_interpreter::power_maskg<true>();
template <bool rec>
void dppc_interpreter::power_maskir() {
ppc_grab_regssab(ppc_cur_instruction);
ppc_result_a = (ppc_result_a & ~ppc_result_b) | (ppc_result_d & ppc_result_b);
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_maskir<RC0>();
template void dppc_interpreter::power_maskir<true>();
template <bool rec, bool ov>
void dppc_interpreter::power_mul() {
ppc_grab_regsdab(ppc_cur_instruction);
uint64_t product;
@ -228,22 +265,37 @@ void dppc_interpreter::power_mul() {
uint32_t ppc_result_d = ((uint32_t)(product >> 32));
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
if (ov)
power_setsoov(ppc_result_a, ppc_result_b, ppc_result_d);
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_mul<RC0, OV0>();
template void dppc_interpreter::power_mul<RC0, OV1>();
template void dppc_interpreter::power_mul<RC1, OV0>();
template void dppc_interpreter::power_mul<RC1, OV1>();
template <bool rec, bool ov>
void dppc_interpreter::power_nabs() {
ppc_grab_regsda(ppc_cur_instruction);
uint32_t ppc_result_d = ppc_result_a & 0x80000000 ? ppc_result_a : -ppc_result_a;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_d);
if (ov)
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
ppc_store_iresult_reg(reg_d, ppc_result_d);
}
template void dppc_interpreter::power_nabs<RC0, OV0>();
template void dppc_interpreter::power_nabs<RC0, OV1>();
template void dppc_interpreter::power_nabs<RC1, OV0>();
template void dppc_interpreter::power_nabs<RC1, OV1>();
void dppc_interpreter::power_rlmi() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
@ -255,12 +307,13 @@ void dppc_interpreter::power_rlmi() {
ppc_result_a = ((r & mask) | (ppc_result_a & ~mask));
if (rc_flag)
if ((ppc_cur_instruction & 0x01) == 1)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template <bool rec>
void dppc_interpreter::power_rrib() {
ppc_grab_regssab(ppc_cur_instruction);
@ -270,12 +323,16 @@ void dppc_interpreter::power_rrib() {
ppc_result_a &= ~((ppc_result_d & 0x80000000) >> ppc_result_b);
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_rrib<RC0>();
template void dppc_interpreter::power_rrib<RC1>();
template <bool rec>
void dppc_interpreter::power_sle() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -285,12 +342,16 @@ void dppc_interpreter::power_sle() {
ppc_store_iresult_reg(reg_a, ppc_result_a);
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sle<RC0>();
template void dppc_interpreter::power_sle<RC1>();
template <bool rec>
void dppc_interpreter::power_sleq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -300,12 +361,16 @@ void dppc_interpreter::power_sleq() {
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
ppc_state.spr[SPR::MQ] = r;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sleq<RC0>();
template void dppc_interpreter::power_sleq<RC1>();
template <bool rec>
void dppc_interpreter::power_sliq() {
ppc_grab_regssa(ppc_cur_instruction);
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
@ -313,12 +378,16 @@ void dppc_interpreter::power_sliq() {
ppc_result_a = ppc_result_d << rot_sh;
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sliq<RC0>();
template void dppc_interpreter::power_sliq<RC1>();
template <bool rec>
void dppc_interpreter::power_slliq() {
ppc_grab_regssa(ppc_cur_instruction);
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
@ -328,12 +397,16 @@ void dppc_interpreter::power_slliq() {
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
ppc_state.spr[SPR::MQ] = r;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_slliq<RC0>();
template void dppc_interpreter::power_slliq<RC1>();
template <bool rec>
void dppc_interpreter::power_sllq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -347,12 +420,16 @@ void dppc_interpreter::power_sllq() {
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sllq<RC0>();
template void dppc_interpreter::power_sllq<RC1>();
template <bool rec>
void dppc_interpreter::power_slq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -363,12 +440,16 @@ void dppc_interpreter::power_slq() {
ppc_result_a = 0;
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
}
template void dppc_interpreter::power_slq<RC0>();
template void dppc_interpreter::power_slq<RC1>();
template <bool rec>
void dppc_interpreter::power_sraiq() {
ppc_grab_regssa(ppc_cur_instruction);
unsigned rot_sh = (ppc_cur_instruction >> 11) & 0x1F;
@ -382,12 +463,16 @@ void dppc_interpreter::power_sraiq() {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sraiq<RC0>();
template void dppc_interpreter::power_sraiq<RC1>();
template <bool rec>
void dppc_interpreter::power_sraq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 0x1F;
@ -403,12 +488,16 @@ void dppc_interpreter::power_sraq() {
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sraq<RC0>();
template void dppc_interpreter::power_sraq<RC1>();
template <bool rec>
void dppc_interpreter::power_sre() {
ppc_grab_regssab(ppc_cur_instruction);
@ -417,12 +506,16 @@ void dppc_interpreter::power_sre() {
ppc_result_a = ppc_result_d >> rot_sh;
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sre<RC0>();
template void dppc_interpreter::power_sre<RC1>();
template <bool rec>
void dppc_interpreter::power_srea() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 0x1F;
@ -435,12 +528,16 @@ void dppc_interpreter::power_srea() {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_srea<RC0>();
template void dppc_interpreter::power_srea<RC1>();
template <bool rec>
void dppc_interpreter::power_sreq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -449,24 +546,32 @@ void dppc_interpreter::power_sreq() {
ppc_result_a = ((rot_sh & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
ppc_state.spr[SPR::MQ] = rot_sh;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sreq<RC0>();
template void dppc_interpreter::power_sreq<RC1>();
template <bool rec>
void dppc_interpreter::power_sriq() {
ppc_grab_regssa(ppc_cur_instruction);
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
ppc_result_a = ppc_result_d >> rot_sh;
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_sriq<RC0>();
template void dppc_interpreter::power_sriq<RC1>();
template <bool rec>
void dppc_interpreter::power_srliq() {
ppc_grab_regssa(ppc_cur_instruction);
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
@ -477,12 +582,16 @@ void dppc_interpreter::power_srliq() {
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
ppc_state.spr[SPR::MQ] = r;
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_srliq<RC0>();
template void dppc_interpreter::power_srliq<RC1>();
template <bool rec>
void dppc_interpreter::power_srlq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -496,12 +605,16 @@ void dppc_interpreter::power_srlq() {
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
}
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_srlq<RC0>();
template void dppc_interpreter::power_srlq<RC1>();
template <bool rec>
void dppc_interpreter::power_srq() {
ppc_grab_regssab(ppc_cur_instruction);
unsigned rot_sh = ppc_result_b & 31;
@ -514,8 +627,11 @@ void dppc_interpreter::power_srq() {
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
if (rc_flag)
if (rec)
ppc_changecrf0(ppc_result_a);
ppc_store_iresult_reg(reg_a, ppc_result_a);
}
template void dppc_interpreter::power_srq<RC0>();
template void dppc_interpreter::power_srq<RC1>();

View File

@ -331,9 +331,6 @@ extern bool is_601; // For PowerPC 601 Emulation
extern bool is_altivec; // For Altivec Emulation
extern bool is_64bit; // For PowerPC G5 Emulation
extern bool rc_flag; // Record flag
extern bool oe_flag; // Overflow flag
// Important Addressing Integers
extern uint32_t ppc_cur_instruction;
extern uint32_t ppc_effective_address;
@ -391,6 +388,35 @@ extern void add_ctx_sync_action(const std::function<void()> &);
extern void do_ctx_sync(void);
// The functions used by the PowerPC processor
enum bool_fun {
bool_and = 1,
bool_andc = 2,
bool_eqv = 3,
bool_nand = 4,
bool_nor = 5,
bool_or = 6,
bool_orc = 7,
bool_xor = 8,
};
enum field_setting {
LK0 = 0,
LK1 = 1,
AA0 = 0,
AA1 = 1,
SHFT0 = 0,
SHFT1 = 1,
RC0 = 0,
RC1 = 1,
OV0 = 0,
OV1 = 1,
CARRY0 = 0,
CARRY1 = 1,
IS601 = 0,
NOT601 = 1
};
namespace dppc_interpreter {
template <bool l, bool for601> extern void ppc_bcctr();
template <bool l> extern void ppc_bclr();
@ -404,72 +430,55 @@ extern void ppc_crorc();
extern void ppc_crxor();
extern void ppc_isync();
extern void ppc_add();
extern void ppc_addc();
extern void ppc_adde();
extern void ppc_addme();
extern void ppc_addze();
extern void ppc_and();
extern void ppc_andc();
template <int bool_op, bool rec> extern void ppc_do_bool();
template <bool carry, bool rec, bool ov> extern void ppc_add();
template <bool rec, bool ov> extern void ppc_adde();
template <bool rec, bool ov> extern void ppc_addme();
template <bool rec, bool ov> extern void ppc_addze();
extern void ppc_cmp();
extern void ppc_cmpl();
extern void ppc_cntlzw();
template <bool rec> extern void ppc_cntlzw();
extern void ppc_dcbf();
extern void ppc_dcbi();
extern void ppc_dcbst();
extern void ppc_dcbt();
extern void ppc_dcbtst();
extern void ppc_dcbz();
extern void ppc_divw();
extern void ppc_divwu();
template <bool rec, bool ov> extern void ppc_divw();
template <bool rec, bool ov> extern void ppc_divwu();
extern void ppc_eciwx();
extern void ppc_ecowx();
extern void ppc_eieio();
extern void ppc_eqv();
extern void ppc_extsb();
extern void ppc_extsh();
template <class T, bool rec>extern void ppc_exts();
extern void ppc_icbi();
extern void ppc_mftb();
extern void ppc_lhzux();
extern void ppc_lhzx();
extern void ppc_lhaux();
extern void ppc_lhax();
extern void ppc_lhbrx();
extern void ppc_lwarx();
extern void ppc_lbzux();
extern void ppc_lbzx();
extern void ppc_lwbrx();
extern void ppc_lwzux();
extern void ppc_lwzx();
template <class T> extern void ppc_lzx();
template <class T> extern void ppc_lzux();
extern void ppc_mcrxr();
extern void ppc_mfcr();
extern void ppc_mulhwu();
extern void ppc_mulhw();
extern void ppc_mullw();
extern void ppc_nand();
extern void ppc_neg();
extern void ppc_nor();
extern void ppc_or();
extern void ppc_orc();
extern void ppc_slw();
extern void ppc_srw();
extern void ppc_sraw();
extern void ppc_srawi();
extern void ppc_stbx();
extern void ppc_stbux();
template <bool rec> extern void ppc_mulhwu();
template <bool rec> extern void ppc_mulhw();
template <bool rec, bool ov> extern void ppc_mullw();
template <bool rec, bool ov> extern void ppc_neg();
template <bool left, bool rec> extern void ppc_shift();
template <bool rec> extern void ppc_sraw();
template <bool rec> extern void ppc_srawi();
template <class T> extern void ppc_stx();
template <class T> extern void ppc_stux();
extern void ppc_stfiwx();
extern void ppc_sthx();
extern void ppc_sthux();
extern void ppc_sthbrx();
extern void ppc_stwx();
extern void ppc_stwcx();
extern void ppc_stwux();
extern void ppc_stwbrx();
extern void ppc_subf();
extern void ppc_subfc();
extern void ppc_subfe();
extern void ppc_subfme();
extern void ppc_subfze();
template <bool carry, bool rec, bool ov> extern void ppc_subf();
template <bool rec, bool ov> extern void ppc_subfe();
template <bool rec, bool ov> extern void ppc_subfme();
template <bool rec, bool ov> extern void ppc_subfze();
extern void ppc_sync();
extern void ppc_tlbia();
extern void ppc_tlbie();
@ -477,7 +486,6 @@ extern void ppc_tlbli();
extern void ppc_tlbld();
extern void ppc_tlbsync();
extern void ppc_tw();
extern void ppc_xor();
extern void ppc_lswi();
extern void ppc_lswx();
@ -496,52 +504,39 @@ extern void ppc_mfspr();
extern void ppc_mtmsr();
extern void ppc_mtspr();
extern void ppc_mtfsb0();
extern void ppc_mtfsb1();
template <bool rec> extern void ppc_mtfsb0();
template <bool rec> extern void ppc_mtfsb1();
extern void ppc_mcrfs();
extern void ppc_fmr();
template <bool for601> extern void ppc_mffs();
extern void ppc_mtfsf();
extern void ppc_mtfsfi();
template <bool rec> extern void ppc_fmr();
template <bool for601, bool rec> extern void ppc_mffs();
template <bool rec> extern void ppc_mtfsf();
template <bool rec> extern void ppc_mtfsfi();
extern void ppc_addi();
extern void ppc_addic();
extern void ppc_addicdot();
extern void ppc_addis();
extern void ppc_andidot();
extern void ppc_andisdot();
template <bool shift> extern void ppc_addi();
template <bool rec> extern void ppc_addic();
template <bool shift> extern void ppc_andirc();
template <bool l, bool a> extern void ppc_b();
template <bool l, bool a> extern void ppc_bc();
extern void ppc_cmpi();
extern void ppc_cmpli();
extern void ppc_lbz();
extern void ppc_lbzu();
template <class T> extern void ppc_lz();
template <class T> extern void ppc_lzu();
extern void ppc_lha();
extern void ppc_lhau();
extern void ppc_lhz();
extern void ppc_lhzu();
extern void ppc_lwz();
extern void ppc_lwzu();
extern void ppc_lmw();
extern void ppc_mulli();
extern void ppc_ori();
extern void ppc_oris();
template <bool shift> extern void ppc_ori();
extern void ppc_rfi();
extern void ppc_rlwimi();
extern void ppc_rlwinm();
extern void ppc_rlwnm();
extern void ppc_sc();
extern void ppc_stb();
extern void ppc_stbu();
extern void ppc_sth();
extern void ppc_sthu();
extern void ppc_stw();
extern void ppc_stwu();
template <class T> extern void ppc_st();
template <class T> extern void ppc_stu();
extern void ppc_stmw();
extern void ppc_subfic();
extern void ppc_twi();
extern void ppc_xori();
extern void ppc_xoris();
template <bool shift> extern void ppc_xori();
extern void ppc_lfs();
extern void ppc_lfsu();
@ -560,66 +555,66 @@ extern void ppc_stfdu();
extern void ppc_stfdx();
extern void ppc_stfdux();
extern void ppc_fadd();
extern void ppc_fsub();
extern void ppc_fmul();
extern void ppc_fdiv();
extern void ppc_fadds();
extern void ppc_fsubs();
extern void ppc_fmuls();
extern void ppc_fdivs();
extern void ppc_fmadd();
extern void ppc_fmsub();
extern void ppc_fnmadd();
extern void ppc_fnmsub();
extern void ppc_fmadds();
extern void ppc_fmsubs();
extern void ppc_fnmadds();
extern void ppc_fnmsubs();
extern void ppc_fabs();
extern void ppc_fnabs();
extern void ppc_fneg();
extern void ppc_fsel();
extern void ppc_fres();
extern void ppc_fsqrts();
extern void ppc_fsqrt();
extern void ppc_frsqrte();
extern void ppc_frsp();
extern void ppc_fctiw();
extern void ppc_fctiwz();
template <bool rec> extern void ppc_fadd();
template <bool rec> extern void ppc_fsub();
template <bool rec> extern void ppc_fmul();
template <bool rec> extern void ppc_fdiv();
template <bool rec> extern void ppc_fadds();
template <bool rec> extern void ppc_fsubs();
template <bool rec> extern void ppc_fmuls();
template <bool rec> extern void ppc_fdivs();
template <bool rec> extern void ppc_fmadd();
template <bool rec> extern void ppc_fmsub();
template <bool rec> extern void ppc_fnmadd();
template <bool rec> extern void ppc_fnmsub();
template <bool rec> extern void ppc_fmadds();
template <bool rec> extern void ppc_fmsubs();
template <bool rec> extern void ppc_fnmadds();
template <bool rec> extern void ppc_fnmsubs();
template <bool rec> extern void ppc_fabs();
template <bool rec> extern void ppc_fnabs();
template <bool rec> extern void ppc_fneg();
template <bool rec> extern void ppc_fsel();
template <bool rec> extern void ppc_fres();
template <bool rec> extern void ppc_fsqrts();
template <bool rec> extern void ppc_fsqrt();
template <bool rec> extern void ppc_frsqrte();
template <bool rec> extern void ppc_frsp();
template <bool rec> extern void ppc_fctiw();
template <bool rec> extern void ppc_fctiwz();
extern void ppc_fcmpo();
extern void ppc_fcmpu();
// Power-specific instructions
extern void power_abs();
template <bool rec, bool ov> extern void power_abs();
extern void power_clcs();
extern void power_div();
extern void power_divs();
extern void power_doz();
template <bool rec, bool ov> extern void power_div();
template <bool rec, bool ov> extern void power_divs();
template <bool rec, bool ov> extern void power_doz();
extern void power_dozi();
extern void power_lscbx();
extern void power_maskg();
extern void power_maskir();
extern void power_mul();
extern void power_nabs();
template <bool rec> extern void power_lscbx();
template <bool rec> extern void power_maskg();
template <bool rec> extern void power_maskir();
template <bool rec, bool ov> extern void power_mul();
template <bool rec, bool ov> extern void power_nabs();
extern void power_rlmi();
extern void power_rrib();
extern void power_sle();
extern void power_sleq();
extern void power_sliq();
extern void power_slliq();
extern void power_sllq();
extern void power_slq();
extern void power_sraiq();
extern void power_sraq();
extern void power_sre();
extern void power_srea();
extern void power_sreq();
extern void power_sriq();
extern void power_srliq();
extern void power_srlq();
extern void power_srq();
template <bool rec> extern void power_rrib();
template <bool rec> extern void power_sle();
template <bool rec> extern void power_sleq();
template <bool rec> extern void power_sliq();
template <bool rec> extern void power_slliq();
template <bool rec> extern void power_sllq();
template <bool rec> extern void power_slq();
template <bool rec> extern void power_sraiq();
template <bool rec> extern void power_sraq();
template <bool rec> extern void power_sre();
template <bool rec> extern void power_srea();
template <bool rec> extern void power_sreq();
template <bool rec> extern void power_sriq();
template <bool rec> extern void power_srliq();
template <bool rec> extern void power_srlq();
template <bool rec> extern void power_srq();
} // namespace dppc_interpreter
// AltiVec instructions

View File

@ -44,9 +44,6 @@ Po_Cause power_off_reason = po_enter_debugger;
SetPRS ppc_state;
bool rc_flag = 0; // Record flag
bool oe_flag = 0; // Overflow flag
bool grab_return;
bool grab_breakpoint;
@ -137,41 +134,52 @@ public:
/** Opcode lookup tables. */
/** Primary opcode (bits 0...5) lookup table. */
static PPCOpcode OpcodeGrabber[] = {
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_illegalop,
ppc_illegalop, ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi,
ppc_cmpli, ppc_cmpi, ppc_addic, ppc_addicdot, ppc_addi,
ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19<false>,
ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm, ppc_ori,
ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz,
ppc_lbzu, ppc_stw, ppc_stwu, ppc_stb, ppc_stbu,
ppc_lhz, ppc_lhzu, ppc_lha, ppc_lhau, ppc_sth,
ppc_sthu, ppc_lmw, ppc_stmw, ppc_lfs, ppc_lfsu,
ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu, ppc_stfd,
ppc_stfdu, ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode59,
static PPCOpcode OpcodeGrabber[] = {
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi,
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_mulli,
ppc_subfic, power_dozi, ppc_cmpli, ppc_cmpi,
ppc_addic<RC0>, ppc_addic<RC1>,
ppc_addi<SHFT0>, ppc_addi<SHFT1>,
ppc_opcode16, ppc_sc,
ppc_opcode18, ppc_opcode19<NOT601>,
ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm,
ppc_ori<SHFT0>, ppc_ori<SHFT1>,
ppc_xori<SHFT0>, ppc_xori<SHFT1>,
ppc_andirc<SHFT0>, ppc_andirc<SHFT1>,
ppc_illegalop, ppc_opcode31,
ppc_lz<uint32_t>, ppc_lzu<uint32_t>,
ppc_lz<uint8_t>, ppc_lzu<uint8_t>,
ppc_st<uint32_t>, ppc_stu<uint32_t>,
ppc_st<uint8_t>, ppc_stu<uint8_t>,
ppc_lz<uint16_t>, ppc_lzu<uint16_t>,
ppc_lha, ppc_lhau,
ppc_st<uint16_t>, ppc_stu<uint16_t>,
ppc_lmw, ppc_stmw,
ppc_lfs, ppc_lfsu, ppc_lfd, ppc_lfdu,
ppc_stfs, ppc_stfsu, ppc_stfd, ppc_stfdu,
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode59,
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode63
};
/** Lookup tables for branch instructions. */
static PPCOpcode SubOpcode16Grabber[] = {
dppc_interpreter::ppc_bc<false, false>, //bc
dppc_interpreter::ppc_bc<true, false>, //bcl
dppc_interpreter::ppc_bc<false, true>, //bca
dppc_interpreter::ppc_bc<true, true>}; //bcla
const static PPCOpcode SubOpcode16Grabber[] = {
dppc_interpreter::ppc_bc<LK0, AA0>, // bc
dppc_interpreter::ppc_bc<LK1, AA0>, // bcl
dppc_interpreter::ppc_bc<LK0, AA1>, // bca
dppc_interpreter::ppc_bc<LK1, AA1>}; // bcla
static PPCOpcode SubOpcode18Grabber[] = {
dppc_interpreter::ppc_b<false, false>, //b
dppc_interpreter::ppc_b<true, false>, //bl
dppc_interpreter::ppc_b<false, true>, //ba
dppc_interpreter::ppc_b<true, true>}; //bla
const static PPCOpcode SubOpcode18Grabber[] = {
dppc_interpreter::ppc_b<LK0, AA0>, // b
dppc_interpreter::ppc_b<LK1, AA0>, // bl
dppc_interpreter::ppc_b<LK0, AA1>, // ba
dppc_interpreter::ppc_b<LK1, AA1>}; // bla
/** Instructions decoding tables for integer,
single floating-point, and double-floating point ops respectively */
PPCOpcode SubOpcode31Grabber[1024];
PPCOpcode SubOpcode59Grabber[32];
PPCOpcode SubOpcode63Grabber[1024];
PPCOpcode SubOpcode31Grabber[2048];
PPCOpcode SubOpcode59Grabber[64];
PPCOpcode SubOpcode63Grabber[2048];
/** Exception helpers. */
@ -253,40 +261,36 @@ void ppc_opcode19() {
break;
case 1056:
if (for601)
ppc_bcctr<false, true>();
ppc_bcctr<RC0, IS601>();
else
ppc_bcctr<false, false>();
ppc_bcctr<RC0, NOT601>();
break;
case 1057:
if (for601)
ppc_bcctr<true, true>();
ppc_bcctr<RC1, IS601>();
else
ppc_bcctr<true, false>();
ppc_bcctr<RC1, NOT601>();
break;
default:
ppc_illegalop();
}
}
template void ppc_opcode19<false>();
template void ppc_opcode19<true>();
template void ppc_opcode19<NOT601>();
template void ppc_opcode19<IS601>();
void ppc_opcode31() {
uint16_t subop_grab = (ppc_cur_instruction & 0x7FFUL) >> 1UL;
rc_flag = ppc_cur_instruction & 0x1;
oe_flag = ppc_cur_instruction & 0x400;
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
SubOpcode31Grabber[subop_grab]();
}
void ppc_opcode59() {
uint16_t subop_grab = (ppc_cur_instruction & 0x3EUL) >> 1UL;
rc_flag = ppc_cur_instruction & 0x1;
uint16_t subop_grab = ppc_cur_instruction & 0x3FUL;
SubOpcode59Grabber[subop_grab]();
}
void ppc_opcode63() {
uint16_t subop_grab = (ppc_cur_instruction & 0x7FFUL) >> 1UL;
rc_flag = ppc_cur_instruction & 0x1;
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
SubOpcode63Grabber[subop_grab]();
}
@ -578,182 +582,315 @@ void ppc_exec_dbg(volatile uint32_t start_addr, volatile uint32_t size)
}
void initialize_ppc_opcode_tables() {
std::fill_n(SubOpcode31Grabber, 1024, ppc_illegalop);
std::fill_n(SubOpcode31Grabber, 2048, ppc_illegalop);
SubOpcode31Grabber[0] = ppc_cmp;
SubOpcode31Grabber[4] = ppc_tw;
SubOpcode31Grabber[32] = ppc_cmpl;
SubOpcode31Grabber[8] = ppc_tw;
SubOpcode31Grabber[64] = ppc_cmpl;
SubOpcode31Grabber[8] = SubOpcode31Grabber[520] = ppc_subfc;
SubOpcode31Grabber[40] = SubOpcode31Grabber[552] = ppc_subf;
SubOpcode31Grabber[104] = SubOpcode31Grabber[616] = ppc_neg;
SubOpcode31Grabber[136] = SubOpcode31Grabber[648] = ppc_subfe;
SubOpcode31Grabber[200] = SubOpcode31Grabber[712] = ppc_subfze;
SubOpcode31Grabber[232] = SubOpcode31Grabber[744] = ppc_subfme;
SubOpcode31Grabber[16] = ppc_subf<CARRY1, RC0, OV0>;
SubOpcode31Grabber[17] = ppc_subf<CARRY1, RC1, OV0>;
SubOpcode31Grabber[80] = ppc_subf<CARRY0, RC0, OV0>;
SubOpcode31Grabber[81] = ppc_subf<CARRY0, RC1, OV0>;
SubOpcode31Grabber[208] = ppc_neg<RC0, OV0>;
SubOpcode31Grabber[209] = ppc_neg<RC1, OV0>;
SubOpcode31Grabber[272] = ppc_subfe<RC0, OV0>;
SubOpcode31Grabber[273] = ppc_subfe<RC1, OV0>;
SubOpcode31Grabber[400] = ppc_subfze<RC0, OV0>;
SubOpcode31Grabber[401] = ppc_subfze<RC1, OV0>;
SubOpcode31Grabber[464] = ppc_subfme<RC0, OV0>;
SubOpcode31Grabber[465] = ppc_subfme<RC1, OV0>;
SubOpcode31Grabber[10] = SubOpcode31Grabber[522] = ppc_addc;
SubOpcode31Grabber[138] = SubOpcode31Grabber[650] = ppc_adde;
SubOpcode31Grabber[202] = SubOpcode31Grabber[714] = ppc_addze;
SubOpcode31Grabber[234] = SubOpcode31Grabber[746] = ppc_addme;
SubOpcode31Grabber[266] = SubOpcode31Grabber[778] = ppc_add;
SubOpcode31Grabber[1040] = ppc_subf<CARRY1, RC0, OV1>;
SubOpcode31Grabber[1041] = ppc_subf<CARRY1, RC1, OV1>;
SubOpcode31Grabber[1104] = ppc_subf<CARRY0, RC0, OV1>;
SubOpcode31Grabber[1105] = ppc_subf<CARRY0, RC1, OV1>;
SubOpcode31Grabber[1232] = ppc_neg<RC0, OV1>;
SubOpcode31Grabber[1233] = ppc_neg<RC1, OV1>;
SubOpcode31Grabber[1296] = ppc_subfe<RC0, OV1>;
SubOpcode31Grabber[1297] = ppc_subfe<RC1, OV1>;
SubOpcode31Grabber[1424] = ppc_subfze<RC0, OV1>;
SubOpcode31Grabber[1425] = ppc_subfze<RC1, OV1>;
SubOpcode31Grabber[1488] = ppc_subfme<RC0, OV1>;
SubOpcode31Grabber[1489] = ppc_subfme<RC1, OV1>;
SubOpcode31Grabber[11] = ppc_mulhwu;
SubOpcode31Grabber[75] = ppc_mulhw;
SubOpcode31Grabber[235] = SubOpcode31Grabber[747] = ppc_mullw;
SubOpcode31Grabber[459] = SubOpcode31Grabber[971] = ppc_divwu;
SubOpcode31Grabber[491] = SubOpcode31Grabber[1003] = ppc_divw;
SubOpcode31Grabber[20] = ppc_add<CARRY1, RC0, OV0>;
SubOpcode31Grabber[21] = ppc_add<CARRY1, RC1, OV0>;
SubOpcode31Grabber[276] = ppc_adde<RC0, OV0>;
SubOpcode31Grabber[277] = ppc_adde<RC1, OV0>;
SubOpcode31Grabber[404] = ppc_addze<RC0, OV0>;
SubOpcode31Grabber[405] = ppc_addze<RC1, OV0>;
SubOpcode31Grabber[468] = ppc_addme<RC0, OV0>;
SubOpcode31Grabber[469] = ppc_addme<RC1, OV0>;
SubOpcode31Grabber[532] = ppc_add<CARRY0, RC0, OV0>;
SubOpcode31Grabber[533] = ppc_add<CARRY0, RC1, OV0>;
SubOpcode31Grabber[20] = ppc_lwarx;
SubOpcode31Grabber[23] = ppc_lwzx;
SubOpcode31Grabber[55] = ppc_lwzux;
SubOpcode31Grabber[87] = ppc_lbzx;
SubOpcode31Grabber[119] = ppc_lbzux;
SubOpcode31Grabber[279] = ppc_lhzx;
SubOpcode31Grabber[311] = ppc_lhzux;
SubOpcode31Grabber[343] = ppc_lhax;
SubOpcode31Grabber[375] = ppc_lhaux;
SubOpcode31Grabber[533] = ppc_lswx;
SubOpcode31Grabber[534] = ppc_lwbrx;
SubOpcode31Grabber[535] = ppc_lfsx;
SubOpcode31Grabber[567] = ppc_lfsux;
SubOpcode31Grabber[597] = ppc_lswi;
SubOpcode31Grabber[599] = ppc_lfdx;
SubOpcode31Grabber[631] = ppc_lfdux;
SubOpcode31Grabber[790] = ppc_lhbrx;
SubOpcode31Grabber[1044] = ppc_add<CARRY1, RC0, OV1>;
SubOpcode31Grabber[1045] = ppc_add<CARRY1, RC1, OV1>;
SubOpcode31Grabber[1300] = ppc_adde<RC0, OV1>;
SubOpcode31Grabber[1301] = ppc_adde<RC1, OV1>;
SubOpcode31Grabber[1428] = ppc_addze<RC0, OV1>;
SubOpcode31Grabber[1429] = ppc_addze<RC1, OV1>;
SubOpcode31Grabber[1492] = ppc_addme<RC0, OV1>;
SubOpcode31Grabber[1493] = ppc_addme<RC1, OV1>;
SubOpcode31Grabber[1556] = ppc_add<CARRY0, RC0, OV1>;
SubOpcode31Grabber[1557] = ppc_add<CARRY0, RC1, OV1>;
SubOpcode31Grabber[150] = ppc_stwcx;
SubOpcode31Grabber[151] = ppc_stwx;
SubOpcode31Grabber[183] = ppc_stwux;
SubOpcode31Grabber[215] = ppc_stbx;
SubOpcode31Grabber[247] = ppc_stbux;
SubOpcode31Grabber[407] = ppc_sthx;
SubOpcode31Grabber[439] = ppc_sthux;
SubOpcode31Grabber[661] = ppc_stswx;
SubOpcode31Grabber[662] = ppc_stwbrx;
SubOpcode31Grabber[663] = ppc_stfsx;
SubOpcode31Grabber[695] = ppc_stfsux;
SubOpcode31Grabber[725] = ppc_stswi;
SubOpcode31Grabber[727] = ppc_stfdx;
SubOpcode31Grabber[759] = ppc_stfdux;
SubOpcode31Grabber[918] = ppc_sthbrx;
SubOpcode31Grabber[983] = ppc_stfiwx;
SubOpcode31Grabber[22] = ppc_mulhwu<RC0>;
SubOpcode31Grabber[23] = ppc_mulhwu<RC1>;
SubOpcode31Grabber[150] = ppc_mulhw<RC0>;
SubOpcode31Grabber[151] = ppc_mulhw<RC1>;
SubOpcode31Grabber[470] = ppc_mullw<RC0, OV0>;
SubOpcode31Grabber[471] = ppc_mullw<RC1, OV0>;
SubOpcode31Grabber[918] = ppc_divwu<RC0, OV0>;
SubOpcode31Grabber[919] = ppc_divwu<RC1, OV0>;
SubOpcode31Grabber[982] = ppc_divw<RC0, OV0>;
SubOpcode31Grabber[983] = ppc_divw<RC1, OV0>;
SubOpcode31Grabber[310] = ppc_eciwx;
SubOpcode31Grabber[438] = ppc_ecowx;
SubOpcode31Grabber[1494] = ppc_mullw<RC0, OV1>;
SubOpcode31Grabber[1495] = ppc_mullw<RC1, OV1>;
SubOpcode31Grabber[1942] = ppc_divwu<RC0, OV1>;
SubOpcode31Grabber[1943] = ppc_divwu<RC1, OV1>;
SubOpcode31Grabber[2006] = ppc_divw<RC0, OV1>;
SubOpcode31Grabber[2007] = ppc_divw<RC1, OV1>;
SubOpcode31Grabber[24] = ppc_slw;
SubOpcode31Grabber[28] = ppc_and;
SubOpcode31Grabber[60] = ppc_andc;
SubOpcode31Grabber[124] = ppc_nor;
SubOpcode31Grabber[284] = ppc_eqv;
SubOpcode31Grabber[316] = ppc_xor;
SubOpcode31Grabber[412] = ppc_orc;
SubOpcode31Grabber[444] = ppc_or;
SubOpcode31Grabber[476] = ppc_nand;
SubOpcode31Grabber[536] = ppc_srw;
SubOpcode31Grabber[792] = ppc_sraw;
SubOpcode31Grabber[824] = ppc_srawi;
SubOpcode31Grabber[922] = ppc_extsh;
SubOpcode31Grabber[954] = ppc_extsb;
SubOpcode31Grabber[40] = ppc_lwarx;
SubOpcode31Grabber[46] = ppc_lzx<uint32_t>;
SubOpcode31Grabber[110] = ppc_lzux<uint32_t>;
SubOpcode31Grabber[174] = ppc_lzx<uint8_t>;
SubOpcode31Grabber[238] = ppc_lzux<uint8_t>;
SubOpcode31Grabber[558] = ppc_lzx<uint16_t>;
SubOpcode31Grabber[622] = ppc_lzux<uint16_t>;
SubOpcode31Grabber[686] = ppc_lhax;
SubOpcode31Grabber[750] = ppc_lhaux;
SubOpcode31Grabber[1066] = ppc_lswx;
SubOpcode31Grabber[1068] = ppc_lwbrx;
SubOpcode31Grabber[1070] = ppc_lfsx;
SubOpcode31Grabber[1134] = ppc_lfsux;
SubOpcode31Grabber[1194] = ppc_lswi;
SubOpcode31Grabber[1198] = ppc_lfdx;
SubOpcode31Grabber[1262] = ppc_lfdux;
SubOpcode31Grabber[1580] = ppc_lhbrx;
SubOpcode31Grabber[26] = ppc_cntlzw;
SubOpcode31Grabber[301] = ppc_stwcx;
SubOpcode31Grabber[302] = ppc_stx<uint32_t>;
SubOpcode31Grabber[366] = ppc_stux<uint32_t>;
SubOpcode31Grabber[430] = ppc_stx<uint8_t>;
SubOpcode31Grabber[494] = ppc_stux<uint8_t>;
SubOpcode31Grabber[814] = ppc_stx<uint16_t>;
SubOpcode31Grabber[878] = ppc_stux<uint16_t>;
SubOpcode31Grabber[1322] = ppc_stswx;
SubOpcode31Grabber[1324] = ppc_stwbrx;
SubOpcode31Grabber[1326] = ppc_stfsx;
SubOpcode31Grabber[1390] = ppc_stfsux;
SubOpcode31Grabber[1450] = ppc_stswi;
SubOpcode31Grabber[1454] = ppc_stfdx;
SubOpcode31Grabber[1518] = ppc_stfdux;
SubOpcode31Grabber[1836] = ppc_sthbrx;
SubOpcode31Grabber[1966] = ppc_stfiwx;
SubOpcode31Grabber[19] = ppc_mfcr;
SubOpcode31Grabber[83] = ppc_mfmsr;
SubOpcode31Grabber[144] = ppc_mtcrf;
SubOpcode31Grabber[146] = ppc_mtmsr;
SubOpcode31Grabber[210] = ppc_mtsr;
SubOpcode31Grabber[242] = ppc_mtsrin;
SubOpcode31Grabber[339] = ppc_mfspr;
SubOpcode31Grabber[371] = ppc_mftb;
SubOpcode31Grabber[467] = ppc_mtspr;
SubOpcode31Grabber[512] = ppc_mcrxr;
SubOpcode31Grabber[595] = ppc_mfsr;
SubOpcode31Grabber[659] = ppc_mfsrin;
SubOpcode31Grabber[620] = ppc_eciwx;
SubOpcode31Grabber[876] = ppc_ecowx;
SubOpcode31Grabber[54] = ppc_dcbst;
SubOpcode31Grabber[86] = ppc_dcbf;
SubOpcode31Grabber[246] = ppc_dcbtst;
SubOpcode31Grabber[278] = ppc_dcbt;
SubOpcode31Grabber[598] = ppc_sync;
SubOpcode31Grabber[470] = ppc_dcbi;
SubOpcode31Grabber[1014] = ppc_dcbz;
SubOpcode31Grabber[48] = ppc_shift<SHFT1, RC0>;
SubOpcode31Grabber[49] = ppc_shift<SHFT1, RC1>;
SubOpcode31Grabber[56] = ppc_do_bool<bool_and, RC0>;
SubOpcode31Grabber[57] = ppc_do_bool<bool_and, RC1>;
SubOpcode31Grabber[120] = ppc_do_bool<bool_andc, RC0>;
SubOpcode31Grabber[121] = ppc_do_bool<bool_andc, RC1>;
SubOpcode31Grabber[248] = ppc_do_bool<bool_nor, RC0>;
SubOpcode31Grabber[249] = ppc_do_bool<bool_nor, RC1>;
SubOpcode31Grabber[568] = ppc_do_bool<bool_eqv, RC0>;
SubOpcode31Grabber[569] = ppc_do_bool<bool_eqv, RC1>;
SubOpcode31Grabber[632] = ppc_do_bool<bool_xor, RC0>;
SubOpcode31Grabber[633] = ppc_do_bool<bool_xor, RC1>;
SubOpcode31Grabber[824] = ppc_do_bool<bool_orc, RC0>;
SubOpcode31Grabber[825] = ppc_do_bool<bool_orc, RC1>;
SubOpcode31Grabber[888] = ppc_do_bool<bool_or, RC0>;
SubOpcode31Grabber[889] = ppc_do_bool<bool_or, RC1>;
SubOpcode31Grabber[952] = ppc_do_bool<bool_nand, RC0>;
SubOpcode31Grabber[953] = ppc_do_bool<bool_nand, RC1>;
SubOpcode31Grabber[1072] = ppc_shift<SHFT0, RC0>;
SubOpcode31Grabber[1073] = ppc_shift<SHFT0, RC1>;
SubOpcode31Grabber[1584] = ppc_sraw<RC0>;
SubOpcode31Grabber[1585] = ppc_sraw<RC1>;
SubOpcode31Grabber[1648] = ppc_srawi<RC0>;
SubOpcode31Grabber[1649] = ppc_srawi<RC1>;
SubOpcode31Grabber[1844] = ppc_exts<int16_t, RC0>;
SubOpcode31Grabber[1845] = ppc_exts<int16_t, RC1>;
SubOpcode31Grabber[1908] = ppc_exts<int8_t, RC0>;
SubOpcode31Grabber[1909] = ppc_exts<int8_t, RC1>;
SubOpcode31Grabber[29] = power_maskg;
SubOpcode31Grabber[107] = SubOpcode31Grabber[619] = power_mul;
SubOpcode31Grabber[152] = power_slq;
SubOpcode31Grabber[153] = power_sle;
SubOpcode31Grabber[184] = power_sliq;
SubOpcode31Grabber[216] = power_sllq;
SubOpcode31Grabber[217] = power_sleq;
SubOpcode31Grabber[248] = power_slliq;
SubOpcode31Grabber[264] = SubOpcode31Grabber[776] = power_doz;
SubOpcode31Grabber[277] = power_lscbx;
SubOpcode31Grabber[331] = SubOpcode31Grabber[843] = power_div;
SubOpcode31Grabber[360] = SubOpcode31Grabber[872] = power_abs;
SubOpcode31Grabber[363] = SubOpcode31Grabber[875] = power_divs;
SubOpcode31Grabber[488] = SubOpcode31Grabber[1000] = power_nabs;
SubOpcode31Grabber[531] = power_clcs;
SubOpcode31Grabber[537] = power_rrib;
SubOpcode31Grabber[541] = power_maskir;
SubOpcode31Grabber[664] = power_srq;
SubOpcode31Grabber[665] = power_sre;
SubOpcode31Grabber[696] = power_sriq;
SubOpcode31Grabber[728] = power_srlq;
SubOpcode31Grabber[729] = power_sreq;
SubOpcode31Grabber[760] = power_srliq;
SubOpcode31Grabber[920] = power_sraq;
SubOpcode31Grabber[921] = power_srea;
SubOpcode31Grabber[952] = power_sraiq;
SubOpcode31Grabber[52] = ppc_cntlzw<RC0>;
SubOpcode31Grabber[53] = ppc_cntlzw<RC1>;
SubOpcode31Grabber[306] = ppc_tlbie;
SubOpcode31Grabber[370] = ppc_tlbia;
SubOpcode31Grabber[566] = ppc_tlbsync;
SubOpcode31Grabber[854] = ppc_eieio;
SubOpcode31Grabber[982] = ppc_icbi;
SubOpcode31Grabber[978] = ppc_tlbld;
SubOpcode31Grabber[1010] = ppc_tlbli;
SubOpcode31Grabber[38] = ppc_mfcr;
SubOpcode31Grabber[166] = ppc_mfmsr;
SubOpcode31Grabber[288] = ppc_mtcrf;
SubOpcode31Grabber[292] = ppc_mtmsr;
SubOpcode31Grabber[420] = ppc_mtsr;
SubOpcode31Grabber[484] = ppc_mtsrin;
SubOpcode31Grabber[678] = ppc_mfspr;
SubOpcode31Grabber[742] = ppc_mftb;
SubOpcode31Grabber[934] = ppc_mtspr;
SubOpcode31Grabber[1024] = ppc_mcrxr;
SubOpcode31Grabber[1190] = ppc_mfsr;
SubOpcode31Grabber[1318] = ppc_mfsrin;
std::fill_n(SubOpcode59Grabber, 32, ppc_illegalop);
SubOpcode59Grabber[18] = ppc_fdivs;
SubOpcode59Grabber[20] = ppc_fsubs;
SubOpcode59Grabber[21] = ppc_fadds;
SubOpcode59Grabber[22] = ppc_fsqrts;
SubOpcode59Grabber[24] = ppc_fres;
SubOpcode59Grabber[25] = ppc_fmuls;
SubOpcode59Grabber[28] = ppc_fmsubs;
SubOpcode59Grabber[29] = ppc_fmadds;
SubOpcode59Grabber[30] = ppc_fnmsubs;
SubOpcode59Grabber[31] = ppc_fnmadds;
SubOpcode31Grabber[108] = ppc_dcbst;
SubOpcode31Grabber[172] = ppc_dcbf;
SubOpcode31Grabber[492] = ppc_dcbtst;
SubOpcode31Grabber[556] = ppc_dcbt;
SubOpcode31Grabber[940] = ppc_dcbi;
SubOpcode31Grabber[1196] = ppc_sync;
SubOpcode31Grabber[2028] = ppc_dcbz;
std::fill_n(SubOpcode63Grabber, 1024, ppc_illegalop);
SubOpcode63Grabber[0] = ppc_fcmpu;
SubOpcode63Grabber[12] = ppc_frsp;
SubOpcode63Grabber[14] = ppc_fctiw;
SubOpcode63Grabber[15] = ppc_fctiwz;
SubOpcode63Grabber[18] = ppc_fdiv;
SubOpcode63Grabber[20] = ppc_fsub;
SubOpcode63Grabber[21] = ppc_fadd;
SubOpcode63Grabber[22] = ppc_fsqrt;
SubOpcode63Grabber[26] = ppc_frsqrte;
SubOpcode63Grabber[32] = ppc_fcmpo;
SubOpcode63Grabber[38] = ppc_mtfsb1;
SubOpcode63Grabber[40] = ppc_fneg;
SubOpcode63Grabber[64] = ppc_mcrfs;
SubOpcode63Grabber[70] = ppc_mtfsb0;
SubOpcode63Grabber[72] = ppc_fmr;
SubOpcode63Grabber[134] = ppc_mtfsfi;
SubOpcode63Grabber[136] = ppc_fnabs;
SubOpcode63Grabber[264] = ppc_fabs;
SubOpcode63Grabber[583] = ppc_mffs<false>;
SubOpcode63Grabber[711] = ppc_mtfsf;
SubOpcode31Grabber[58] = power_maskg<RC0>;
SubOpcode31Grabber[59] = power_maskg<RC1>;
SubOpcode31Grabber[214] = power_mul<RC0, OV0>;
SubOpcode31Grabber[215] = power_mul<RC1, OV0>;
SubOpcode31Grabber[304] = power_slq<RC0>;
SubOpcode31Grabber[305] = power_slq<RC1>;
SubOpcode31Grabber[306] = power_sle<RC0>;
SubOpcode31Grabber[306] = power_sle<RC1>;
SubOpcode31Grabber[368] = power_sliq<RC0>;
SubOpcode31Grabber[369] = power_sliq<RC1>;
SubOpcode31Grabber[432] = power_sllq<RC0>;
SubOpcode31Grabber[433] = power_sllq<RC1>;
SubOpcode31Grabber[434] = power_sleq<RC0>;
SubOpcode31Grabber[435] = power_sleq<RC1>;
SubOpcode31Grabber[496] = power_slliq<RC0>;
SubOpcode31Grabber[497] = power_slliq<RC1>;
SubOpcode31Grabber[528] = power_doz<RC0, OV0>;
SubOpcode31Grabber[529] = power_doz<RC1, OV0>;
SubOpcode31Grabber[554] = power_lscbx<RC0>;
SubOpcode31Grabber[555] = power_lscbx<RC1>;
SubOpcode31Grabber[662] = power_div<RC0, OV0>;
SubOpcode31Grabber[663] = power_div<RC1, OV0>;
SubOpcode31Grabber[720] = power_abs<RC0, OV0>;
SubOpcode31Grabber[721] = power_abs<RC1, OV0>;
SubOpcode31Grabber[726] = power_divs<RC0, OV0>;
SubOpcode31Grabber[727] = power_divs<RC1, OV0>;
SubOpcode31Grabber[976] = power_nabs<RC0, OV0>;
SubOpcode31Grabber[977] = power_nabs<RC1, OV0>;
SubOpcode31Grabber[1062] = power_clcs;
SubOpcode31Grabber[1074] = power_rrib<RC0>;
SubOpcode31Grabber[1075] = power_rrib<RC1>;
SubOpcode31Grabber[1082] = power_maskir<RC0>;
SubOpcode31Grabber[1083] = power_maskir<RC1>;
SubOpcode31Grabber[1328] = power_srq<RC0>;
SubOpcode31Grabber[1329] = power_srq<RC1>;
SubOpcode31Grabber[1330] = power_sre<RC0>;
SubOpcode31Grabber[1331] = power_sre<RC1>;
SubOpcode31Grabber[1332] = power_sriq<RC0>;
SubOpcode31Grabber[1333] = power_sriq<RC1>;
SubOpcode31Grabber[1456] = power_srlq<RC0>;
SubOpcode31Grabber[1457] = power_srlq<RC1>;
SubOpcode31Grabber[1458] = power_sreq<RC0>;
SubOpcode31Grabber[1459] = power_sreq<RC1>;
SubOpcode31Grabber[1520] = power_srliq<RC0>;
SubOpcode31Grabber[1521] = power_srliq<RC1>;
SubOpcode31Grabber[1840] = power_sraq<RC0>;
SubOpcode31Grabber[1841] = power_sraq<RC1>;
SubOpcode31Grabber[1842] = power_srea<RC0>;
SubOpcode31Grabber[1843] = power_srea<RC1>;
SubOpcode31Grabber[1904] = power_sraiq<RC0>;
SubOpcode31Grabber[1905] = power_sraiq<RC1>;
for (int i = 0; i < 1024; i += 32) {
SubOpcode63Grabber[i + 23] = ppc_fsel;
SubOpcode63Grabber[i + 25] = ppc_fmul;
SubOpcode63Grabber[i + 28] = ppc_fmsub;
SubOpcode63Grabber[i + 29] = ppc_fmadd;
SubOpcode63Grabber[i + 30] = ppc_fnmsub;
SubOpcode63Grabber[i + 31] = ppc_fnmadd;
SubOpcode31Grabber[1238] = power_mul<RC0, OV1>;
SubOpcode31Grabber[1239] = power_mul<RC1, OV1>;
SubOpcode31Grabber[1552] = power_doz<RC0, OV1>;
SubOpcode31Grabber[1553] = power_doz<RC1, OV1>;
SubOpcode31Grabber[1686] = power_div<RC0, OV1>;
SubOpcode31Grabber[1687] = power_div<RC1, OV1>;
SubOpcode31Grabber[1744] = power_abs<RC0, OV1>;
SubOpcode31Grabber[1745] = power_abs<RC1, OV1>;
SubOpcode31Grabber[1750] = power_divs<RC0, OV1>;
SubOpcode31Grabber[1751] = power_divs<RC1, OV1>;
SubOpcode31Grabber[2000] = power_nabs<RC0, OV1>;
SubOpcode31Grabber[2001] = power_nabs<RC1, OV1>;
SubOpcode31Grabber[612] = ppc_tlbie;
SubOpcode31Grabber[740] = ppc_tlbia;
SubOpcode31Grabber[1132] = ppc_tlbsync;
SubOpcode31Grabber[1708] = ppc_eieio;
SubOpcode31Grabber[1964] = ppc_icbi;
SubOpcode31Grabber[1956] = ppc_tlbld;
SubOpcode31Grabber[2020] = ppc_tlbli;
std::fill_n(SubOpcode59Grabber, 64, ppc_illegalop);
SubOpcode59Grabber[36] = ppc_fdivs<RC0>;
SubOpcode59Grabber[37] = ppc_fdivs<RC1>;
SubOpcode59Grabber[40] = ppc_fsubs<RC0>;
SubOpcode59Grabber[41] = ppc_fsubs<RC1>;
SubOpcode59Grabber[42] = ppc_fadds<RC0>;
SubOpcode59Grabber[43] = ppc_fadds<RC1>;
SubOpcode59Grabber[44] = ppc_fsqrts<RC0>;
SubOpcode59Grabber[45] = ppc_fsqrts<RC1>;
SubOpcode59Grabber[48] = ppc_fres<RC0>;
SubOpcode59Grabber[49] = ppc_fres<RC1>;
SubOpcode59Grabber[50] = ppc_fmuls<RC0>;
SubOpcode59Grabber[51] = ppc_fmuls<RC1>;
SubOpcode59Grabber[56] = ppc_fmsubs<RC0>;
SubOpcode59Grabber[57] = ppc_fmsubs<RC1>;
SubOpcode59Grabber[58] = ppc_fmadds<RC0>;
SubOpcode59Grabber[59] = ppc_fmadds<RC1>;
SubOpcode59Grabber[60] = ppc_fnmsubs<RC0>;
SubOpcode59Grabber[61] = ppc_fnmsubs<RC1>;
SubOpcode59Grabber[62] = ppc_fnmadds<RC0>;
SubOpcode59Grabber[63] = ppc_fnmadds<RC1>;
std::fill_n(SubOpcode63Grabber, 2048, ppc_illegalop);
SubOpcode63Grabber[0] = ppc_fcmpu;
SubOpcode63Grabber[24] = ppc_frsp<RC0>;
SubOpcode63Grabber[25] = ppc_frsp<RC1>;
SubOpcode63Grabber[28] = ppc_fctiw<RC0>;
SubOpcode63Grabber[29] = ppc_fctiw<RC1>;
SubOpcode63Grabber[30] = ppc_fctiwz<RC0>;
SubOpcode63Grabber[31] = ppc_fctiwz<RC1>;
SubOpcode63Grabber[36] = ppc_fdiv<RC0>;
SubOpcode63Grabber[37] = ppc_fdiv<RC1>;
SubOpcode63Grabber[40] = ppc_fsub<RC0>;
SubOpcode63Grabber[41] = ppc_fsub<RC1>;
SubOpcode63Grabber[42] = ppc_fadd<RC0>;
SubOpcode63Grabber[43] = ppc_fadd<RC1>;
SubOpcode63Grabber[44] = ppc_fsqrt<RC0>;
SubOpcode63Grabber[45] = ppc_fsqrt<RC1>;
SubOpcode63Grabber[52] = ppc_frsqrte<RC0>;
SubOpcode63Grabber[53] = ppc_frsqrte<RC1>;
SubOpcode63Grabber[64] = ppc_fcmpo;
SubOpcode63Grabber[76] = ppc_mtfsb1<RC0>;
SubOpcode63Grabber[77] = ppc_mtfsb1<RC1>;
SubOpcode63Grabber[80] = ppc_fneg<RC0>;
SubOpcode63Grabber[81] = ppc_fneg<RC1>;
SubOpcode63Grabber[128] = ppc_mcrfs;
SubOpcode63Grabber[140] = ppc_mtfsb0<RC0>;
SubOpcode63Grabber[141] = ppc_mtfsb0<RC1>;
SubOpcode63Grabber[144] = ppc_fmr<RC0>;
SubOpcode63Grabber[145] = ppc_fmr<RC1>;
SubOpcode63Grabber[268] = ppc_mtfsfi<RC0>;
SubOpcode63Grabber[269] = ppc_mtfsfi<RC1>;
SubOpcode63Grabber[272] = ppc_fnabs<RC0>;
SubOpcode63Grabber[273] = ppc_fnabs<RC1>;
SubOpcode63Grabber[528] = ppc_fabs<RC0>;
SubOpcode63Grabber[529] = ppc_fabs<RC1>;
SubOpcode63Grabber[1166] = ppc_mffs<IS601, RC0>;
SubOpcode63Grabber[1167] = ppc_mffs<IS601, RC1>;
SubOpcode63Grabber[1422] = ppc_mtfsf<RC0>;
SubOpcode63Grabber[1423] = ppc_mtfsf<RC1>;
for (int i = 0; i < 2048; i += 64) {
SubOpcode63Grabber[i + 46] = ppc_fsel<RC0>;
SubOpcode63Grabber[i + 47] = ppc_fsel<RC1>;
SubOpcode63Grabber[i + 50] = ppc_fmul<RC0>;
SubOpcode63Grabber[i + 51] = ppc_fmul<RC1>;
SubOpcode63Grabber[i + 56] = ppc_fmsub<RC0>;
SubOpcode63Grabber[i + 57] = ppc_fmsub<RC1>;
SubOpcode63Grabber[i + 58] = ppc_fmadd<RC0>;
SubOpcode63Grabber[i + 59] = ppc_fmadd<RC1>;
SubOpcode63Grabber[i + 60] = ppc_fnmsub<RC0>;
SubOpcode63Grabber[i + 61] = ppc_fnmsub<RC1>;
SubOpcode63Grabber[i + 62] = ppc_fnmadd<RC0>;
SubOpcode63Grabber[i + 63] = ppc_fnmadd<RC1>;
}
}
@ -777,19 +914,23 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
initialize_ppc_opcode_tables();
if (cpu_version == PPC_VER::MPC601) {
OpcodeGrabber[19] = ppc_opcode19<true>;
SubOpcode31Grabber[370] = ppc_illegalop; // tlbia
SubOpcode31Grabber[371] = ppc_illegalop; // mftb
SubOpcode59Grabber[24] = ppc_illegalop; // fres
SubOpcode63Grabber[26] = ppc_illegalop; // frsqrte
SubOpcode63Grabber[583] = ppc_mffs<true>;
for (int i = 0; i < 1024; i += 32) {
SubOpcode63Grabber[i + 23] = ppc_illegalop; // fsel
OpcodeGrabber[19] = ppc_opcode19<IS601>;
SubOpcode31Grabber[740] = ppc_illegalop; // tlbia
SubOpcode31Grabber[742] = ppc_illegalop; // mftb
SubOpcode59Grabber[48] = ppc_illegalop; // fres
SubOpcode63Grabber[52] = ppc_illegalop; // frsqrte
SubOpcode63Grabber[1166] = ppc_mffs<IS601, RC0>;
SubOpcode63Grabber[1167] = ppc_mffs<IS601, RC1>;
for (int i = 0; i < 2048; i += 64) {
SubOpcode63Grabber[i + 46] = ppc_illegalop; // fsel
SubOpcode63Grabber[i + 47] = ppc_illegalop; // fsel.
}
}
if (cpu_version != PPC_VER::MPC970MP) {
SubOpcode59Grabber[22] = ppc_illegalop; // fsqrts
SubOpcode63Grabber[22] = ppc_illegalop; // fsqrt
SubOpcode59Grabber[44] = ppc_illegalop; // fsqrts
SubOpcode59Grabber[45] = ppc_illegalop; // fsqrts.
SubOpcode63Grabber[44] = ppc_illegalop; // fsqrt
SubOpcode63Grabber[45] = ppc_illegalop; // fsqrt.
}
// initialize emulator timers

View File

@ -92,7 +92,7 @@ void update_fex() {
}
template <const FPOP fpop>
void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, bool rc_flag = false) {
void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, bool rec = false) {
double input_a = ppc_state.fpr[chosen_reg_1].dbl64_r;
double input_b = ppc_state.fpr[chosen_reg_2].dbl64_r;
@ -156,145 +156,178 @@ static void fpresult_update(double set_result) {
}
// Floating Point Arithmetic
template <bool rec>
void dppc_interpreter::ppc_fadd() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_state.fpscr |= FPCC_FUNAN;
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = val_reg_a + val_reg_b;
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fadd<RC0>();
template void dppc_interpreter::ppc_fadd<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fsub() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_state.fpscr |= FPCC_FUNAN;
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = val_reg_a - val_reg_b;
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fsub<RC0>();
template void dppc_interpreter::ppc_fsub<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fdiv() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<DIV>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<DIV>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = val_reg_a / val_reg_b;
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fdiv<RC0>();
template void dppc_interpreter::ppc_fdiv<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmul() {
ppc_grab_regsfpdac(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
double ppc_dblresult64_d = val_reg_a * val_reg_c;
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmul<RC0>();
template void dppc_interpreter::ppc_fmul<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmadd() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmadd<RC0>();
template void dppc_interpreter::ppc_fmadd<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmsub() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, -val_reg_b);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmsub<RC0>();
template void dppc_interpreter::ppc_fmsub<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fnmadd() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, val_reg_b);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fnmadd<RC0>();
template void dppc_interpreter::ppc_fnmadd<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fnmsub() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = std::fma(-val_reg_a, val_reg_c, val_reg_b);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fnmsub<RC0>();
template void dppc_interpreter::ppc_fnmsub<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fadds() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
float ppc_fltresult32_d = val_reg_a + val_reg_b;
@ -303,127 +336,159 @@ void dppc_interpreter::ppc_fadds() {
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fadds<RC0>();
template void dppc_interpreter::ppc_fadds<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fsubs() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = (float)(val_reg_a - val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fsubs<RC0>();
template void dppc_interpreter::ppc_fsubs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fdivs() {
ppc_grab_regsfpdab(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<DIV>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<DIV>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = (float)(val_reg_a / val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fdivs<RC0>();
template void dppc_interpreter::ppc_fdivs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmuls() {
ppc_grab_regsfpdac(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
double ppc_dblresult64_d = (float)(val_reg_a * val_reg_c);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmuls<RC0>();
template void dppc_interpreter::ppc_fmuls<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmadds() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmadds<RC0>();
template void dppc_interpreter::ppc_fmadds<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fmsubs() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, -val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fmsubs<RC0>();
template void dppc_interpreter::ppc_fmsubs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fnmadds() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<ADD>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fnmadds<RC0>();
template void dppc_interpreter::ppc_fnmadds<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fnmsubs() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
if (std::isnan(val_reg_a) || std::isnan(val_reg_c)) {
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rc_flag);
ppc_confirm_inf_nan<MUL>(reg_a, reg_c, rec);
}
if (std::isnan(val_reg_b)) {
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rc_flag);
ppc_confirm_inf_nan<SUB>(reg_a, reg_b, rec);
}
double ppc_dblresult64_d = (float)std::fma(-val_reg_a, val_reg_c, val_reg_b);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
fpresult_update(ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fnmsubs<RC0>();
template void dppc_interpreter::ppc_fnmsubs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fabs() {
ppc_grab_regsfpdb(ppc_cur_instruction);
@ -431,10 +496,14 @@ void dppc_interpreter::ppc_fabs() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fabs<RC0>();
template void dppc_interpreter::ppc_fabs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fnabs() {
ppc_grab_regsfpdb(ppc_cur_instruction);
@ -443,10 +512,14 @@ void dppc_interpreter::ppc_fnabs() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fnabs<RC0>();
template void dppc_interpreter::ppc_fnabs<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fneg() {
ppc_grab_regsfpdb(ppc_cur_instruction);
@ -454,10 +527,14 @@ void dppc_interpreter::ppc_fneg() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fneg<RC0>();
template void dppc_interpreter::ppc_fneg<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fsel() {
ppc_grab_regsfpdabc(ppc_cur_instruction);
@ -465,54 +542,74 @@ void dppc_interpreter::ppc_fsel() {
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fsel<RC0>();
template void dppc_interpreter::ppc_fsel<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fsqrt() {
ppc_grab_regsfpdb(ppc_cur_instruction);
double testd2 = (double)(GET_FPR(reg_b));
double ppc_dblresult64_d = std::sqrt(testd2);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rc_flag);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rec);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fsqrt<RC0>();
template void dppc_interpreter::ppc_fsqrt<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fsqrts() {
ppc_grab_regsfpdb(ppc_cur_instruction);
double testd2 = (double)(GET_FPR(reg_b));
double ppc_dblresult64_d = (float)std::sqrt(testd2);
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rc_flag);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rec);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_fsqrts<RC0>();
template void dppc_interpreter::ppc_fsqrts<RC1>();
template <bool rec>
void dppc_interpreter::ppc_frsqrte() {
ppc_grab_regsfpdb(ppc_cur_instruction);
double testd2 = (double)(GET_FPR(reg_b));
double ppc_dblresult64_d = 1.0 / sqrt(testd2);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rc_flag);
ppc_confirm_inf_nan<SQRT>(0, reg_b, rec);
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_frsqrte<RC0>();
template void dppc_interpreter::ppc_frsqrte<RC1>();
template <bool rec>
void dppc_interpreter::ppc_frsp() {
ppc_grab_regsfpdb(ppc_cur_instruction);
double ppc_dblresult64_d = (float)(GET_FPR(reg_b));
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_frsp<RC0>();
template void dppc_interpreter::ppc_frsp<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fres() {
ppc_grab_regsfpdb(ppc_cur_instruction);
double start_num = GET_FPR(reg_b);
@ -530,11 +627,14 @@ void dppc_interpreter::ppc_fres() {
ppc_state.fpscr |= FPSCR::VXSNAN;
}
if (rc_flag)
if (rec)
ppc_update_cr1();
}
static void round_to_int(const uint8_t mode) {
template void dppc_interpreter::ppc_fres<RC0>();
template void dppc_interpreter::ppc_fres<RC1>();
static void round_to_int(const uint8_t mode, bool rec) {
ppc_grab_regsfpdb(ppc_cur_instruction);
double val_reg_b = GET_FPR(reg_b);
@ -587,18 +687,26 @@ static void round_to_int(const uint8_t mode) {
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
}
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template <bool rec>
void dppc_interpreter::ppc_fctiw() {
round_to_int(ppc_state.fpscr & 0x3);
round_to_int(ppc_state.fpscr & 0x3, rec);
}
template void dppc_interpreter::ppc_fctiw<RC0>();
template void dppc_interpreter::ppc_fctiw<RC1>();
template <bool rec>
void dppc_interpreter::ppc_fctiwz() {
round_to_int(1);
round_to_int(1, rec);
}
template void dppc_interpreter::ppc_fctiwz<RC0>();
template void dppc_interpreter::ppc_fctiwz<RC1>();
// Floating Point Store and Load
void dppc_interpreter::ppc_lfs() {
@ -765,27 +873,34 @@ void dppc_interpreter::ppc_stfiwx() {
// Floating Point Register Transfer
template <bool rec>
void dppc_interpreter::ppc_fmr() {
ppc_grab_regsfpdb(ppc_cur_instruction);
ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r;
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template <bool for601>
template void dppc_interpreter::ppc_fmr<RC0>();
template void dppc_interpreter::ppc_fmr<RC1>();
template <bool for601, bool rec>
void dppc_interpreter::ppc_mffs() {
ppc_grab_regsda(ppc_cur_instruction);
int reg_d = (ppc_cur_instruction >> 21) & 31;
ppc_state.fpr[reg_d].int64_r = uint64_t(ppc_state.fpscr) | (for601 ? 0xFFFFFFFF00000000ULL : 0xFFF8000000000000ULL);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_mffs<false>();
template void dppc_interpreter::ppc_mffs<true>();
template void dppc_interpreter::ppc_mffs<NOT601, RC0>();
template void dppc_interpreter::ppc_mffs<NOT601, RC1>();
template void dppc_interpreter::ppc_mffs<IS601, RC0>();
template void dppc_interpreter::ppc_mffs<IS601, RC1>();
template <bool rec>
void dppc_interpreter::ppc_mtfsf() {
int reg_b = (ppc_cur_instruction >> 11) & 0x1F;
uint8_t fm = (ppc_cur_instruction >> 17) & 0xFF;
@ -811,10 +926,14 @@ void dppc_interpreter::ppc_mtfsf() {
// copy FPR[reg_b] to FPSCR under control of cr_mask
ppc_state.fpscr = (ppc_state.fpscr & ~cr_mask) | (ppc_state.fpr[reg_b].int64_r & cr_mask);
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_mtfsf<RC0>();
template void dppc_interpreter::ppc_mtfsf<RC1>();
template <bool rec>
void dppc_interpreter::ppc_mtfsfi() {
int crf_d = (ppc_cur_instruction >> 21) & 0x1C;
uint32_t imm = (ppc_cur_instruction << 16) & 0xF0000000UL;
@ -827,30 +946,41 @@ void dppc_interpreter::ppc_mtfsfi() {
// TODO: update FEX and VX according to the "usual rule"
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_mtfsfi<RC0>();
template void dppc_interpreter::ppc_mtfsfi<RC1>();
template <bool rec>
void dppc_interpreter::ppc_mtfsb0() {
int crf_d = (ppc_cur_instruction >> 21) & 0x1F;
if (!crf_d || (crf_d > 2)) { // FEX and VX can't be explicitely cleared
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
}
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_mtfsb0<RC0>();
template void dppc_interpreter::ppc_mtfsb0<RC1>();
template <bool rec>
void dppc_interpreter::ppc_mtfsb1() {
int crf_d = (ppc_cur_instruction >> 21) & 0x1F;
if (!crf_d || (crf_d > 2)) { // FEX and VX can't be explicitely set
ppc_state.fpscr |= (0x80000000UL >> crf_d);
}
if (rc_flag)
if (rec)
ppc_update_cr1();
}
template void dppc_interpreter::ppc_mtfsb1<RC0>();
template void dppc_interpreter::ppc_mtfsb1<RC1>();
void dppc_interpreter::ppc_mcrfs() {
int crf_d = (ppc_cur_instruction >> 21) & 0x1C;
int crf_s = (ppc_cur_instruction >> 16) & 0x1C;

View File

@ -112,7 +112,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
int reg_d = (opcode >> 21) & 31; \
int reg_b = (opcode >> 11) & 31;
#define GET_FPR(reg) ppc_state.fpr[(reg)].dbl64_r
#define GET_FPR(reg) \
ppc_state.fpr[(reg)].dbl64_r
#define ppc_grab_regsfpdiab(opcode) \
int reg_d = (opcode >> 21) & 31; \

File diff suppressed because it is too large Load Diff