This commit is contained in:
dingusdev
2024-09-15 16:59:17 -07:00
parent 0f6c32245b
commit f5e2d3be48
7 changed files with 67 additions and 39 deletions

View File

@@ -34,16 +34,19 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
#endif
uint32_t cs_code[] = {
0x3863FFFC, 0x7C861671, 0x41820090, 0x70600002, 0x41E2001C, 0xA0030004,
0x3884FFFE, 0x38630002, 0x5486F0BF, 0x7CA50114, 0x41820070, 0x70C60003,
0x41820014, 0x7CC903A6, 0x84030004, 0x7CA50114, 0x4200FFF8, 0x5486E13F,
0x41820050, 0x80030004, 0x7CC903A6, 0x80C30008, 0x7CA50114, 0x80E3000C,
0x7CA53114, 0x85030010, 0x7CA53914, 0x42400028, 0x80030004, 0x7CA54114,
0x80C30008, 0x7CA50114, 0x80E3000C, 0x7CA53114, 0x85030010, 0x7CA53914,
0x4200FFE0, 0x7CA54114, 0x70800002, 0x41E20010, 0xA0030004, 0x38630002,
0x7CA50114, 0x70800001, 0x41E20010, 0x88030004, 0x5400402E, 0x7CA50114,
0x7C650194, /* 0x4E800020 */ 0x00005AF0
};
0x3863FFFC, 0x7C861671, 0x41820090, 0x70600002,
0x41E2001C, 0xA0030004, 0x3884FFFE, 0x38630002,
0x5486F0BF, 0x7CA50114, 0x41820070, 0x70C60003,
0x41820014, 0x7CC903A6, 0x84030004, 0x7CA50114,
0x4200FFF8, 0x5486E13F, 0x41820050, 0x80030004,
0x7CC903A6, 0x80C30008, 0x7CA50114, 0x80E3000C,
0x7CA53114, 0x85030010, 0x7CA53914, 0x42400028,
0x80030004, 0x7CA54114, 0x80C30008, 0x7CA50114,
0x80E3000C, 0x7CA53114, 0x85030010, 0x7CA53914,
0x4200FFE0, 0x7CA54114, 0x70800002, 0x41E20010,
0xA0030004, 0x38630002, 0x7CA50114, 0x70800001,
0x41E20010, 0x88030004, 0x5400402E, 0x7CA50114,
0x7C650194, 0x4E800020};
constexpr uint32_t test_size = 0x8000; // 0x7FFFFFFC is the max
constexpr uint32_t test_samples = 200;

View File

@@ -83,7 +83,7 @@ typedef struct struct_ppc_instr {
};
} SetInstr;
SetInstr instr;
extern SetInstr instr;
typedef struct struct_ppc_state {
FPR_storage fpr[32];
@@ -98,7 +98,7 @@ typedef struct struct_ppc_state {
bool reserve; // reserve bit used for lwarx and stcwx
} SetPRS;
SetPRS ppc_state;
extern SetPRS ppc_state;
/** symbolic names for frequently used SPRs */
enum SPR : int {
@@ -423,7 +423,6 @@ void ppc_fpu_off();
void ppc_assert_int();
void ppc_release_int();
void (*ref_instr)();
void decode_instr();
void initialize_ppc_opcode_tables(bool include_601);

View File

@@ -56,6 +56,10 @@ using namespace dppc_interpreter;
MemCtrlBase* mem_ctrl_instance = 0;
void (*ref_instr)();
SetPRS ppc_state;
SetInstr instr;
bool is_601 = false;
bool power_on = false;
@@ -245,7 +249,7 @@ void ppc_opcode19() {
switch (subop_grab) {
case 0:
ref_instr = ppc_mcrf;
ppc_grab_regs_crf(ppc_cur_instruction);
ppc_grab_regs_crfds(ppc_cur_instruction);
break;
case 32:
ref_instr = ppc_bclr<LK0>;
@@ -311,18 +315,22 @@ template void ppc_opcode19<IS601>();
static void ppc_opcode31() {
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
ref_instr = SubOpcode59Grabber[subop_grab];
ref_instr = SubOpcode31Grabber[subop_grab];
switch ((subop_grab >> 1)) {
case 0:
case 32:
ppc_grab_crfd_regsab(ppc_cur_instruction);
break;
case 8:
ppc_grab_tw(ppc_cur_instruction);
break;
case 83:
ppc_grab_d(ppc_cur_instruction);
break;
case 144:
ppc_grab_crfd(ppc_cur_instruction);
break;
case 210:
case 595:
ppc_grab_sr(ppc_cur_instruction);
@@ -343,16 +351,24 @@ static void ppc_opcode59() {
static void ppc_opcode63() {
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
ref_instr = SubOpcode59Grabber[subop_grab];
ref_instr = SubOpcode63Grabber[subop_grab];
switch ((subop_grab >> 1)) {
case 0:
case 32:
ppc_grab_regsfpsab(ppc_cur_instruction);
break;
case 38:
case 70:
ppc_grab_crfd(ppc_cur_instruction);
break;
case 64:
ppc_grab_regs_crf(ppc_cur_instruction);
ppc_grab_regs_crfds(ppc_cur_instruction);
break;
case 134:
ppc_grab_mtfsfi(ppc_cur_instruction);
break;
case 711:
default:
ppc_grab_regsfpdabc(ppc_cur_instruction);
}
@@ -375,10 +391,12 @@ static void ppc_main_opcode() {
case 20: case 21:
case 22: case 23:
ppc_grab_regs_sab_rot(ppc_cur_instruction);
break;
case 24: case 25:
case 26: case 27:
case 28: case 29:
ppc_grab_regs_sauimm(ppc_cur_instruction);
break;
case 32: case 33: case 34: case 35:
case 36: case 37: case 38: case 39:
case 40: case 31: case 42: case 43:
@@ -386,6 +404,7 @@ static void ppc_main_opcode() {
case 48: case 49: case 50: case 51:
case 52: case 53: case 54: case 55:
ppc_grab_regs_da_addr(ppc_cur_instruction);
break;
}
}
@@ -1014,7 +1033,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, bool include_601,
tbr_wr_timestamp = 0;
rtc_timestamp = 0;
tbr_wr_value = 0;
tbr_freq_ghz = (tb_freq << 32) / NS_PER_SEC;
tbr_freq_ghz = uint32_t((tb_freq << 32) / NS_PER_SEC);
tbr_period_ns = ((uint64_t)NS_PER_SEC << 32) / tb_freq;
exec_flags = 0;

View File

@@ -638,7 +638,7 @@ static void round_to_int(const uint8_t mode, field_rc rec) {
ppc_state.fpr[instr.arg0].int64_r = 0xFFF8000080000000ULL;
}
} else {
uint64_t ppc_result64_d;
uint64_t ppc_result64_d = 0;
switch (mode & 0x3) {
case 0:
ppc_result64_d = uint32_t(round_to_nearest(val_reg_b));
@@ -875,7 +875,8 @@ void dppc_interpreter::ppc_mtfsf() {
cr_mask &= ~(FPSCR::FEX | FPSCR::VX);
// copy FPR[reg_b] to FPSCR under control of cr_mask
ppc_state.fpscr = (ppc_state.fpscr & ~cr_mask) | (ppc_state.fpr[instr.arg2].int64_r & cr_mask);
ppc_state.fpscr = (ppc_state.fpscr & ~cr_mask) |
(ppc_state.fpr[instr.arg2].int64_r & cr_mask);
if (rec)
ppc_update_cr1();
@@ -905,9 +906,8 @@ template void dppc_interpreter::ppc_mtfsfi<RC1>();
template <field_rc 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 explicitly cleared
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
if (!instr.arg0 || (instr.arg0 > 2)) { // FEX and VX can't be explicitly cleared
ppc_state.fpscr &= ~(0x80000000UL >> instr.arg0);
}
if (rec)
@@ -919,9 +919,8 @@ template void dppc_interpreter::ppc_mtfsb0<RC1>();
template <field_rc 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 explicitly set
ppc_state.fpscr |= (0x80000000UL >> crf_d);
if (!instr.arg0 || (instr.arg0 > 2)) { // FEX and VX can't be explicitly set
ppc_state.fpscr |= (0x80000000UL >> instr.arg0);
}
if (rec)

View File

@@ -40,6 +40,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define crf_s(opcode) ((opcode >> 16) & 0x1C)
#define crm(opcode) ((opcode >> 12) & 0xFFU)
#define fcrm(opcode) crm(opcode)
#define fmmask(opcode) ((opcode >> 17) & 0xFFU)
#define br_bo(opcode) reg_d(opcode)
#define br_bi(opcode) reg_a(opcode)
#define br_bd(opcode) int32_t(int16_t(opcode & ~3UL))
@@ -56,18 +57,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define ppc_grab_tw(opcode) \
instr.i_simm = simm(opcode); \
instr.arg1 = reg_a(opcode); \
instr.arg0 = trap_to(opcode);
instr.arg0 = trap_to(opcode); \
#define ppc_grab_crfd(opcode) \
instr.arg0 = crf_d(opcode);
#define ppc_grab_mcrxr(opcode) \
instr.arg0 = crf_d(opcode);
instr.arg0 = crf_d(opcode); \
instr.arg4 = crf_d(opcode); \
#define ppc_grab_sr(opcode) \
instr.arg0 = reg_d(opcode); \
instr.arg1 = segreg(opcode);
instr.arg1 = segreg(opcode); \
#define ppc_grab_mtfsfi(opcode) \
instr.arg0 = reg_d(opcode); \
instr.mask = mtfsfi_mask(opcode);
instr.mask = mtfsfi_mask(opcode); \
#define ppc_grab_mtfsf(opcode) \
instr.arg2 = reg_b(opcode); \
instr.mask = fmmask(opcode);\
#define ppc_grab_regs_dasimm(opcode) \
instr.arg0 = reg_d(opcode); \
@@ -85,15 +94,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
instr.addr = adr_d(opcode); \
#define ppc_grab_branch(opcode) \
instr.addr = adr_li(opcode);
instr.addr = adr_li(opcode); \
#define ppc_grab_branch_cond(opcode) \
instr.arg0 = br_bo(opcode); \
instr.arg1 = br_bi(opcode);
#define ppc_grab_branch_cond(opcode) \
instr.arg0 = br_bo(opcode); \
instr.arg1 = br_bi(opcode);
instr.arg1 = br_bi(opcode); \
#define ppc_grab_d(opcode) \
instr.arg0 = reg_d(opcode);
@@ -126,7 +131,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define ppc_grab_s(opcode) \
instr.arg0 = reg_s(opcode); \
#define ppc_grab_regs_crf(opcode) \
#define ppc_grab_regs_crfds(opcode) \
instr.arg0 = crf_d(opcode); \
instr.arg1 = crf_s(opcode); \

View File

@@ -982,6 +982,7 @@ void dppc_interpreter::ppc_mtspr() {
case 543:
ppc_state.spr[ref_spr] = val;
dbat_update(ref_spr);
break;
default:
// FIXME: Unknown SPR should be noop or illegal instruction.
ppc_state.spr[ref_spr] = val;
@@ -1037,8 +1038,8 @@ void dppc_interpreter::ppc_mtcrf() {
}
void dppc_interpreter::ppc_mcrxr() {
ppc_state.cr = (ppc_state.cr & ~(0xF0000000UL >> instr.arg4)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> instr.arg4);
ppc_state.cr = (ppc_state.cr & ~(0xF0000000UL >> instr.arg0)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> instr.arg0);
ppc_state.spr[SPR::XER] &= 0x0FFFFFFF;
}

View File

@@ -33,6 +33,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std;
void (*ref_instr)();
int ntested; // number of tested instructions
int nfailed; // number of failed instructions