Merge pull request #21 from dingusdev/floating-point

Floating point fixes. Rehauled floating-point emulation code. Fixed a test suite for floating points.
This commit is contained in:
dingusdev 2021-10-19 07:18:21 -07:00 committed by GitHub
commit 7919cd0590
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 4577 additions and 386 deletions

View File

@ -169,6 +169,7 @@ if (DPPC_BUILD_PPC_TESTS)
TARGET testppc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcinttests.csv"
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcfloattests.csv"
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcdisasmtest.csv"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
endif()

View File

@ -200,6 +200,71 @@ enum class BB_end_kind {
BB_RFI /* the rfi instruction is encountered */
};
enum CR_select : int32_t {
CR0_field = (0xF << 28),
CR1_field = (0xF << 24),
};
enum CRx_bit : uint32_t {
CR_SO = 0,
CR_EQ,
CR_GT,
CR_LT
};
enum CR1_bit : uint32_t {
CR1_OX = 24,
CR1_VX,
CR1_FEX,
CR1_FX,
};
enum FPSCR : uint32_t {
RN = 0x3,
NI = 0x4,
XE = 0x8,
ZE = 0x10,
UE = 0x20,
OE = 0x40,
VE = 0x80,
VXCVI = 0x100,
VXSQRT = 0x200,
VXSOFT = 0x400,
FPRF = 0x1F000,
FPCC_FUNAN = 0x10000,
FPCC_NEG = 0x8000,
FPCC_POS = 0x4000,
FPCC_ZERO = 0x2000,
FPCC_FPRCD = 0x1000,
FI = 0x20000,
FR = 0x40000,
VXVC = 0x80000,
VXIMZ = 0x100000,
VXZDZ = 0x200000,
VXIDI = 0x400000,
VXISI = 0x800000,
VXSNAN = 0x1000000,
XX = 0x2000000,
ZX = 0x4000000,
UX = 0x8000000,
OX = 0x10000000,
VX = 0x20000000,
FEX = 0x40000000,
FX = 0x80000000
};
//for inf and nan checks
enum FPOP : int {
DIV = 0x12,
SUB = 0x14,
ADD = 0x15,
MUL = 0x19,
FMSUB = 0x1C,
FMADD = 0x1D,
FNMSUB = 0x1E,
FNMADD = 0x1F,
};
/** PowerPC exception types. */
enum class Except_Type {
EXC_SYSTEM_RESET = 1,
@ -271,7 +336,6 @@ void ppc_opcode63();
void initialize_ppc_opcode_tables();
extern bool ppc_confirm_inf_nan(uint64_t input_a, uint64_t input_b, bool is_single, uint32_t op);
extern double fp_return_double(uint32_t reg);
extern uint64_t fp_return_uint64(uint32_t reg);
@ -416,15 +480,10 @@ extern void ppc_mtspr();
extern void ppc_mtfsb0();
extern void ppc_mtfsb1();
extern void ppc_mcrfs();
extern void ppc_mtfsb0dot();
extern void ppc_mtfsb1dot();
extern void ppc_fmr();
extern void ppc_mffs();
extern void ppc_mffsdot();
extern void ppc_mtfsf();
extern void ppc_mtfsfdot();
extern void ppc_mtfsfi();
extern void ppc_mtfsfidot();
extern void ppc_addi();
extern void ppc_addic();

View File

@ -253,8 +253,7 @@ void ppc_opcode31() {
oe_flag = ppc_cur_instruction & 0x400;
#ifdef EXHAUSTIVE_DEBUG
uint32_t regrab = (uint32_t)subop_grab;
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
LOG_F(INFO, "Executing Opcode 31 table subopcode entry %n \n", (uint32_t)subop_grab);
#endif // EXHAUSTIVE_DEBUG
SubOpcode31Grabber[subop_grab]();
@ -264,8 +263,7 @@ void ppc_opcode59() {
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x1F;
rc_flag = ppc_cur_instruction & 1;
#ifdef EXHAUSTIVE_DEBUG
uint32_t regrab = (uint32_t)subop_grab;
LOG_F(INFO, "Executing Opcode 59 table subopcode entry \n", regrab);
LOG_F(INFO, "Executing Opcode 59 table subopcode entry %n \n", (uint32_t)subop_grab);
#endif // EXHAUSTIVE_DEBUG
SubOpcode59Grabber[subop_grab]();
}
@ -274,8 +272,7 @@ void ppc_opcode63() {
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x3FF;
rc_flag = ppc_cur_instruction & 1;
#ifdef EXHAUSTIVE_DEBUG
uint32_t regrab = (uint32_t)subop_grab;
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
LOG_F(INFO, "Executing Opcode 63 table subopcode entry %n \n", (uint32_t)subop_grab);
#endif // EXHAUSTIVE_DEBUG
SubOpcode63Grabber[subop_grab]();
}

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "ppcmmu.h"
#include <array>
#include <cfenv>
#include <cfloat>
#include <cinttypes>
#include <cmath>
#include <iostream>
@ -150,20 +151,11 @@ void ppc_fp_changecrf1() {
ppc_state.fpscr |= 0xf0000000;
}
void ppc_divbyzero(uint64_t input_a, uint64_t input_b, bool is_single) {
if (input_b == 0) {
ppc_state.fpscr |= 0x84000000;
if (input_a == 0) {
ppc_state.fpscr |= 0x200000;
}
}
}
int64_t round_to_nearest(double f) {
if (f >= 0.0) {
return static_cast<int32_t>(static_cast<int64_t> (f + 0.5));
return static_cast<int32_t>(static_cast<int64_t> (ceil(f)));
} else {
return static_cast<int32_t>(static_cast<int64_t> (-f + 0.5));
return static_cast<int32_t>(static_cast<int64_t> (floor(f)));
}
}
@ -179,153 +171,113 @@ int64_t round_to_neg_inf(double f) {
return static_cast<int32_t>(floor(f));
}
void ppc_toggle_fpscr_fex() {
bool fex_result = ((ppc_state.fpscr & 0x20000000) & (ppc_state.fpscr & 0x80));
fex_result |= ((ppc_state.fpscr & 0x10000000) & (ppc_state.fpscr & 0x40));
fex_result |= ((ppc_state.fpscr & 0x8000000) & (ppc_state.fpscr & 0x20));
fex_result |= ((ppc_state.fpscr & 0x4000000) & (ppc_state.fpscr & 0x10));
fex_result |= ((ppc_state.fpscr & 0x2000000) & (ppc_state.fpscr & 0x8));
ppc_state.fpscr |= (fex_result << 30);
void update_fex() {
int fex_result = !!((ppc_state.fpscr & (ppc_state.fpscr << 22)) & 0x3E000000);
ppc_state.fpscr = (ppc_state.fpscr & ~0x40000000) | (fex_result << 30);
}
bool ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, bool is_single, uint32_t op) {
uint64_t input_a = ppc_state.fpr[chosen_reg_1].int64_r;
uint64_t input_b = ppc_state.fpr[chosen_reg_2].int64_r;
template <typename T, const FPOP fpop>
void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, int chosen_reg_3, bool rc_flag = false) {
T input_a = T(ppc_state.fpr[chosen_reg_1].int64_r);
T input_b = T(ppc_state.fpr[chosen_reg_2].int64_r);
T input_c = T(ppc_state.fpr[chosen_reg_3].int64_r);
if (is_single) {
uint32_t exp_a = (input_a >> 23) & 0xff;
uint32_t exp_b = (input_b >> 23) & 0xff;
ppc_state.fpscr &= 0x7fbfffff;
ppc_state.fpscr &= 0x7fbfffff;
switch (fpop) {
case FPOP::DIV:
if (isnan(input_a) && isnan(input_b)) {
ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXIDI);
} else if ((input_a == FP_ZERO) && (input_b == FP_ZERO)) {
ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXZDZ);
}
update_fex();
break;
case FPOP::SUB:
if (isnan(input_a) && isnan(input_b)) {
ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXISI);
}
update_fex();
break;
case FPOP::ADD:
if (isnan(input_a) && isnan(input_b)) {
ppc_state.fpscr |= (FPSCR::FX | FPSCR::VXISI);
}
update_fex();
break;
case FPOP::MUL:
if (((input_a == FP_ZERO) && (input_c == FP_INFINITE)) ||
((input_c == FP_ZERO) && (input_a == FP_INFINITE))) {
ppc_state.fpscr |=
(FPSCR::FX | FPSCR::VXSNAN |
FPSCR::VXIMZ);
}
update_fex();
break;
case FPOP::FMSUB:
case FPOP::FNMSUB:
if (isnan(input_a) || isnan(input_b) || isnan(input_c)) {
ppc_state.fpscr |= FPSCR::VXSNAN;
if (((input_a == FP_ZERO) && (input_c == FP_INFINITE)) ||
((input_c == FP_ZERO) && (input_a == FP_INFINITE))) {
ppc_state.fpscr |= FPSCR::VXIMZ;
}
}
switch (op) {
case 36:
if ((exp_a == 0xff) && (exp_b == 0xff)) {
ppc_state.fpscr |= 0x80400000;
ppc_toggle_fpscr_fex();
return true;
} else if ((input_a == 0) && (input_b == 0)) {
ppc_state.fpscr |= 0x80200000;
ppc_toggle_fpscr_fex();
return true;
}
update_fex();
break;
case 40:
if ((exp_a == 0xff) && (exp_b == 0xff)) {
ppc_state.fpscr |= 0x80800000;
ppc_toggle_fpscr_fex();
return true;
case FPOP::FMADD:
case FPOP::FNMADD:
if (isnan(input_a) || isnan(input_b) || isnan(input_c)) {
ppc_state.fpscr |= (FPSCR::VXSNAN | FPSCR::FPCC_FUNAN);
}
update_fex();
break;
case 50:
if (((exp_a == 0xff) & (input_b == 0)) | ((exp_b == 0xff) & (input_a == 0))) {
ppc_state.fpscr |= 0x80100000;
ppc_toggle_fpscr_fex();
return true;
}
break;
case 56:
case 58:
if ((exp_a == 0xff) && (exp_b == 0xff)) {
ppc_state.fpscr |= 0x80800000;
ppc_toggle_fpscr_fex();
return true;
}
break;
default:
return false;
}
} else {
uint32_t exp_a = (input_a >> 52) & 0x7ff;
uint32_t exp_b = (input_b >> 52) & 0x7ff;
ppc_state.fpscr &= 0x7fbfffff;
switch (op) {
case 36:
if ((exp_a == 0x7ff) && (exp_b == 0x7ff)) {
ppc_state.fpscr |= 0x80400000;
ppc_toggle_fpscr_fex();
return true;
} else if ((input_a == 0) && (input_b == 0)) {
ppc_state.fpscr |= 0x80200000;
ppc_toggle_fpscr_fex();
return true;
}
break;
case 40:
if ((exp_a == 0x7ff) && (exp_b == 0x7ff)) {
ppc_state.fpscr |= 0x80800000;
ppc_toggle_fpscr_fex();
return true;
}
break;
case 50:
if (((exp_a == 0x7ff) & (input_b == 0)) | ((exp_b == 0x7ff) & (input_a == 0))) {
ppc_state.fpscr |= 0x80100000;
ppc_toggle_fpscr_fex();
return true;
}
break;
case 56:
case 58:
if ((exp_a == 0xff) && (exp_b == 0xff)) {
ppc_state.fpscr |= 0x80800000;
ppc_toggle_fpscr_fex();
return true;
}
break;
default:
return false;
}
}
return false;
}
void fpresult_update(uint64_t set_result, bool confirm_arc) {
void fpresult_update(double set_result, bool confirm_arc) {
bool confirm_ov = (bool)std::fetestexcept(FE_OVERFLOW);
if (ppc_state.fpscr & 0x3)
ppc_state.cr |= 0x2;
if (set_result > 0.0) {
ppc_state.fpscr |= FPSCR::FPCC_POS;
} else if (set_result < 0.0) {
ppc_state.fpscr |= FPSCR::FPCC_NEG;
} else if (set_result == 0.0) {
ppc_state.fpscr |= FPSCR::FPCC_ZERO;
} else {
ppc_state.fpscr |= FPSCR::FPCC_FPRCD;
}
if (confirm_ov) {
ppc_state.fpscr |= 0x80001000;
ppc_state.fpscr |= (FPSCR::FX | (FPSCR::FPRF & FPSCR::FPCC_FUNAN));
}
if (confirm_arc) {
ppc_state.fpscr |= 0x80010000;
ppc_state.fpscr &= 0xFFFF0FFF;
if (set_result == 0) {
ppc_state.fpscr |= 0x2000;
} else {
if (set_result < 0) {
ppc_state.fpscr |= 0x8000;
} else if (set_result > 0) {
ppc_state.fpscr |= 0x4000;
} else {
ppc_state.fpscr |= 0x1000;
}
}
}
}
void ppc_frsqrte_result() {
if (ppc_result64_d & 0x007FF000000000000UL) {
ppc_state.fpscr |= (FPSCR::FX | (FPSCR::FPRF & FPSCR::FPCC_FUNAN));
//ppc_state.fpscr &= 0xFFFF0FFF;
}
}
void ppc_changecrf1() {
ppc_state.cr &= 0xF0FFFFFF;
ppc_state.cr |= (ppc_state.fpscr & 0xF0000000) >> 4;
ppc_state.cr &= ~((uint32_t)CR_select::CR1_field);
ppc_state.cr |= (ppc_state.fpscr & (uint32_t)CR_select::CR0_field) >> 4;
}
// Floating Point Arithmetic
void dppc_interpreter::ppc_fadd() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
ppc_dblresult64_d = val_reg_a + val_reg_b;
ppc_dblresult64_d = val_reg_a + val_reg_b;
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, ADD>(reg_a, reg_b, 0, rc_flag);
}
if (rc_flag)
@ -335,9 +287,13 @@ void dppc_interpreter::ppc_fadd() {
void dppc_interpreter::ppc_fsub() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 56)) {
ppc_dblresult64_d = val_reg_a - val_reg_b;
ppc_dblresult64_d = val_reg_a - val_reg_b;
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, SUB>(reg_a, reg_b, 0, rc_flag);
}
if (rc_flag)
@ -347,9 +303,13 @@ void dppc_interpreter::ppc_fsub() {
void dppc_interpreter::ppc_fdiv() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 36)) {
ppc_dblresult64_d = val_reg_a / val_reg_b;
ppc_dblresult64_d = val_reg_a / val_reg_b;
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, DIV>(reg_a, reg_b, 0, rc_flag);
}
if (rc_flag)
@ -359,9 +319,13 @@ void dppc_interpreter::ppc_fdiv() {
void dppc_interpreter::ppc_fmul() {
ppc_grab_regsfpdac();
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
ppc_dblresult64_d = val_reg_a * val_reg_c;
ppc_dblresult64_d = val_reg_a * val_reg_c;
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, MUL>(reg_a, reg_b, 0, rc_flag);
}
if (rc_flag)
@ -371,14 +335,14 @@ void dppc_interpreter::ppc_fmul() {
void dppc_interpreter::ppc_fmadd() {
ppc_grab_regsfpdabc();
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
ppc_dblresult64_d = (val_reg_a * val_reg_c);
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
ppc_dblresult64_d += val_reg_b;
}
}
ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b);
ppc_store_dfpresult_flt(reg_d);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, FMADD>(reg_a, reg_b, reg_c);
}
if (rc_flag)
ppc_changecrf1();
@ -387,14 +351,15 @@ void dppc_interpreter::ppc_fmadd() {
void dppc_interpreter::ppc_fmsub() {
ppc_grab_regsfpdabc();
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
ppc_dblresult64_d = (val_reg_a * val_reg_c);
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
ppc_dblresult64_d -= val_reg_b;
}
}
ppc_dblresult64_d = (val_reg_a * val_reg_c);
ppc_dblresult64_d -= val_reg_b;
ppc_store_dfpresult_flt(reg_d);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, FMSUB>(reg_a, reg_b, reg_c);
}
if (rc_flag)
ppc_changecrf1();
@ -403,15 +368,16 @@ void dppc_interpreter::ppc_fmsub() {
void dppc_interpreter::ppc_fnmadd() {
ppc_grab_regsfpdabc();
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
ppc_dblresult64_d = (val_reg_a * val_reg_c);
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
ppc_dblresult64_d += val_reg_b;
}
}
ppc_dblresult64_d = (val_reg_a * val_reg_c);
ppc_dblresult64_d += val_reg_b;
ppc_dblresult64_d = -ppc_dblresult64_d;
ppc_store_dfpresult_flt(reg_d);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
}
else {
ppc_confirm_inf_nan<double, FNMADD>(reg_a, reg_b, reg_c);
}
if (rc_flag)
ppc_changecrf1();
@ -420,15 +386,16 @@ void dppc_interpreter::ppc_fnmadd() {
void dppc_interpreter::ppc_fnmsub() {
ppc_grab_regsfpdabc();
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
ppc_dblresult64_d = (val_reg_a * val_reg_c);
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
ppc_dblresult64_d -= val_reg_b;
}
}
ppc_dblresult64_d = (val_reg_a * val_reg_c);
ppc_dblresult64_d -= val_reg_b;
ppc_dblresult64_d = -ppc_dblresult64_d;
ppc_store_dfpresult_flt(reg_d);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_dfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<double, FNMSUB>(reg_a, reg_b, reg_c);
}
if (rc_flag)
ppc_changecrf1();
@ -437,10 +404,14 @@ void dppc_interpreter::ppc_fnmsub() {
void dppc_interpreter::ppc_fadds() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
float intermediate = (float)val_reg_a + (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
float intermediate = (float)val_reg_a + (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, ADD>(reg_a, reg_b, 0);
}
if (rc_flag)
@ -450,23 +421,14 @@ void dppc_interpreter::ppc_fadds() {
void dppc_interpreter::ppc_fsubs() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
float intermediate = (float)val_reg_a - (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_sfpresult_flt(reg_d);
}
if (rc_flag)
ppc_changecrf1();
}
void dppc_interpreter::ppc_fmuls() {
ppc_grab_regsfpdac();
if (!ppc_confirm_inf_nan(reg_a, reg_c, true, 50)) {
float intermediate = (float)val_reg_a * (float)val_reg_c;
ppc_dblresult64_d = static_cast<double>(intermediate);
float intermediate = (float)val_reg_a - (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, SUB>(reg_a, reg_b, 0);
}
if (rc_flag)
@ -476,10 +438,31 @@ void dppc_interpreter::ppc_fmuls() {
void dppc_interpreter::ppc_fdivs() {
ppc_grab_regsfpdab();
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
float intermediate = (float)val_reg_a / (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
float intermediate = (float)val_reg_a / (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, DIV>(reg_a, reg_b, 0);
}
if (rc_flag)
ppc_changecrf1();
}
void dppc_interpreter::ppc_fmuls() {
ppc_grab_regsfpdac();
float intermediate = (float)val_reg_a * (float)val_reg_c;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, MUL>(reg_a, 0, reg_c);
}
if (rc_flag)
@ -489,16 +472,14 @@ void dppc_interpreter::ppc_fdivs() {
void dppc_interpreter::ppc_fmadds() {
ppc_grab_regsfpdabc();
float intermediate;
ppc_dblresult64_d = static_cast<double>(
std::fma((float)val_reg_a, (float)val_reg_c, (float)val_reg_b));
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
intermediate = (float)val_reg_a * (float)val_reg_c;
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
intermediate += (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_sfpresult_flt(reg_d);
}
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, FMADD>(reg_a, reg_b, reg_c);
}
if (rc_flag)
@ -508,16 +489,15 @@ void dppc_interpreter::ppc_fmadds() {
void dppc_interpreter::ppc_fmsubs() {
ppc_grab_regsfpdabc();
float intermediate;
float intermediate = (float)val_reg_a * (float)val_reg_c;
intermediate -= (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
intermediate = (float)val_reg_a * (float)val_reg_c;
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
intermediate -= (float)val_reg_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_sfpresult_flt(reg_d);
}
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, FMSUB>(reg_a, reg_b, reg_c);
}
if (rc_flag)
@ -527,18 +507,16 @@ void dppc_interpreter::ppc_fmsubs() {
void dppc_interpreter::ppc_fnmadds() {
ppc_grab_regsfpdabc();
float intermediate;
float intermediate = (float)val_reg_a * (float)val_reg_c;
intermediate += (float)val_reg_b;
intermediate = -intermediate;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
intermediate = (float)val_reg_a * (float)val_reg_c;
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
intermediate += (float)val_reg_b;
intermediate = -intermediate;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_sfpresult_flt(reg_d);
}
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, FNMADD>(reg_a, reg_b, reg_c);
}
if (rc_flag)
@ -548,18 +526,17 @@ void dppc_interpreter::ppc_fnmadds() {
void dppc_interpreter::ppc_fnmsubs() {
ppc_grab_regsfpdabc();
float intermediate;
float intermediate = (float)val_reg_a * (float)val_reg_c;
intermediate -= (float)val_reg_b;
intermediate = -intermediate;
ppc_dblresult64_d = static_cast<double>(intermediate);
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
intermediate = (float)val_reg_a * (float)val_reg_c;
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
intermediate -= (float)val_reg_b;
intermediate = -intermediate;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_sfpresult_flt(reg_d);
}
if (!isnan(ppc_dblresult64_d)) {
ppc_store_sfpresult_flt(reg_d);
fpresult_update(ppc_dblresult64_d, rc_flag);
} else {
ppc_confirm_inf_nan<float, FNMSUB>(reg_a, reg_b, reg_c);
}
if (rc_flag)
@ -603,7 +580,7 @@ void dppc_interpreter::ppc_fneg() {
void dppc_interpreter::ppc_fsel() {
ppc_grab_regsfpdabc();
ppc_dblresult64_d = (val_reg_a >= 0.0) ? val_reg_c : val_reg_b;
ppc_dblresult64_d = (val_reg_a >= -0.0) ? val_reg_c : val_reg_b;
ppc_store_dfpresult_flt(reg_d);
@ -658,11 +635,23 @@ void dppc_interpreter::ppc_frsp() {
void dppc_interpreter::ppc_fres() {
ppc_grab_regsfpdb();
float testf2 = (float)GET_FPR(reg_b);
double start_num = GET_FPR(reg_b);
float testf2 = (float)start_num;
testf2 = 1 / testf2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult_flt(reg_d);
if (start_num == 0.0) {
ppc_state.fpscr |= FPSCR::ZX;
}
else if (std::isnan(start_num)) {
ppc_state.fpscr |= FPSCR::VXSNAN;
}
else if (std::isinf(start_num)){
ppc_state.fpscr |= FPSCR::VXSNAN;
ppc_state.fpscr &= 0xFFF9FFFF;
}
if (rc_flag)
ppc_changecrf1();
}
@ -673,26 +662,30 @@ void dppc_interpreter::ppc_fctiw() {
if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100;
ppc_state.fpscr |= FPSCR::VXSNAN | FPSCR::VXCVI;
}
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100;
ppc_state.fpscr |= FPSCR::VXCVI;
}
else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100;
ppc_state.fpscr |= FPSCR::VXCVI;
}
else {
switch (ppc_state.fpscr & 0x3) {
case 0:
ppc_result64_d = round_to_nearest(val_reg_b);
break;
case 1:
ppc_result64_d = round_to_zero(val_reg_b);
break;
case 2:
ppc_result64_d = round_to_pos_inf(val_reg_b);
break;
case 3:
ppc_result64_d = round_to_neg_inf(val_reg_b);
break;
}
ppc_store_dfpresult_int(reg_d);
@ -709,15 +702,15 @@ void dppc_interpreter::ppc_fctiwz() {
if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100;
ppc_state.fpscr |= FPSCR::VXSNAN | FPSCR::VXCVI;
}
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100;
ppc_state.fpscr |= FPSCR::VXCVI;
}
else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100;
ppc_state.fpscr |= FPSCR::VXCVI;
}
else {
ppc_result64_d = round_to_zero(val_reg_b);
@ -914,22 +907,14 @@ void dppc_interpreter::ppc_fmr() {
ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r;
}
void dppc_interpreter::ppc_mffs() {
ppc_grab_regsda();
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000;
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
fpstore1 |= fpstore2;
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & ((uint64_t)0xFFF80000 << 32);
fpstore1 |= (uint64_t)ppc_state.fpscr;
fp_save_uint64(fpstore1);
}
void dppc_interpreter::ppc_mffsdot() {
ppc_grab_regsda();
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000;
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
fpstore1 |= fpstore2;
fp_save_uint64(fpstore1);
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
}
void dppc_interpreter::ppc_mtfsf() {
@ -945,22 +930,9 @@ void dppc_interpreter::ppc_mtfsf() {
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
}
void dppc_interpreter::ppc_mtfsfdot() {
reg_b = (ppc_cur_instruction >> 11) & 31;
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
crm += (((fm_mask >> 1) & 1) == 1) ? 0x0F000000 : 0x00000000;
crm += (((fm_mask >> 2) & 1) == 1) ? 0x00F00000 : 0x00000000;
crm += (((fm_mask >> 3) & 1) == 1) ? 0x000F0000 : 0x00000000;
crm += (((fm_mask >> 4) & 1) == 1) ? 0x0000F000 : 0x00000000;
crm += (((fm_mask >> 5) & 1) == 1) ? 0x00000F00 : 0x00000000;
crm += (((fm_mask >> 6) & 1) == 1) ? 0x000000F0 : 0x00000000;
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
}
void dppc_interpreter::ppc_mtfsfi() {
@ -969,15 +941,9 @@ void dppc_interpreter::ppc_mtfsfi() {
crf_d = crf_d << 2;
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
}
void dppc_interpreter::ppc_mtfsfidot() {
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
}
void dppc_interpreter::ppc_mtfsb0() {
@ -985,14 +951,9 @@ void dppc_interpreter::ppc_mtfsb0() {
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
}
}
void dppc_interpreter::ppc_mtfsb0dot() {
crf_d = (ppc_cur_instruction >> 21) & 0x1F;
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
}
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
}
void dppc_interpreter::ppc_mtfsb1() {
@ -1000,14 +961,9 @@ void dppc_interpreter::ppc_mtfsb1() {
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr |= (0x80000000UL >> crf_d);
}
}
void dppc_interpreter::ppc_mtfsb1dot() {
crf_d = (ppc_cur_instruction >> 21) & 0x1F;
if ((crf_d == 0) || (crf_d > 2)) {
ppc_state.fpscr |= (0x80000000UL >> crf_d);
}
ppc_fp_changecrf1();
if (rc_flag)
ppc_fp_changecrf1();
}
void dppc_interpreter::ppc_mcrfs() {
@ -1027,25 +983,28 @@ void dppc_interpreter::ppc_fcmpo() {
ppc_state.fpscr &= 0xFFFF0FFF;
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
cmp_c |= 0x01;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_SO);
} else if (db_test_a < db_test_b) {
cmp_c |= 0x08;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_LT);
} else if (db_test_a > db_test_b) {
cmp_c |= 0x04;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_GT);
} else {
cmp_c |= 0x02;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_EQ);
}
ppc_state.fpscr |= (cmp_c << 12);
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
fpresult_update(db_test_a, true);
if ((db_test_a == snan) || (db_test_b == snan)) {
ppc_state.fpscr |= 0x1000000;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FPRF)) | (cmp_c << 12);
ppc_state.cr =
((ppc_state.cr & ~((uint32_t)CR_select::CR0_field >> crf_d)) | ((cmp_c + xercon) >> crf_d));
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
ppc_state.fpscr |= FPSCR::VXSNAN;
if (ppc_state.fpscr & 0x80) {
ppc_state.fpscr |= 0x80000;
ppc_state.fpscr |= FPSCR::VXVC;
}
} else if ((db_test_a == qnan) || (db_test_b == qnan)) {
ppc_state.fpscr |= 0x80000;
ppc_state.fpscr |= FPSCR::VXVC;
}
}
@ -1055,19 +1014,22 @@ void dppc_interpreter::ppc_fcmpu() {
ppc_state.fpscr &= 0xFFFF0FFF;
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
cmp_c |= 0x01;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_SO);
} else if (db_test_a < db_test_b) {
cmp_c |= 0x08;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_LT);
} else if (db_test_a > db_test_b) {
cmp_c |= 0x04;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_GT);
} else {
cmp_c |= 0x02;
cmp_c |= (1 << (uint32_t)CRx_bit::CR_EQ);
}
ppc_state.fpscr |= (cmp_c << 12);
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
fpresult_update(db_test_a, true);
if ((db_test_a == snan) || (db_test_b == snan)) {
ppc_state.fpscr |= 0x1000000;
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FPRF)) | (cmp_c << 12);
ppc_state.cr =
((ppc_state.cr & ~((uint32_t)CR_select::CR0_field >> crf_d)) | ((cmp_c + xercon) >> crf_d));
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
ppc_state.fpscr |= FPSCR::VXSNAN;
}
}

View File

@ -127,14 +127,18 @@ def gen_ppc_opcode(opc_str, imm):
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1)
elif opc_str == "FDIV.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1) + 1
elif opc_str == "FDIVS":
return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1)
elif opc_str == "FDIVS.":
return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1) + 1
elif opc_str == "FMADD":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1D << 1)
elif opc_str == "FMADD.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1D << 1) + 1
elif opc_str == "FMADDS":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1D << 1)
elif opc_str == "FMADDS.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1D << 1) + 1
elif opc_str == "FMUL":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1)
elif opc_str == "FMUL.":
@ -152,29 +156,29 @@ def gen_ppc_opcode(opc_str, imm):
elif opc_str == "FMULS.":
return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x28 << 1) + 1
elif opc_str == "FMSUB":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1)
elif opc_str == "FMSUB.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1) + 1
elif opc_str == "FMSUBS":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1)
elif opc_str == "FMSUBS.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1) + 1
elif opc_str == "FNMADD":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1F << 1)
elif opc_str == "FNMADD.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1F << 1) + 1
elif opc_str == "FNMADDS":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1F << 1)
elif opc_str == "FNMADDS.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1F << 1) + 1
elif opc_str == "FNMSUB":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1)
elif opc_str == "FNMSUB.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1) + 1
elif opc_str == "FNMSUBS":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1)
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1)
elif opc_str == "FNMSUBS.":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (5 << 6) + (0x1C << 1) + 1
elif opc_str == "FSUB":
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1)
elif opc_str == "FSUB.":
@ -346,7 +350,6 @@ def extract_rot_params(line):
pos += 16
return (sh, mb, me)
if __name__ == "__main__":
with open("ppcinttest.txt", "r") as in_file:
with open("ppcinttests.csv", "w") as out_file:
@ -404,41 +407,152 @@ if __name__ == "__main__":
line = line.strip()
opcode = (line[0:8]).rstrip().upper()
out_file.write(opcode + ",")
out_file.write(opcode+ ",")
out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, 0)))
if opcode.startswith("RLWI"):
sh, mb, me = extract_rot_params(line)
out_file.write("0x{:X}".format(gen_rot_opcode(opcode, sh, mb, me)))
else:
imm = extract_imm(line)
out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, imm)))
pos = 12
pos = 10
checkstring = ''
while pos < len(line):
reg_id = line[pos:pos+4]
if reg_id.startswith("frD"):
out_file.write(",frD=" + line[pos+4:pos+14])
pos += 16
elif reg_id.startswith("frA"):
out_file.write(",frA=" + line[pos+4:pos+14])
pos += 16
elif reg_id.startswith("frB"):
out_file.write(",frB=" + line[pos+4:pos+14])
pos += 16
elif reg_id.startswith("frC"):
out_file.write(",frC=" + line[pos+4:pos+14])
pos += 16
elif reg_id.startswith("FPSCR:"):
out_file.write(",FPSCR=" + line[pos+7:pos+17])
pos += 19
elif reg_id.startswith("CR:"):
out_file.write(",CR=" + line[pos+4:pos+14])
pos += 17
elif reg_id.startswith("imm"):
pos += 17 # ignore immediate operands
else:
out_file.write("Unknown reg ID" + reg_id)
break
if (line[pos].isalnum()):
checkstring += line[pos]
if ("RTN" in checkstring):
if (line[pos+1:pos+2] == "I"):
out_file.write(",round=RNI")
checkstring = ''
else:
out_file.write(",round=RTN")
checkstring = ''
pos += 1
elif ("RTZ" in checkstring):
out_file.write(",round=RTZ")
checkstring = ''
pos += 1
elif ("RTPI" in checkstring):
out_file.write(",round=RPI")
checkstring = ''
pos += 1
elif ("VE" in checkstring):
out_file.write(",round=VEN")
checkstring = ''
pos += 1
elif ("frD" in checkstring):
out_file.write(",frD=0x" + line[pos+4:pos+20])
checkstring = ''
elif ("frA" in checkstring): #sloppy temp code
check2 = line[pos+1:pos+10]
if ("-inf" in check2):
out_file.write(",frA=-inf")
elif ("inf" in check2):
out_file.write(",frA=inf")
pos += 1
elif ("nan" in check2):
out_file.write(",frA=nan")
pos += 1
elif ("-0." or "-2." or "-4." or \
"-6." or "-8." or "-7." or\
"-5." or "-3." or "-1." or \
"-9." in check2):
get_pos = line[pos+2:pos+16].strip("|")
out_file.write(",frA=" + get_pos.strip())
elif ("0." or "2." or "4." or \
"6." or "8." or "7." or\
"5." or "3." or "1." or \
"9." in check2):
get_pos = line[pos+2:pos+15]
out_file.write(",frA=" + get_pos.strip())
checkstring = ''
elif ("frB" in checkstring): #sloppy temp code
check2 = line[pos+1:pos+10]
if ("-inf" in check2):
out_file.write(",frB=-inf")
elif ("inf" in check2):
out_file.write(",frB=inf")
pos += 1
elif ("nan" in check2):
out_file.write(",frB=nan")
pos += 1
elif ("-0." or "-2." or "-4." or \
"-6." or "-8." or "-7." or\
"-5." or "-3." or "-1." or \
"-9." in check2):
get_pos = line[pos+2:pos+16].strip("|")
out_file.write(",frB=" + get_pos.strip())
elif ("0." or "2." or "4." or \
"6." or "8." or "7." or\
"5." or "3." or "1." or \
"9." in check2):
get_pos = line[pos+2:pos+15]
out_file.write(",frB=" + get_pos.strip())
checkstring = ''
elif ("frC" in checkstring): #sloppy temp code
check2 = line[pos+1:pos+10]
if ("-inf" in check2):
out_file.write(",frC=-inf")
elif ("inf" in check2):
out_file.write(",frC=inf")
pos += 1
elif ("nan" in check2):
out_file.write(",frC=nan")
pos += 1
elif ("-0." or "-2." or "-4." or \
"-6." or "-8." or "-7." or\
"-5." or "-3." or "-1." or \
"-9." in check2):
get_pos = line[pos+2:pos+16].strip("|")
out_file.write(",frC=" + get_pos.strip())
elif ("0." or "2." or "4." or \
"6." or "8." or "7." or\
"5." or "3." or "1." or \
"9." in check2):
get_pos = line[pos+2:pos+15]
out_file.write(",frC=" + get_pos.strip())
checkstring = ''
elif ("FPSCR" in checkstring):
out_file.write(",FPSCR=" + line[pos+3:pos+13])
checkstring = ''
elif ("CR" in checkstring):
out_file.write(",CR=0x0" + line[pos+6:pos+14])
checkstring = ''
pos += 1
out_file.write("\n")
# reg_id = line[pos:pos+4]
# if reg_id.startswith("frD"):
# out_file.write(",frD=" + line[pos+4:pos+22])
# pos += 24
# elif reg_id.startswith("frA"):
# out_file.write(",frA=" + line[pos+4:pos+14])
# pos += 16
# elif reg_id.startswith("frB"):
# out_file.write(",frB=" + line[pos+4:pos+14])
# pos += 16
# elif reg_id.startswith("frC"):
# out_file.write(",frC=" + line[pos+4:pos+14])
# pos += 16
# elif reg_id.startswith("FPSCR:"):
# out_file.write(",FPSCR=" + line[pos+7:pos+17])
# pos += 19
# elif reg_id.startswith("CR:"):
# out_file.write(",CR=" + line[pos+4:pos+14])
# pos += 17
# elif reg_id.startswith("VE)"):
# out_file.write("round=VEN" + line[pos+4:pos+20])
# pos += 17
# elif reg_id.startswith("TN)"):
# out_file.write("round=RTN" + line[pos+4:pos+20])
# pos += 17
# elif reg_id.startswith("TZ)"):
# out_file.write("round=RTZ" + line[pos+4:pos+20])
# pos += 17
# elif reg_id.startswith("NI)"):
# out_file.write("round=RNI" + line[pos+4:pos+20])
# pos += 17
# elif reg_id.startswith("PI)"):
# out_file.write("round=RPI" + line[pos+4:pos+20])
# pos += 17
# else:
# out_file.write("Unknown reg ID" + reg_id)
# break
out_file.write("\n")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#include "../ppcdisasm.h"
#include "../ppcemu.h"
#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>
@ -148,7 +149,7 @@ static void read_test_float_data() {
uint32_t opcode, dest, src1, src2, check_xer, check_cr, check_fpscr;
uint64_t dest_64, src1_64, src2_64;
float sfp_dest, sfp_src1, sfp_src2, sfp_src3;
//float sfp_dest, sfp_src1, sfp_src2, sfp_src3;
double dfp_dest, dfp_src1, dfp_src2, dfp_src3;
string rounding_mode;
@ -181,48 +182,50 @@ static void read_test_float_data() {
opcode = stoul(tokens[1], NULL, 16);
dest = 0;
src1 = 0;
src2 = 0;
check_xer = 0;
check_cr = 0;
check_fpscr = 0;
sfp_dest = 0.0;
sfp_src1 = 0.0;
sfp_src2 = 0.0;
sfp_src3 = 0.0;
//sfp_dest = 0.0;
//sfp_src1 = 0.0;
//sfp_src2 = 0.0;
//sfp_src3 = 0.0;
dfp_dest = 0.0;
dfp_src1 = 0.0;
dfp_src2 = 0.0;
dfp_src3 = 0.0;
dest_64 = 0;
for (i = 2; i < tokens.size(); i++) {
if (tokens[i].rfind("frD=", 0) == 0) {
dfp_dest = stoul(tokens[i].substr(4), NULL, 16);
dest_64 = stoull(tokens[i].substr(4), NULL, 16);
} else if (tokens[i].rfind("frA=", 0) == 0) {
dfp_src1 = stoul(tokens[i].substr(4), NULL, 16);
dfp_src1 = stod(tokens[i].substr(4), NULL);
} else if (tokens[i].rfind("frB=", 0) == 0) {
dfp_src2 = stoul(tokens[i].substr(4), NULL, 16);
dfp_src2 = stod(tokens[i].substr(4), NULL);
} else if (tokens[i].rfind("frC=", 0) == 0) {
dfp_src3 = stoul(tokens[i].substr(4), NULL, 16);
dfp_src3 = stod(tokens[i].substr(4), NULL);
} else if (tokens[i].rfind("round=", 0) == 0) {
rounding_mode = tokens[i].substr(6, 3);
ppc_state.fpscr &= 0xFFFFFFFC;
if (rounding_mode.compare("RTN") == 0) {
ppc_state.fpscr |= 0x0;
ppc_state.fpscr = 0x0;
} else if (rounding_mode.compare("RTZ") == 0) {
ppc_state.fpscr |= 0x1;
ppc_state.fpscr = 0x1;
} else if (rounding_mode.compare("RPI") == 0) {
ppc_state.fpscr |= 0x2;
ppc_state.fpscr = 0x2;
} else if (rounding_mode.compare("RNI") == 0) {
ppc_state.fpscr |= 0x3;
ppc_state.fpscr = 0x3;
} else if (rounding_mode.compare("VEN") == 0) {
ppc_state.fpscr = FPSCR::VE;
} else {
cout << "ILLEGAL ROUNDING METHOD: " << tokens[i] << " in line " << lineno
<< ". Exiting..." << endl;
exit(0);
}
} else if (tokens[i].rfind("FPSCR=", 0) == 0) {
check_cr = stoul(tokens[i].substr(6), NULL, 16);
check_fpscr = stoul(tokens[i].substr(6), NULL, 16);
} else if (tokens[i].rfind("CR=", 0) == 0) {
check_cr = stoul(tokens[i].substr(3), NULL, 16);
} else {
@ -239,7 +242,6 @@ static void read_test_float_data() {
ppc_state.fpr[4].dbl64_r = dfp_src2;
ppc_state.fpr[5].dbl64_r = dfp_src3;
ppc_state.spr[SPR::XER] = 0;
ppc_state.cr = 0;
ppc_cur_instruction = opcode;
@ -248,13 +250,14 @@ static void read_test_float_data() {
ntested++;
if ((tokens[0].rfind("FCMP") && (ppc_state.gpr[3] != dest)) || (ppc_state.fpscr != check_fpscr) ||
if ((tokens[0].rfind("FCMP") && (ppc_state.fpr[3].int64_r != dest_64)) ||
(ppc_state.fpscr != check_fpscr) ||
(ppc_state.cr != check_cr)) {
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1 << ", src2=0x" << hex
<< src2 << endl;
cout << "expected: dest=0x" << hex << dest << ", FPSCR=0x" << hex << check_xer << ", CR=0x"
cout << "Mismatch: instr=" << tokens[0] << ", src1=" << scientific << dfp_src1 << ", src2=" << scientific << dfp_src2 << ", src3=" << scientific << dfp_src3 << endl;
cout << "expected: dest=0x" << hex << dest_64 << ", FPSCR=0x" << hex << check_fpscr
<< ", CR=0x"
<< hex << check_cr << endl;
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", FPSCR=0x" << hex
cout << "got: dest=0x" << hex << ppc_state.fpr[3].int64_r << ", FPSCR=0x" << hex
<< ppc_state.fpscr << ", CR=0x" << hex << ppc_state.cr << endl;
cout << "Test file line #: " << dec << lineno << endl << endl;