mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-24 12:30:05 +00:00
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:
commit
7919cd0590
@ -169,6 +169,7 @@ if (DPPC_BUILD_PPC_TESTS)
|
|||||||
TARGET testppc POST_BUILD
|
TARGET testppc POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcinttests.csv"
|
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcinttests.csv"
|
||||||
|
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcfloattests.csv"
|
||||||
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcdisasmtest.csv"
|
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcdisasmtest.csv"
|
||||||
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
|
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
|
||||||
endif()
|
endif()
|
||||||
|
@ -200,6 +200,71 @@ enum class BB_end_kind {
|
|||||||
BB_RFI /* the rfi instruction is encountered */
|
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. */
|
/** PowerPC exception types. */
|
||||||
enum class Except_Type {
|
enum class Except_Type {
|
||||||
EXC_SYSTEM_RESET = 1,
|
EXC_SYSTEM_RESET = 1,
|
||||||
@ -271,7 +336,6 @@ void ppc_opcode63();
|
|||||||
|
|
||||||
void initialize_ppc_opcode_tables();
|
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 double fp_return_double(uint32_t reg);
|
||||||
extern uint64_t fp_return_uint64(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_mtfsb0();
|
||||||
extern void ppc_mtfsb1();
|
extern void ppc_mtfsb1();
|
||||||
extern void ppc_mcrfs();
|
extern void ppc_mcrfs();
|
||||||
extern void ppc_mtfsb0dot();
|
|
||||||
extern void ppc_mtfsb1dot();
|
|
||||||
extern void ppc_fmr();
|
extern void ppc_fmr();
|
||||||
extern void ppc_mffs();
|
extern void ppc_mffs();
|
||||||
extern void ppc_mffsdot();
|
|
||||||
extern void ppc_mtfsf();
|
extern void ppc_mtfsf();
|
||||||
extern void ppc_mtfsfdot();
|
|
||||||
extern void ppc_mtfsfi();
|
extern void ppc_mtfsfi();
|
||||||
extern void ppc_mtfsfidot();
|
|
||||||
|
|
||||||
extern void ppc_addi();
|
extern void ppc_addi();
|
||||||
extern void ppc_addic();
|
extern void ppc_addic();
|
||||||
|
@ -253,8 +253,7 @@ void ppc_opcode31() {
|
|||||||
oe_flag = ppc_cur_instruction & 0x400;
|
oe_flag = ppc_cur_instruction & 0x400;
|
||||||
|
|
||||||
#ifdef EXHAUSTIVE_DEBUG
|
#ifdef EXHAUSTIVE_DEBUG
|
||||||
uint32_t regrab = (uint32_t)subop_grab;
|
LOG_F(INFO, "Executing Opcode 31 table subopcode entry %n \n", (uint32_t)subop_grab);
|
||||||
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
|
|
||||||
#endif // EXHAUSTIVE_DEBUG
|
#endif // EXHAUSTIVE_DEBUG
|
||||||
|
|
||||||
SubOpcode31Grabber[subop_grab]();
|
SubOpcode31Grabber[subop_grab]();
|
||||||
@ -264,8 +263,7 @@ void ppc_opcode59() {
|
|||||||
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x1F;
|
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x1F;
|
||||||
rc_flag = ppc_cur_instruction & 1;
|
rc_flag = ppc_cur_instruction & 1;
|
||||||
#ifdef EXHAUSTIVE_DEBUG
|
#ifdef EXHAUSTIVE_DEBUG
|
||||||
uint32_t regrab = (uint32_t)subop_grab;
|
LOG_F(INFO, "Executing Opcode 59 table subopcode entry %n \n", (uint32_t)subop_grab);
|
||||||
LOG_F(INFO, "Executing Opcode 59 table subopcode entry \n", regrab);
|
|
||||||
#endif // EXHAUSTIVE_DEBUG
|
#endif // EXHAUSTIVE_DEBUG
|
||||||
SubOpcode59Grabber[subop_grab]();
|
SubOpcode59Grabber[subop_grab]();
|
||||||
}
|
}
|
||||||
@ -274,8 +272,7 @@ void ppc_opcode63() {
|
|||||||
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x3FF;
|
uint16_t subop_grab = (ppc_cur_instruction >> 1) & 0x3FF;
|
||||||
rc_flag = ppc_cur_instruction & 1;
|
rc_flag = ppc_cur_instruction & 1;
|
||||||
#ifdef EXHAUSTIVE_DEBUG
|
#ifdef EXHAUSTIVE_DEBUG
|
||||||
uint32_t regrab = (uint32_t)subop_grab;
|
LOG_F(INFO, "Executing Opcode 63 table subopcode entry %n \n", (uint32_t)subop_grab);
|
||||||
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
|
|
||||||
#endif // EXHAUSTIVE_DEBUG
|
#endif // EXHAUSTIVE_DEBUG
|
||||||
SubOpcode63Grabber[subop_grab]();
|
SubOpcode63Grabber[subop_grab]();
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include "ppcmmu.h"
|
#include "ppcmmu.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cfenv>
|
#include <cfenv>
|
||||||
|
#include <cfloat>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -150,20 +151,11 @@ void ppc_fp_changecrf1() {
|
|||||||
ppc_state.fpscr |= 0xf0000000;
|
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) {
|
int64_t round_to_nearest(double f) {
|
||||||
if (f >= 0.0) {
|
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 {
|
} 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));
|
return static_cast<int32_t>(floor(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc_toggle_fpscr_fex() {
|
void update_fex() {
|
||||||
bool fex_result = ((ppc_state.fpscr & 0x20000000) & (ppc_state.fpscr & 0x80));
|
int fex_result = !!((ppc_state.fpscr & (ppc_state.fpscr << 22)) & 0x3E000000);
|
||||||
fex_result |= ((ppc_state.fpscr & 0x10000000) & (ppc_state.fpscr & 0x40));
|
ppc_state.fpscr = (ppc_state.fpscr & ~0x40000000) | (fex_result << 30);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, bool is_single, uint32_t op) {
|
template <typename T, const FPOP fpop>
|
||||||
uint64_t input_a = ppc_state.fpr[chosen_reg_1].int64_r;
|
void ppc_confirm_inf_nan(int chosen_reg_1, int chosen_reg_2, int chosen_reg_3, bool rc_flag = false) {
|
||||||
uint64_t input_b = ppc_state.fpr[chosen_reg_2].int64_r;
|
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) {
|
ppc_state.fpscr &= 0x7fbfffff;
|
||||||
uint32_t exp_a = (input_a >> 23) & 0xff;
|
|
||||||
uint32_t exp_b = (input_b >> 23) & 0xff;
|
|
||||||
|
|
||||||
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) {
|
update_fex();
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 40:
|
case FPOP::FMADD:
|
||||||
if ((exp_a == 0xff) && (exp_b == 0xff)) {
|
case FPOP::FNMADD:
|
||||||
ppc_state.fpscr |= 0x80800000;
|
if (isnan(input_a) || isnan(input_b) || isnan(input_c)) {
|
||||||
ppc_toggle_fpscr_fex();
|
ppc_state.fpscr |= (FPSCR::VXSNAN | FPSCR::FPCC_FUNAN);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
update_fex();
|
||||||
break;
|
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);
|
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) {
|
if (confirm_ov) {
|
||||||
ppc_state.fpscr |= 0x80001000;
|
ppc_state.fpscr |= (FPSCR::FX | (FPSCR::FPRF & FPSCR::FPCC_FUNAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (confirm_arc) {
|
if (confirm_arc) {
|
||||||
ppc_state.fpscr |= 0x80010000;
|
ppc_state.fpscr |= (FPSCR::FX | (FPSCR::FPRF & FPSCR::FPCC_FUNAN));
|
||||||
ppc_state.fpscr &= 0xFFFF0FFF;
|
//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) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc_changecrf1() {
|
void ppc_changecrf1() {
|
||||||
ppc_state.cr &= 0xF0FFFFFF;
|
ppc_state.cr &= ~((uint32_t)CR_select::CR1_field);
|
||||||
ppc_state.cr |= (ppc_state.fpscr & 0xF0000000) >> 4;
|
ppc_state.cr |= (ppc_state.fpscr & (uint32_t)CR_select::CR0_field) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floating Point Arithmetic
|
// Floating Point Arithmetic
|
||||||
void dppc_interpreter::ppc_fadd() {
|
void dppc_interpreter::ppc_fadd() {
|
||||||
ppc_grab_regsfpdab();
|
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);
|
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)
|
if (rc_flag)
|
||||||
@ -335,9 +287,13 @@ void dppc_interpreter::ppc_fadd() {
|
|||||||
void dppc_interpreter::ppc_fsub() {
|
void dppc_interpreter::ppc_fsub() {
|
||||||
ppc_grab_regsfpdab();
|
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);
|
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)
|
if (rc_flag)
|
||||||
@ -347,9 +303,13 @@ void dppc_interpreter::ppc_fsub() {
|
|||||||
void dppc_interpreter::ppc_fdiv() {
|
void dppc_interpreter::ppc_fdiv() {
|
||||||
ppc_grab_regsfpdab();
|
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);
|
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)
|
if (rc_flag)
|
||||||
@ -359,9 +319,13 @@ void dppc_interpreter::ppc_fdiv() {
|
|||||||
void dppc_interpreter::ppc_fmul() {
|
void dppc_interpreter::ppc_fmul() {
|
||||||
ppc_grab_regsfpdac();
|
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);
|
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)
|
if (rc_flag)
|
||||||
@ -371,14 +335,14 @@ void dppc_interpreter::ppc_fmul() {
|
|||||||
void dppc_interpreter::ppc_fmadd() {
|
void dppc_interpreter::ppc_fmadd() {
|
||||||
ppc_grab_regsfpdabc();
|
ppc_grab_regsfpdabc();
|
||||||
|
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b);
|
||||||
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_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)
|
if (rc_flag)
|
||||||
ppc_changecrf1();
|
ppc_changecrf1();
|
||||||
@ -387,14 +351,15 @@ void dppc_interpreter::ppc_fmadd() {
|
|||||||
void dppc_interpreter::ppc_fmsub() {
|
void dppc_interpreter::ppc_fmsub() {
|
||||||
ppc_grab_regsfpdabc();
|
ppc_grab_regsfpdabc();
|
||||||
|
|
||||||
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);
|
ppc_dblresult64_d -= val_reg_b;
|
||||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
|
||||||
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)
|
if (rc_flag)
|
||||||
ppc_changecrf1();
|
ppc_changecrf1();
|
||||||
@ -403,15 +368,16 @@ void dppc_interpreter::ppc_fmsub() {
|
|||||||
void dppc_interpreter::ppc_fnmadd() {
|
void dppc_interpreter::ppc_fnmadd() {
|
||||||
ppc_grab_regsfpdabc();
|
ppc_grab_regsfpdabc();
|
||||||
|
|
||||||
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);
|
ppc_dblresult64_d += val_reg_b;
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
|
|
||||||
ppc_dblresult64_d += val_reg_b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
ppc_store_dfpresult_flt(reg_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)
|
if (rc_flag)
|
||||||
ppc_changecrf1();
|
ppc_changecrf1();
|
||||||
@ -420,15 +386,16 @@ void dppc_interpreter::ppc_fnmadd() {
|
|||||||
void dppc_interpreter::ppc_fnmsub() {
|
void dppc_interpreter::ppc_fnmsub() {
|
||||||
ppc_grab_regsfpdabc();
|
ppc_grab_regsfpdabc();
|
||||||
|
|
||||||
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);
|
ppc_dblresult64_d -= val_reg_b;
|
||||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
|
||||||
ppc_dblresult64_d -= val_reg_b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
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)
|
if (rc_flag)
|
||||||
ppc_changecrf1();
|
ppc_changecrf1();
|
||||||
@ -437,10 +404,14 @@ void dppc_interpreter::ppc_fnmsub() {
|
|||||||
void dppc_interpreter::ppc_fadds() {
|
void dppc_interpreter::ppc_fadds() {
|
||||||
ppc_grab_regsfpdab();
|
ppc_grab_regsfpdab();
|
||||||
|
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
float intermediate = (float)val_reg_a + (float)val_reg_b;
|
||||||
float intermediate = (float)val_reg_a + (float)val_reg_b;
|
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
|
||||||
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
ppc_store_sfpresult_flt(reg_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)
|
if (rc_flag)
|
||||||
@ -450,23 +421,14 @@ void dppc_interpreter::ppc_fadds() {
|
|||||||
void dppc_interpreter::ppc_fsubs() {
|
void dppc_interpreter::ppc_fsubs() {
|
||||||
ppc_grab_regsfpdab();
|
ppc_grab_regsfpdab();
|
||||||
|
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
|
float intermediate = (float)val_reg_a - (float)val_reg_b;
|
||||||
float intermediate = (float)val_reg_a - (float)val_reg_b;
|
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
|
||||||
ppc_store_sfpresult_flt(reg_d);
|
if (!isnan(ppc_dblresult64_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);
|
|
||||||
ppc_store_sfpresult_flt(reg_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)
|
if (rc_flag)
|
||||||
@ -476,10 +438,31 @@ void dppc_interpreter::ppc_fmuls() {
|
|||||||
void dppc_interpreter::ppc_fdivs() {
|
void dppc_interpreter::ppc_fdivs() {
|
||||||
ppc_grab_regsfpdab();
|
ppc_grab_regsfpdab();
|
||||||
|
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
|
float intermediate = (float)val_reg_a / (float)val_reg_b;
|
||||||
float intermediate = (float)val_reg_a / (float)val_reg_b;
|
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
|
||||||
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
ppc_store_sfpresult_flt(reg_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)
|
if (rc_flag)
|
||||||
@ -489,16 +472,14 @@ void dppc_interpreter::ppc_fdivs() {
|
|||||||
void dppc_interpreter::ppc_fmadds() {
|
void dppc_interpreter::ppc_fmadds() {
|
||||||
ppc_grab_regsfpdabc();
|
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)) {
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
intermediate = (float)val_reg_a * (float)val_reg_c;
|
ppc_store_sfpresult_flt(reg_d);
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
fpresult_update(ppc_dblresult64_d, rc_flag);
|
||||||
intermediate += (float)val_reg_b;
|
} else {
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
ppc_confirm_inf_nan<float, FMADD>(reg_a, reg_b, reg_c);
|
||||||
|
|
||||||
ppc_store_sfpresult_flt(reg_d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc_flag)
|
if (rc_flag)
|
||||||
@ -508,16 +489,15 @@ void dppc_interpreter::ppc_fmadds() {
|
|||||||
void dppc_interpreter::ppc_fmsubs() {
|
void dppc_interpreter::ppc_fmsubs() {
|
||||||
ppc_grab_regsfpdabc();
|
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)) {
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
intermediate = (float)val_reg_a * (float)val_reg_c;
|
ppc_store_sfpresult_flt(reg_d);
|
||||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
fpresult_update(ppc_dblresult64_d, rc_flag);
|
||||||
intermediate -= (float)val_reg_b;
|
} else {
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
ppc_confirm_inf_nan<float, FMSUB>(reg_a, reg_b, reg_c);
|
||||||
|
|
||||||
ppc_store_sfpresult_flt(reg_d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc_flag)
|
if (rc_flag)
|
||||||
@ -527,18 +507,16 @@ void dppc_interpreter::ppc_fmsubs() {
|
|||||||
void dppc_interpreter::ppc_fnmadds() {
|
void dppc_interpreter::ppc_fnmadds() {
|
||||||
ppc_grab_regsfpdabc();
|
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)) {
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
intermediate = (float)val_reg_a * (float)val_reg_c;
|
ppc_store_sfpresult_flt(reg_d);
|
||||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
fpresult_update(ppc_dblresult64_d, rc_flag);
|
||||||
intermediate += (float)val_reg_b;
|
} else {
|
||||||
intermediate = -intermediate;
|
ppc_confirm_inf_nan<float, FNMADD>(reg_a, reg_b, reg_c);
|
||||||
|
|
||||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
|
||||||
|
|
||||||
ppc_store_sfpresult_flt(reg_d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc_flag)
|
if (rc_flag)
|
||||||
@ -548,18 +526,17 @@ void dppc_interpreter::ppc_fnmadds() {
|
|||||||
void dppc_interpreter::ppc_fnmsubs() {
|
void dppc_interpreter::ppc_fnmsubs() {
|
||||||
ppc_grab_regsfpdabc();
|
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);
|
if (!isnan(ppc_dblresult64_d)) {
|
||||||
|
ppc_store_sfpresult_flt(reg_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)
|
if (rc_flag)
|
||||||
@ -603,7 +580,7 @@ void dppc_interpreter::ppc_fneg() {
|
|||||||
void dppc_interpreter::ppc_fsel() {
|
void dppc_interpreter::ppc_fsel() {
|
||||||
ppc_grab_regsfpdabc();
|
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);
|
ppc_store_dfpresult_flt(reg_d);
|
||||||
|
|
||||||
@ -658,11 +635,23 @@ void dppc_interpreter::ppc_frsp() {
|
|||||||
|
|
||||||
void dppc_interpreter::ppc_fres() {
|
void dppc_interpreter::ppc_fres() {
|
||||||
ppc_grab_regsfpdb();
|
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;
|
testf2 = 1 / testf2;
|
||||||
ppc_dblresult64_d = (double)testf2;
|
ppc_dblresult64_d = (double)testf2;
|
||||||
ppc_store_dfpresult_flt(reg_d);
|
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)
|
if (rc_flag)
|
||||||
ppc_changecrf1();
|
ppc_changecrf1();
|
||||||
}
|
}
|
||||||
@ -673,26 +662,30 @@ void dppc_interpreter::ppc_fctiw() {
|
|||||||
|
|
||||||
if (std::isnan(val_reg_b)) {
|
if (std::isnan(val_reg_b)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
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)) {
|
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 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)) {
|
else if (val_reg_b < -static_cast<double>(0x80000000)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
||||||
ppc_state.fpscr |= 0x100;
|
ppc_state.fpscr |= FPSCR::VXCVI;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (ppc_state.fpscr & 0x3) {
|
switch (ppc_state.fpscr & 0x3) {
|
||||||
case 0:
|
case 0:
|
||||||
ppc_result64_d = round_to_nearest(val_reg_b);
|
ppc_result64_d = round_to_nearest(val_reg_b);
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
ppc_result64_d = round_to_zero(val_reg_b);
|
ppc_result64_d = round_to_zero(val_reg_b);
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
ppc_result64_d = round_to_pos_inf(val_reg_b);
|
ppc_result64_d = round_to_pos_inf(val_reg_b);
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
ppc_result64_d = round_to_neg_inf(val_reg_b);
|
ppc_result64_d = round_to_neg_inf(val_reg_b);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppc_store_dfpresult_int(reg_d);
|
ppc_store_dfpresult_int(reg_d);
|
||||||
@ -709,15 +702,15 @@ void dppc_interpreter::ppc_fctiwz() {
|
|||||||
|
|
||||||
if (std::isnan(val_reg_b)) {
|
if (std::isnan(val_reg_b)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
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)) {
|
else if (val_reg_b > static_cast<double>(0x7fffffff)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 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)) {
|
else if (val_reg_b < -static_cast<double>(0x80000000)) {
|
||||||
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
ppc_state.fpr[reg_d].int64_r = 0x80000000;
|
||||||
ppc_state.fpscr |= 0x100;
|
ppc_state.fpscr |= FPSCR::VXCVI;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ppc_result64_d = round_to_zero(val_reg_b);
|
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;
|
ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mffs() {
|
void dppc_interpreter::ppc_mffs() {
|
||||||
ppc_grab_regsda();
|
ppc_grab_regsda();
|
||||||
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000;
|
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & ((uint64_t)0xFFF80000 << 32);
|
||||||
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
|
fpstore1 |= (uint64_t)ppc_state.fpscr;
|
||||||
fpstore1 |= fpstore2;
|
|
||||||
fp_save_uint64(fpstore1);
|
fp_save_uint64(fpstore1);
|
||||||
}
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mffsdot() {
|
if (rc_flag)
|
||||||
ppc_grab_regsda();
|
ppc_fp_changecrf1();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsf() {
|
void dppc_interpreter::ppc_mtfsf() {
|
||||||
@ -945,22 +930,9 @@ void dppc_interpreter::ppc_mtfsf() {
|
|||||||
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
|
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
|
||||||
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
|
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
|
||||||
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
|
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
|
||||||
}
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsfdot() {
|
if (rc_flag)
|
||||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
ppc_fp_changecrf1();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsfi() {
|
void dppc_interpreter::ppc_mtfsfi() {
|
||||||
@ -969,15 +941,9 @@ void dppc_interpreter::ppc_mtfsfi() {
|
|||||||
crf_d = crf_d << 2;
|
crf_d = crf_d << 2;
|
||||||
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
|
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
|
||||||
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||||
}
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsfidot() {
|
if (rc_flag)
|
||||||
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
|
ppc_fp_changecrf1();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsb0() {
|
void dppc_interpreter::ppc_mtfsb0() {
|
||||||
@ -985,14 +951,9 @@ void dppc_interpreter::ppc_mtfsb0() {
|
|||||||
if ((crf_d == 0) || (crf_d > 2)) {
|
if ((crf_d == 0) || (crf_d > 2)) {
|
||||||
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
|
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsb0dot() {
|
if (rc_flag)
|
||||||
crf_d = (ppc_cur_instruction >> 21) & 0x1F;
|
ppc_fp_changecrf1();
|
||||||
if ((crf_d == 0) || (crf_d > 2)) {
|
|
||||||
ppc_state.fpscr &= ~(0x80000000UL >> crf_d);
|
|
||||||
}
|
|
||||||
ppc_fp_changecrf1();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsb1() {
|
void dppc_interpreter::ppc_mtfsb1() {
|
||||||
@ -1000,14 +961,9 @@ void dppc_interpreter::ppc_mtfsb1() {
|
|||||||
if ((crf_d == 0) || (crf_d > 2)) {
|
if ((crf_d == 0) || (crf_d > 2)) {
|
||||||
ppc_state.fpscr |= (0x80000000UL >> crf_d);
|
ppc_state.fpscr |= (0x80000000UL >> crf_d);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mtfsb1dot() {
|
if (rc_flag)
|
||||||
crf_d = (ppc_cur_instruction >> 21) & 0x1F;
|
ppc_fp_changecrf1();
|
||||||
if ((crf_d == 0) || (crf_d > 2)) {
|
|
||||||
ppc_state.fpscr |= (0x80000000UL >> crf_d);
|
|
||||||
}
|
|
||||||
ppc_fp_changecrf1();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dppc_interpreter::ppc_mcrfs() {
|
void dppc_interpreter::ppc_mcrfs() {
|
||||||
@ -1027,25 +983,28 @@ void dppc_interpreter::ppc_fcmpo() {
|
|||||||
ppc_state.fpscr &= 0xFFFF0FFF;
|
ppc_state.fpscr &= 0xFFFF0FFF;
|
||||||
|
|
||||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
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) {
|
} 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) {
|
} else if (db_test_a > db_test_b) {
|
||||||
cmp_c |= 0x04;
|
cmp_c |= (1 << (uint32_t)CRx_bit::CR_GT);
|
||||||
} else {
|
} else {
|
||||||
cmp_c |= 0x02;
|
cmp_c |= (1 << (uint32_t)CRx_bit::CR_EQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppc_state.fpscr |= (cmp_c << 12);
|
fpresult_update(db_test_a, true);
|
||||||
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
||||||
|
|
||||||
if ((db_test_a == snan) || (db_test_b == snan)) {
|
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FPRF)) | (cmp_c << 12);
|
||||||
ppc_state.fpscr |= 0x1000000;
|
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) {
|
if (ppc_state.fpscr & 0x80) {
|
||||||
ppc_state.fpscr |= 0x80000;
|
ppc_state.fpscr |= FPSCR::VXVC;
|
||||||
}
|
}
|
||||||
} else if ((db_test_a == qnan) || (db_test_b == qnan)) {
|
} 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;
|
ppc_state.fpscr &= 0xFFFF0FFF;
|
||||||
|
|
||||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
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) {
|
} 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) {
|
} else if (db_test_a > db_test_b) {
|
||||||
cmp_c |= 0x04;
|
cmp_c |= (1 << (uint32_t)CRx_bit::CR_GT);
|
||||||
} else {
|
} else {
|
||||||
cmp_c |= 0x02;
|
cmp_c |= (1 << (uint32_t)CRx_bit::CR_EQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppc_state.fpscr |= (cmp_c << 12);
|
fpresult_update(db_test_a, true);
|
||||||
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
||||||
|
|
||||||
if ((db_test_a == snan) || (db_test_b == snan)) {
|
ppc_state.fpscr = (ppc_state.fpscr & ~(FPSCR::FPRF)) | (cmp_c << 12);
|
||||||
ppc_state.fpscr |= 0x1000000;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,14 +127,18 @@ def gen_ppc_opcode(opc_str, imm):
|
|||||||
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1)
|
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1)
|
||||||
elif opc_str == "FDIV.":
|
elif opc_str == "FDIV.":
|
||||||
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1) + 1
|
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":
|
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.":
|
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":
|
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.":
|
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":
|
elif opc_str == "FMUL":
|
||||||
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1)
|
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1)
|
||||||
elif opc_str == "FMUL.":
|
elif opc_str == "FMUL.":
|
||||||
@ -152,29 +156,29 @@ def gen_ppc_opcode(opc_str, imm):
|
|||||||
elif opc_str == "FMULS.":
|
elif opc_str == "FMULS.":
|
||||||
return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x28 << 1) + 1
|
return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x28 << 1) + 1
|
||||||
elif opc_str == "FMSUB":
|
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.":
|
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":
|
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.":
|
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":
|
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.":
|
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":
|
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.":
|
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":
|
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.":
|
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":
|
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.":
|
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":
|
elif opc_str == "FSUB":
|
||||||
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1)
|
return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1)
|
||||||
elif opc_str == "FSUB.":
|
elif opc_str == "FSUB.":
|
||||||
@ -346,7 +350,6 @@ def extract_rot_params(line):
|
|||||||
pos += 16
|
pos += 16
|
||||||
return (sh, mb, me)
|
return (sh, mb, me)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
with open("ppcinttest.txt", "r") as in_file:
|
with open("ppcinttest.txt", "r") as in_file:
|
||||||
with open("ppcinttests.csv", "w") as out_file:
|
with open("ppcinttests.csv", "w") as out_file:
|
||||||
@ -404,41 +407,152 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
opcode = (line[0:8]).rstrip().upper()
|
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"):
|
pos = 10
|
||||||
sh, mb, me = extract_rot_params(line)
|
checkstring = ''
|
||||||
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
|
|
||||||
|
|
||||||
while pos < len(line):
|
while pos < len(line):
|
||||||
reg_id = line[pos:pos+4]
|
if (line[pos].isalnum()):
|
||||||
if reg_id.startswith("frD"):
|
checkstring += line[pos]
|
||||||
out_file.write(",frD=" + line[pos+4:pos+14])
|
|
||||||
pos += 16
|
if ("RTN" in checkstring):
|
||||||
elif reg_id.startswith("frA"):
|
if (line[pos+1:pos+2] == "I"):
|
||||||
out_file.write(",frA=" + line[pos+4:pos+14])
|
out_file.write(",round=RNI")
|
||||||
pos += 16
|
checkstring = ''
|
||||||
elif reg_id.startswith("frB"):
|
else:
|
||||||
out_file.write(",frB=" + line[pos+4:pos+14])
|
out_file.write(",round=RTN")
|
||||||
pos += 16
|
checkstring = ''
|
||||||
elif reg_id.startswith("frC"):
|
pos += 1
|
||||||
out_file.write(",frC=" + line[pos+4:pos+14])
|
elif ("RTZ" in checkstring):
|
||||||
pos += 16
|
out_file.write(",round=RTZ")
|
||||||
elif reg_id.startswith("FPSCR:"):
|
checkstring = ''
|
||||||
out_file.write(",FPSCR=" + line[pos+7:pos+17])
|
pos += 1
|
||||||
pos += 19
|
elif ("RTPI" in checkstring):
|
||||||
elif reg_id.startswith("CR:"):
|
out_file.write(",round=RPI")
|
||||||
out_file.write(",CR=" + line[pos+4:pos+14])
|
checkstring = ''
|
||||||
pos += 17
|
pos += 1
|
||||||
elif reg_id.startswith("imm"):
|
elif ("VE" in checkstring):
|
||||||
pos += 17 # ignore immediate operands
|
out_file.write(",round=VEN")
|
||||||
else:
|
checkstring = ''
|
||||||
out_file.write("Unknown reg ID" + reg_id)
|
pos += 1
|
||||||
break
|
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
@ -1,5 +1,6 @@
|
|||||||
#include "../ppcdisasm.h"
|
#include "../ppcdisasm.h"
|
||||||
#include "../ppcemu.h"
|
#include "../ppcemu.h"
|
||||||
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -148,7 +149,7 @@ static void read_test_float_data() {
|
|||||||
|
|
||||||
uint32_t opcode, dest, src1, src2, check_xer, check_cr, check_fpscr;
|
uint32_t opcode, dest, src1, src2, check_xer, check_cr, check_fpscr;
|
||||||
uint64_t dest_64, src1_64, src2_64;
|
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;
|
double dfp_dest, dfp_src1, dfp_src2, dfp_src3;
|
||||||
string rounding_mode;
|
string rounding_mode;
|
||||||
|
|
||||||
@ -181,48 +182,50 @@ static void read_test_float_data() {
|
|||||||
|
|
||||||
opcode = stoul(tokens[1], NULL, 16);
|
opcode = stoul(tokens[1], NULL, 16);
|
||||||
|
|
||||||
dest = 0;
|
|
||||||
src1 = 0;
|
src1 = 0;
|
||||||
src2 = 0;
|
src2 = 0;
|
||||||
check_xer = 0;
|
check_xer = 0;
|
||||||
check_cr = 0;
|
check_cr = 0;
|
||||||
check_fpscr = 0;
|
check_fpscr = 0;
|
||||||
sfp_dest = 0.0;
|
//sfp_dest = 0.0;
|
||||||
sfp_src1 = 0.0;
|
//sfp_src1 = 0.0;
|
||||||
sfp_src2 = 0.0;
|
//sfp_src2 = 0.0;
|
||||||
sfp_src3 = 0.0;
|
//sfp_src3 = 0.0;
|
||||||
dfp_dest = 0.0;
|
dfp_dest = 0.0;
|
||||||
dfp_src1 = 0.0;
|
dfp_src1 = 0.0;
|
||||||
dfp_src2 = 0.0;
|
dfp_src2 = 0.0;
|
||||||
dfp_src3 = 0.0;
|
dfp_src3 = 0.0;
|
||||||
|
dest_64 = 0;
|
||||||
|
|
||||||
for (i = 2; i < tokens.size(); i++) {
|
for (i = 2; i < tokens.size(); i++) {
|
||||||
if (tokens[i].rfind("frD=", 0) == 0) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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) {
|
} else if (tokens[i].rfind("round=", 0) == 0) {
|
||||||
rounding_mode = tokens[i].substr(6, 3);
|
rounding_mode = tokens[i].substr(6, 3);
|
||||||
ppc_state.fpscr &= 0xFFFFFFFC;
|
ppc_state.fpscr &= 0xFFFFFFFC;
|
||||||
if (rounding_mode.compare("RTN") == 0) {
|
if (rounding_mode.compare("RTN") == 0) {
|
||||||
ppc_state.fpscr |= 0x0;
|
ppc_state.fpscr = 0x0;
|
||||||
} else if (rounding_mode.compare("RTZ") == 0) {
|
} else if (rounding_mode.compare("RTZ") == 0) {
|
||||||
ppc_state.fpscr |= 0x1;
|
ppc_state.fpscr = 0x1;
|
||||||
} else if (rounding_mode.compare("RPI") == 0) {
|
} else if (rounding_mode.compare("RPI") == 0) {
|
||||||
ppc_state.fpscr |= 0x2;
|
ppc_state.fpscr = 0x2;
|
||||||
} else if (rounding_mode.compare("RNI") == 0) {
|
} 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 {
|
} else {
|
||||||
cout << "ILLEGAL ROUNDING METHOD: " << tokens[i] << " in line " << lineno
|
cout << "ILLEGAL ROUNDING METHOD: " << tokens[i] << " in line " << lineno
|
||||||
<< ". Exiting..." << endl;
|
<< ". Exiting..." << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
} else if (tokens[i].rfind("FPSCR=", 0) == 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) {
|
} else if (tokens[i].rfind("CR=", 0) == 0) {
|
||||||
check_cr = stoul(tokens[i].substr(3), NULL, 16);
|
check_cr = stoul(tokens[i].substr(3), NULL, 16);
|
||||||
} else {
|
} else {
|
||||||
@ -239,7 +242,6 @@ static void read_test_float_data() {
|
|||||||
ppc_state.fpr[4].dbl64_r = dfp_src2;
|
ppc_state.fpr[4].dbl64_r = dfp_src2;
|
||||||
ppc_state.fpr[5].dbl64_r = dfp_src3;
|
ppc_state.fpr[5].dbl64_r = dfp_src3;
|
||||||
|
|
||||||
ppc_state.spr[SPR::XER] = 0;
|
|
||||||
ppc_state.cr = 0;
|
ppc_state.cr = 0;
|
||||||
|
|
||||||
ppc_cur_instruction = opcode;
|
ppc_cur_instruction = opcode;
|
||||||
@ -248,13 +250,14 @@ static void read_test_float_data() {
|
|||||||
|
|
||||||
ntested++;
|
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)) {
|
(ppc_state.cr != check_cr)) {
|
||||||
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1 << ", src2=0x" << hex
|
cout << "Mismatch: instr=" << tokens[0] << ", src1=" << scientific << dfp_src1 << ", src2=" << scientific << dfp_src2 << ", src3=" << scientific << dfp_src3 << endl;
|
||||||
<< src2 << endl;
|
cout << "expected: dest=0x" << hex << dest_64 << ", FPSCR=0x" << hex << check_fpscr
|
||||||
cout << "expected: dest=0x" << hex << dest << ", FPSCR=0x" << hex << check_xer << ", CR=0x"
|
<< ", CR=0x"
|
||||||
<< hex << check_cr << endl;
|
<< 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;
|
<< ppc_state.fpscr << ", CR=0x" << hex << ppc_state.cr << endl;
|
||||||
cout << "Test file line #: " << dec << lineno << endl << endl;
|
cout << "Test file line #: " << dec << lineno << endl << endl;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user