mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-23 06:31:28 +00:00
ppcopcodes: Fixes for bcctr(l)?.
Add MPC601 variants. Variants that decrement and test the ctr are invalid bon't don't appear to trigger an exception. The manual says MPC601 can decrement the counter. Other CPUs do not decrement the counter but will branch based on the value.
This commit is contained in:
parent
e44676e491
commit
67bd47f11f
@ -371,7 +371,7 @@ void ppc_release_int();
|
||||
//void ppc_opcode4();
|
||||
void ppc_opcode16();
|
||||
void ppc_opcode18();
|
||||
void ppc_opcode19();
|
||||
template <bool for601> void ppc_opcode19();
|
||||
void ppc_opcode31();
|
||||
void ppc_opcode59();
|
||||
void ppc_opcode63();
|
||||
@ -416,8 +416,7 @@ extern void do_ctx_sync(void);
|
||||
|
||||
// The functions used by the PowerPC processor
|
||||
namespace dppc_interpreter {
|
||||
extern void ppc_bcctr();
|
||||
extern void ppc_bcctrl();
|
||||
template <bool l, bool for601> extern void ppc_bcctr();
|
||||
extern void ppc_bclr();
|
||||
extern void ppc_bclrl();
|
||||
extern void ppc_crand();
|
||||
|
@ -137,7 +137,7 @@ 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,
|
||||
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,
|
||||
@ -203,6 +203,7 @@ void ppc_opcode18() {
|
||||
SubOpcode18Grabber[ppc_cur_instruction & 3]();
|
||||
}
|
||||
|
||||
template<bool for601>
|
||||
void ppc_opcode19() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 0x7FF;
|
||||
|
||||
@ -247,16 +248,25 @@ void ppc_opcode19() {
|
||||
ppc_cror();
|
||||
break;
|
||||
case 1056:
|
||||
ppc_bcctr();
|
||||
if (for601)
|
||||
ppc_bcctr<false, true>();
|
||||
else
|
||||
ppc_bcctr<false, false>();
|
||||
break;
|
||||
case 1057:
|
||||
ppc_bcctrl();
|
||||
if (for601)
|
||||
ppc_bcctr<true, true>();
|
||||
else
|
||||
ppc_bcctr<true, false>();
|
||||
break;
|
||||
default:
|
||||
ppc_illegalop();
|
||||
}
|
||||
}
|
||||
|
||||
template void ppc_opcode19<false>();
|
||||
template void ppc_opcode19<true>();
|
||||
|
||||
void ppc_opcode31() {
|
||||
uint16_t subop_grab = (ppc_cur_instruction & 0x7FFUL) >> 1UL;
|
||||
rc_flag = ppc_cur_instruction & 0x1;
|
||||
@ -763,6 +773,7 @@ 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
|
||||
|
@ -1228,32 +1228,40 @@ void dppc_interpreter::ppc_bcla() {
|
||||
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
|
||||
}
|
||||
|
||||
template<bool l, bool for601>
|
||||
void dppc_interpreter::ppc_bcctr() {
|
||||
uint32_t ctr_ok;
|
||||
uint32_t cnd_ok;
|
||||
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
||||
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
||||
|
||||
uint32_t cnd_ok = (br_bo & 0x10) | \
|
||||
(!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
|
||||
uint32_t ctr = ppc_state.spr[SPR::CTR];
|
||||
uint32_t new_ctr;
|
||||
if (for601) {
|
||||
new_ctr = ctr - 1;
|
||||
if (!(br_bo & 0x04)) {
|
||||
ppc_state.spr[SPR::CTR] = new_ctr; /* decrement CTR */
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_ctr = ctr;
|
||||
}
|
||||
ctr_ok = (br_bo & 0x04) | ((new_ctr != 0) == !(br_bo & 0x02));
|
||||
cnd_ok = (br_bo & 0x10) | (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
|
||||
|
||||
if (cnd_ok) {
|
||||
ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & ~3UL);
|
||||
if (ctr_ok && cnd_ok) {
|
||||
ppc_next_instruction_address = (ctr & ~3UL);
|
||||
exec_flags = EXEF_BRANCH;
|
||||
}
|
||||
|
||||
if (l)
|
||||
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_bcctrl() {
|
||||
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
||||
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
||||
|
||||
uint32_t cnd_ok = (br_bo & 0x10) | \
|
||||
(!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
|
||||
|
||||
if (cnd_ok) {
|
||||
ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & ~3UL);
|
||||
exec_flags = EXEF_BRANCH;
|
||||
}
|
||||
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
|
||||
}
|
||||
template void dppc_interpreter::ppc_bcctr<false, false>();
|
||||
template void dppc_interpreter::ppc_bcctr<false, true>();
|
||||
template void dppc_interpreter::ppc_bcctr<true, false>();
|
||||
template void dppc_interpreter::ppc_bcctr<true, true>();
|
||||
|
||||
void dppc_interpreter::ppc_bclr() {
|
||||
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
||||
|
Loading…
x
Reference in New Issue
Block a user