diff --git a/cpu/ppc/ppcfpopcodes.cpp b/cpu/ppc/ppcfpopcodes.cpp index a72fc6c..74b6dd7 100644 --- a/cpu/ppc/ppcfpopcodes.cpp +++ b/cpu/ppc/ppcfpopcodes.cpp @@ -1027,15 +1027,22 @@ void dppc_interpreter::ppc_lfs(uint32_t opcode) { void dppc_interpreter::ppc_lfsu(uint32_t opcode) { ppc_grab_regsfpdia(opcode); - if (reg_a) { - uint32_t ea = int32_t(int16_t(opcode)); - ea += (reg_a) ? val_reg_a : 0; - uint32_t result = mmu_read_vmem(opcode, ea); - ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result); + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = int32_t(int16_t(opcode)); + ea += val_reg_a; + uint32_t result = mmu_read_vmem(opcode, ea); + ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result); + if (reg_a != 0) //accounting for the 601's skipping of updating Reg A ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } } void dppc_interpreter::ppc_lfsx(uint32_t opcode) { @@ -1047,14 +1054,22 @@ void dppc_interpreter::ppc_lfsx(uint32_t opcode) { void dppc_interpreter::ppc_lfsux(uint32_t opcode) { ppc_grab_regsfpdiab(opcode); - if (reg_a) { - uint32_t ea = val_reg_a + val_reg_b; - uint32_t result = mmu_read_vmem(opcode, ea); - ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result); + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = val_reg_a + val_reg_b; + uint32_t result = mmu_read_vmem(opcode, ea); + ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result); + + if (reg_a != 0) // accounting for the 601's skipping of updating Reg A ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } } void dppc_interpreter::ppc_lfd(uint32_t opcode) { @@ -1067,15 +1082,23 @@ void dppc_interpreter::ppc_lfd(uint32_t opcode) { void dppc_interpreter::ppc_lfdu(uint32_t opcode) { ppc_grab_regsfpdia(opcode); - if (reg_a != 0) { - uint32_t ea = int32_t(int16_t(opcode)); - ea += val_reg_a; - uint64_t ppc_result64_d = mmu_read_vmem(opcode, ea); - ppc_store_fpresult_int(reg_d, ppc_result64_d); + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = int32_t(int16_t(opcode)); + ea += val_reg_a; + uint64_t ppc_result64_d = mmu_read_vmem(opcode, ea); + ppc_store_fpresult_int(reg_d, ppc_result64_d); + + if (reg_a != 0) // accounting for the 601's skipping of updating Reg A ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } } void dppc_interpreter::ppc_lfdx(uint32_t opcode) { @@ -1087,14 +1110,22 @@ void dppc_interpreter::ppc_lfdx(uint32_t opcode) { void dppc_interpreter::ppc_lfdux(uint32_t opcode) { ppc_grab_regsfpdiab(opcode); - if (reg_a) { - uint32_t ea = val_reg_a + val_reg_b; - uint64_t ppc_result64_d = mmu_read_vmem(opcode, ea); - ppc_store_fpresult_int(reg_d, ppc_result64_d); + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = val_reg_a + val_reg_b; + uint64_t ppc_result64_d = mmu_read_vmem(opcode, ea); + ppc_store_fpresult_int(reg_d, ppc_result64_d); + + if (reg_a != 0) // accounting for the 601's skipping of updating Reg A ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } } void dppc_interpreter::ppc_stfs(uint32_t opcode) { @@ -1107,15 +1138,21 @@ void dppc_interpreter::ppc_stfs(uint32_t opcode) { void dppc_interpreter::ppc_stfsu(uint32_t opcode) { ppc_grab_regsfpsia(opcode); - if (reg_a != 0) { - uint32_t ea = int32_t(int16_t(opcode)); - ea += val_reg_a; - float result = float(ppc_state.fpr[reg_s].dbl64_r); - mmu_write_vmem(opcode, ea, *(uint32_t*)(&result)); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = int32_t(int16_t(opcode)); + ea += val_reg_a; + float result = float(ppc_state.fpr[reg_s].dbl64_r); + mmu_write_vmem(opcode, ea, *(uint32_t*)(&result)); + ppc_state.gpr[reg_a] = ea; } void dppc_interpreter::ppc_stfsx(uint32_t opcode) { @@ -1127,14 +1164,20 @@ void dppc_interpreter::ppc_stfsx(uint32_t opcode) { void dppc_interpreter::ppc_stfsux(uint32_t opcode) { ppc_grab_regsfpsiab(opcode); - if (reg_a) { - uint32_t ea = val_reg_a + val_reg_b; - float result = float(ppc_state.fpr[reg_s].dbl64_r); - mmu_write_vmem(opcode, ea, *(uint32_t*)(&result)); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = val_reg_a + val_reg_b; + float result = float(ppc_state.fpr[reg_s].dbl64_r); + mmu_write_vmem(opcode, ea, *(uint32_t*)(&result)); + ppc_state.gpr[reg_a] = ea; } void dppc_interpreter::ppc_stfd(uint32_t opcode) { @@ -1146,14 +1189,20 @@ void dppc_interpreter::ppc_stfd(uint32_t opcode) { void dppc_interpreter::ppc_stfdu(uint32_t opcode) { ppc_grab_regsfpsia(opcode); - if (reg_a != 0) { - uint32_t ea = int32_t(int16_t(opcode)); - ea += val_reg_a; - mmu_write_vmem(opcode, ea, ppc_state.fpr[reg_s].int64_r); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = int32_t(int16_t(opcode)); + ea += val_reg_a; + mmu_write_vmem(opcode, ea, ppc_state.fpr[reg_s].int64_r); + ppc_state.gpr[reg_a] = ea; } void dppc_interpreter::ppc_stfdx(uint32_t opcode) { @@ -1164,13 +1213,19 @@ void dppc_interpreter::ppc_stfdx(uint32_t opcode) { void dppc_interpreter::ppc_stfdux(uint32_t opcode) { ppc_grab_regsfpsiab(opcode); - if (reg_a != 0) { - uint32_t ea = val_reg_a + val_reg_b; - mmu_write_vmem(opcode, ea, ppc_state.fpr[reg_s].int64_r); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + val_reg_a = 0; + } else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = val_reg_a + val_reg_b; + mmu_write_vmem(opcode, ea, ppc_state.fpr[reg_s].int64_r); + ppc_state.gpr[reg_a] = ea; } void dppc_interpreter::ppc_stfiwx(uint32_t opcode) { diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 36e390f..e4512af 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -1531,14 +1531,21 @@ void dppc_interpreter::ppc_stu(uint32_t opcode) { num_int_stores++; #endif ppc_grab_regssa(opcode); - if (reg_a != 0) { - uint32_t ea = int32_t(int16_t(opcode)); - ea += ppc_result_a; - mmu_write_vmem(opcode, ea, ppc_result_d); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + ppc_result_a = 0; + } + else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = int32_t(int16_t(opcode)); + ea += ppc_result_a; + mmu_write_vmem(opcode, ea, ppc_result_d); + ppc_state.gpr[reg_a] = ea; } template void dppc_interpreter::ppc_stu(uint32_t opcode); @@ -1551,13 +1558,20 @@ void dppc_interpreter::ppc_stux(uint32_t opcode) { num_int_stores++; #endif ppc_grab_regssab(opcode); - if (reg_a != 0) { - uint32_t ea = ppc_result_a + ppc_result_b; - mmu_write_vmem(opcode, ea, ppc_result_d); - ppc_state.gpr[reg_a] = ea; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + + if (reg_a == 0) { + if (is_601) { + ppc_result_a = 0; + } + else { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + return; + } + } + + uint32_t ea = ppc_result_a + ppc_result_b; + mmu_write_vmem(opcode, ea, ppc_result_d); + ppc_state.gpr[reg_a] = ea; } template void dppc_interpreter::ppc_stux(uint32_t opcode); @@ -1644,9 +1658,11 @@ void dppc_interpreter::ppc_lzu(uint32_t opcode) { if ((reg_a != reg_d) && reg_a != 0) { ea += ppc_result_a; uint32_t ppc_result_d = mmu_read_vmem(opcode, ea); - uint32_t ppc_result_a = ea; ppc_store_iresult_reg(reg_d, ppc_result_d); - ppc_store_iresult_reg(reg_a, ppc_result_a); + if (!(is_601 && (reg_a == 0))) { + uint32_t ppc_result_a = ea; + ppc_store_iresult_reg(reg_a, ppc_result_a); + } } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } @@ -1680,9 +1696,11 @@ void dppc_interpreter::ppc_lzux(uint32_t opcode) { if ((reg_a != reg_d) && reg_a != 0) { uint32_t ea = ppc_result_a + ppc_result_b; uint32_t ppc_result_d = mmu_read_vmem(opcode, ea); - ppc_result_a = ea; ppc_store_iresult_reg(reg_d, ppc_result_d); - ppc_store_iresult_reg(reg_a, ppc_result_a); + if (!(is_601 && (reg_a == 0))) { + uint32_t ppc_result_a = ea; + ppc_store_iresult_reg(reg_a, ppc_result_a); + } } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } @@ -1715,6 +1733,10 @@ void dppc_interpreter::ppc_lhau(uint32_t opcode) { ppc_store_iresult_reg(reg_d, int32_t(val)); uint32_t ppc_result_a = ea; ppc_store_iresult_reg(reg_a, ppc_result_a); + if (!(is_601 && (reg_a == 0))) { + uint32_t ppc_result_a = ea; + ppc_store_iresult_reg(reg_a, ppc_result_a); + } } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } @@ -1731,6 +1753,10 @@ void dppc_interpreter::ppc_lhaux(uint32_t opcode) { ppc_store_iresult_reg(reg_d, int32_t(val)); uint32_t ppc_result_a = ea; ppc_store_iresult_reg(reg_a, ppc_result_a); + if (!(is_601 && (reg_a == 0))) { + uint32_t ppc_result_a = ea; + ppc_store_iresult_reg(reg_a, ppc_result_a); + } } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);