Skip to content

Commit

Permalink
Merge pull request #135 from mihaip/upstream-nofpu
Browse files Browse the repository at this point in the history
Respect FP bit in MSR when running floating point instructions
  • Loading branch information
dingusdev authored Jan 21, 2025
2 parents 38c4f1e + acc6e77 commit 7df166a
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 32 deletions.
2 changes: 2 additions & 0 deletions cpu/ppc/ppcemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,8 @@ extern void ppc_exec_single(void);
extern void ppc_exec_until(uint32_t goal_addr);
extern void ppc_exec_dbg(uint32_t start_addr, uint32_t size);

extern void ppc_msr_did_change();

/* debugging support API */
void print_fprs(void); /* print content of the floating-point registers */
uint64_t get_reg(std::string reg_name); /* get content of the register reg_name */
Expand Down
1 change: 1 addition & 0 deletions cpu/ppc/ppcexceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
ppc_state.msr &= 0xFFFB1041;
/* copy MSR[ILE] to MSR[LE] */
ppc_state.msr = (ppc_state.msr & ~MSR::LE) | !!(ppc_state.msr & MSR::ILE);
ppc_msr_did_change();

if (ppc_state.msr & MSR::IP) {
ppc_next_instruction_address |= 0xFFF00000;
Expand Down
115 changes: 83 additions & 32 deletions cpu/ppc/ppcexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,27 @@ class CPUProfile : public BaseProfile {
primary opcode (bits 0...5) and modifier (bits 21...31). */
static PPCOpcode OpcodeGrabber[64 * 2048];

/** Alternate lookup table when floating point instructions are disabled.
Floating point instructions are mapped to ppc_fpu_off,
everything else is the same.*/
static PPCOpcode OpcodeGrabberNoFPU[64 * 2048];

static PPCOpcode* curOpcodeGrabber = OpcodeGrabberNoFPU;

void ppc_msr_did_change() {
curOpcodeGrabber = ppc_state.msr & MSR::FP ? OpcodeGrabber : OpcodeGrabberNoFPU;
}

/** Exception helpers. */

void ppc_illegalop(uint32_t opcode) {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
}

void ppc_fpu_off(uint32_t opcode) {
ppc_exception_handler(Except_Type::EXC_NO_FPU, Exc_Cause::FPU_OFF);
}

void ppc_assert_int() {
int_pin = true;
if (ppc_state.msr & MSR::EE) {
Expand All @@ -215,7 +230,7 @@ void ppc_main_opcode(uint32_t opcode)
num_opcodes[opcode]++;
#endif
#endif
OpcodeGrabber[(opcode >> 15 & 0x1F800) | (opcode & 0x7FF)](opcode);
curOpcodeGrabber[(opcode >> 15 & 0x1F800) | (opcode & 0x7FF)](opcode);
}

static long long cpu_now_ns() {
Expand Down Expand Up @@ -414,17 +429,39 @@ for (uint32_t mod = 0; mod < 2048; mod++) { \
} \
} while (0)

#define OP_fp(opcode, fn) \
do { \
for (uint32_t mod = 0; mod < 2048; mod++) { \
OpcodeGrabber[((opcode) << 11) | mod] = fn; \
OpcodeGrabberNoFPU[((opcode) << 11) | mod] = ppc_fpu_off; \
} \
} while (0)

#define OPX(opcode, subopcode, fn) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1)] = fn; \
} while (0)

#define OPX_fp(opcode, subopcode, fn) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1)] = fn; \
OpcodeGrabberNoFPU[((opcode) << 11) | ((subopcode)<<1)] = ppc_fpu_off; \
} while (0)

#define OPXd(opcode, subopcode, fn) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x000] = fn<RC0>; \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x001] = fn<RC1>; \
} while (0)

#define OPXd_fp(opcode, subopcode, fn) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x000] = fn<RC0>; \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x001] = fn<RC1>; \
OpcodeGrabberNoFPU[((opcode) << 11) | ((subopcode)<<1) | 0x000] = ppc_fpu_off; \
OpcodeGrabberNoFPU[((opcode) << 11) | ((subopcode)<<1) | 0x001] = ppc_fpu_off; \
} while (0)

#define OPXod(opcode, subopcode, fn) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x000] = fn<RC0, OV0>; \
Expand All @@ -439,6 +476,14 @@ do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x001] = fn<carry, RC1>; \
} while (0)

#define OPXdc_fp(opcode, subopcode, fn, carry) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x000] = fn<carry, RC0>; \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x001] = fn<carry, RC1>; \
OpcodeGrabberNoFPU[((opcode) << 11) | ((subopcode)<<1) | 0x000] = ppc_fpu_off; \
OpcodeGrabberNoFPU[((opcode) << 11) | ((subopcode)<<1) | 0x001] = ppc_fpu_off; \
} while (0)

#define OPXcod(opcode, subopcode, fn, carry) \
do { \
OpcodeGrabber[((opcode) << 11) | ((subopcode)<<1) | 0x000] = fn<carry, RC0, OV0>; \
Expand All @@ -460,36 +505,33 @@ do { \
} while (0)

#define OP31(subopcode, fn) OPX(31, subopcode, fn)
#define OP31_fp(subopcode, fn) OPX_fp(31, subopcode, fn)
#define OP31d(subopcode, fn) OPXd(31, subopcode, fn)
#define OP31od(subopcode, fn) OPXod(31, subopcode, fn)
#define OP31dc(subopcode, fn, carry) OPXdc(31, subopcode, fn, carry)
#define OP31cod(subopcode, fn, carry) OPXcod(31, subopcode, fn, carry)

#define OP63(subopcode, fn) OPX(63, subopcode, fn)
#define OP63d(subopcode, fn) OPXd(63, subopcode, fn)
#define OP63dc(subopcode, fn, carry) OPXdc(63, subopcode, fn, carry)
#define OP63(subopcode, fn) OPX_fp(63, subopcode, fn)
#define OP63d(subopcode, fn) OPXd_fp(63, subopcode, fn)
#define OP63dc(subopcode, fn, carry) OPXdc_fp(63, subopcode, fn, carry)

#define OP59d(subopcode, fn) \
do { \
OPXd(59, (subopcode), fn); \
OPXd_fp(59, (subopcode), fn); \
} while (0)

#define OP59cd(subopcode, fn) \
do { \
for (uint32_t ccccc = 0; ccccc < 32; ccccc++) { \
OPXd(59, (ccccc << 5) | (subopcode), fn); \
} \
} while (0)

#define OP4_ccccc10xxxx(subopcode, fn) \
do { \
for (uint32_t ccccc = 0; ccccc < 32; ccccc++) { \
OPr(4, (ccccc << 6) | (subopcode), fn); \
OPXd_fp(59, (ccccc << 5) | (subopcode), fn); \
} \
} while (0)

void initialize_ppc_opcode_table() {
std::fill_n(OpcodeGrabber, 64 * 2048, ppc_illegalop);
auto opcodeGrabberSize = sizeof(OpcodeGrabber) / sizeof(OpcodeGrabber[0]);
std::fill_n(OpcodeGrabber, opcodeGrabberSize, ppc_illegalop);
std::fill_n(OpcodeGrabberNoFPU, opcodeGrabberSize, ppc_illegalop);

OP(3, ppc_twi);
//OP(4, ppc_opcode4); - Altivec instructions not emulated yet. Uncomment once they're implemented.
OP(7, ppc_mulli);
Expand Down Expand Up @@ -528,14 +570,14 @@ void initialize_ppc_opcode_table() {
OP(45, ppc_stu<uint16_t>);
OP(46, ppc_lmw);
OP(47, ppc_stmw);
OP(48, ppc_lfs);
OP(49, ppc_lfsu);
OP(50, ppc_lfd);
OP(51, ppc_lfdu);
OP(52, ppc_stfs);
OP(53, ppc_stfsu);
OP(54, ppc_stfd);
OP(55, ppc_stfdu);
OP_fp(48, ppc_lfs);
OP_fp(49, ppc_lfsu);
OP_fp(50, ppc_lfd);
OP_fp(51, ppc_lfdu);
OP_fp(52, ppc_stfs);
OP_fp(53, ppc_stfsu);
OP_fp(54, ppc_stfd);
OP_fp(55, ppc_stfdu);

OPla(16, 0x0, (dppc_interpreter::ppc_bc<LK0, AA0>)); // bc
OPla(16, 0x1, (dppc_interpreter::ppc_bc<LK1, AA0>)); // bcl
Expand Down Expand Up @@ -597,11 +639,11 @@ void initialize_ppc_opcode_table() {
OP31(375, ppc_lhaux);
OP31(533, ppc_lswx);
OP31(534, ppc_lwbrx);
OP31(535, ppc_lfsx);
OP31(567, ppc_lfsux);
OP31_fp(535, ppc_lfsx);
OP31_fp(567, ppc_lfsux);
OP31(597, ppc_lswi);
OP31(599, ppc_lfdx);
OP31(631, ppc_lfdux);
OP31_fp(599, ppc_lfdx);
OP31_fp(631, ppc_lfdux);
OP31(790, ppc_lhbrx);

OPr(31, (150<<1) | 1, ppc_stwcx); // No Rc=0 variant.
Expand All @@ -613,13 +655,13 @@ void initialize_ppc_opcode_table() {
OP31(439, ppc_stux<uint16_t>);
OP31(661, ppc_stswx);
OP31(662, ppc_stwbrx);
OP31(663, ppc_stfsx);
OP31(695, ppc_stfsux);
OP31_fp(663, ppc_stfsx);
OP31_fp(695, ppc_stfsux);
OP31(725, ppc_stswi);
OP31(727, ppc_stfdx);
OP31(759, ppc_stfdux);
OP31_fp(727, ppc_stfdx);
OP31_fp(759, ppc_stfdux);
OP31(918, ppc_sthbrx);
if (!is_601) OP31(983, ppc_stfiwx);
if (!is_601) OP31_fp(983, ppc_stfiwx);

OP31(310, ppc_eciwx);
OP31(438, ppc_ecowx);
Expand Down Expand Up @@ -739,6 +781,12 @@ void initialize_ppc_opcode_table() {
OP63d(i + 30, ppc_fnmsub);
OP63d(i + 31, ppc_fnmadd);
}

for (auto i = 0; i < opcodeGrabberSize; i++) {
if (OpcodeGrabberNoFPU[i] != ppc_fpu_off) {
OpcodeGrabberNoFPU[i] = OpcodeGrabber[i];
}
}
}

void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, bool do_include_601, uint64_t tb_freq)
Expand Down Expand Up @@ -788,6 +836,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, bool do_include_6
}

ppc_mmu_init();
ppc_msr_did_change();

/* redirect code execution to reset vector */
ppc_state.pc = 0xFFF00100;
Expand Down Expand Up @@ -845,8 +894,10 @@ static uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
return ppc_state.pc;
}
if (reg_name_u == "MSR") {
if (is_write)
if (is_write) {
ppc_state.msr = (uint32_t)val;
ppc_msr_did_change();
}
return ppc_state.msr;
}
if (reg_name_u == "CR") {
Expand Down
2 changes: 2 additions & 0 deletions cpu/ppc/ppcopcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ void dppc_interpreter::ppc_mtmsr(uint32_t opcode) {
}
uint32_t reg_s = (opcode >> 21) & 0x1F;
ppc_state.msr = ppc_state.gpr[reg_s];
ppc_msr_did_change();

// generate External Interrupt Exception
// if CPU interrupt line is asserted
Expand Down Expand Up @@ -1379,6 +1380,7 @@ void dppc_interpreter::ppc_rfi(uint32_t opcode) {
uint32_t new_srr1_val = (ppc_state.spr[SPR::SRR1] & 0x87C0FF73UL);
uint32_t new_msr_val = (ppc_state.msr & ~0x87C0FF73UL);
ppc_state.msr = (new_msr_val | new_srr1_val) & 0xFFFBFFFFUL;
ppc_msr_did_change();

// generate External Interrupt Exception
// if CPU interrupt line is still asserted
Expand Down

0 comments on commit 7df166a

Please sign in to comment.