mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-06-12 11:29:29 +00:00
Add rounding control for the host FPU.
This commit is contained in:
parent
b59c2be12d
commit
6abb07e61b
|
@ -402,7 +402,8 @@ extern void ppc_store_result_regd();
|
||||||
extern void ppc_store_result_rega();
|
extern void ppc_store_result_rega();
|
||||||
|
|
||||||
void ppc_changecrf0(uint32_t set_result);
|
void ppc_changecrf0(uint32_t set_result);
|
||||||
void ppc_fp_changecrf1();
|
void set_host_rounding_mode(uint8_t mode);
|
||||||
|
void update_fpscr(uint32_t new_fpscr);
|
||||||
|
|
||||||
/* Exception handlers. */
|
/* Exception handlers. */
|
||||||
void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
||||||
|
|
|
@ -751,6 +751,17 @@ void initialize_ppc_opcode_tables() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ppc_fpu_init() {
|
||||||
|
// zero all FPRs as prescribed for MPC601
|
||||||
|
// For later PPC CPUs, GPR content is undefined
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
ppc_state.fpr[i].int64_r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppc_state.fpscr = 0;
|
||||||
|
set_host_rounding_mode(0);
|
||||||
|
}
|
||||||
|
|
||||||
void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -783,12 +794,6 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
||||||
ppc_state.gpr[i] = 0;
|
ppc_state.gpr[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zero all FPRs as prescribed for MPC601 */
|
|
||||||
/* For later PPC CPUs, GPR content is undefined */
|
|
||||||
for (i = 0; i < 32; i++) {
|
|
||||||
ppc_state.fpr[i].int64_r = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* zero all segment registers as prescribed for MPC601 */
|
/* zero all segment registers as prescribed for MPC601 */
|
||||||
/* For later PPC CPUs, SR content is undefined */
|
/* For later PPC CPUs, SR content is undefined */
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
|
@ -796,7 +801,8 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
||||||
}
|
}
|
||||||
|
|
||||||
ppc_state.cr = 0;
|
ppc_state.cr = 0;
|
||||||
ppc_state.fpscr = 0;
|
|
||||||
|
ppc_fpu_init();
|
||||||
|
|
||||||
ppc_state.pc = 0;
|
ppc_state.pc = 0;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#include "ppcemu.h"
|
#include "ppcemu.h"
|
||||||
#include "ppcmmu.h"
|
#include "ppcmmu.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <cfenv>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
@ -134,6 +135,30 @@ int64_t round_to_nearest(double f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_host_rounding_mode(uint8_t mode) {
|
||||||
|
switch(mode & FPSCR::RN_MASK) {
|
||||||
|
case 0:
|
||||||
|
std::fesetround(FE_TONEAREST);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
std::fesetround(FE_TOWARDZERO);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
std::fesetround(FE_UPWARD);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
std::fesetround(FE_DOWNWARD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_fpscr(uint32_t new_fpscr) {
|
||||||
|
if ((new_fpscr & FPSCR::RN_MASK) != (ppc_state.fpscr & FPSCR::RN_MASK))
|
||||||
|
set_host_rounding_mode(new_fpscr & FPSCR::RN_MASK);
|
||||||
|
|
||||||
|
ppc_state.fpscr = new_fpscr;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t round_to_zero(double f) {
|
int64_t round_to_zero(double f) {
|
||||||
return static_cast<int32_t>(std::trunc(f));
|
return static_cast<int32_t>(std::trunc(f));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "../ppcdisasm.h"
|
#include "../ppcdisasm.h"
|
||||||
#include "../ppcemu.h"
|
#include "../ppcemu.h"
|
||||||
|
#include <cfenv>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -186,7 +187,7 @@ static void read_test_float_data() {
|
||||||
lineno++;
|
lineno++;
|
||||||
|
|
||||||
if (line.empty() || !line.rfind("#", 0))
|
if (line.empty() || !line.rfind("#", 0))
|
||||||
continue; /* skip empty/comment lines */
|
continue; // skip empty/comment lines
|
||||||
|
|
||||||
istringstream lnstream(line);
|
istringstream lnstream(line);
|
||||||
|
|
||||||
|
@ -208,16 +209,15 @@ static void read_test_float_data() {
|
||||||
check_xer = 0;
|
check_xer = 0;
|
||||||
check_cr = 0;
|
check_cr = 0;
|
||||||
check_fpscr = 0;
|
check_fpscr = 0;
|
||||||
//sfp_dest = 0.0;
|
|
||||||
//sfp_src1 = 0.0;
|
|
||||||
//sfp_src2 = 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;
|
dest_64 = 0;
|
||||||
|
|
||||||
|
// switch to default rounding
|
||||||
|
fesetround(FE_TONEAREST);
|
||||||
|
|
||||||
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) {
|
||||||
dest_64 = stoull(tokens[i].substr(4), NULL, 16);
|
dest_64 = stoull(tokens[i].substr(4), NULL, 16);
|
||||||
|
@ -229,22 +229,6 @@ static void read_test_float_data() {
|
||||||
dfp_src3 = stod(tokens[i].substr(4), NULL);
|
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 = 0;
|
|
||||||
if (rounding_mode.compare("RTN") == 0) {
|
|
||||||
ppc_state.fpscr = 0x0;
|
|
||||||
} else if (rounding_mode.compare("RTZ") == 0) {
|
|
||||||
ppc_state.fpscr = 0x1;
|
|
||||||
} else if (rounding_mode.compare("RPI") == 0) {
|
|
||||||
ppc_state.fpscr = 0x2;
|
|
||||||
} else if (rounding_mode.compare("RNI") == 0) {
|
|
||||||
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) {
|
} else if (tokens[i].rfind("FPSCR=", 0) == 0) {
|
||||||
check_fpscr = 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) {
|
||||||
|
@ -256,6 +240,22 @@ static void read_test_float_data() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rounding_mode.compare("RTN") == 0) {
|
||||||
|
update_fpscr(0);
|
||||||
|
} else if (rounding_mode.compare("RTZ") == 0) {
|
||||||
|
update_fpscr(1);
|
||||||
|
} else if (rounding_mode.compare("RPI") == 0) {
|
||||||
|
update_fpscr(2);
|
||||||
|
} else if (rounding_mode.compare("RNI") == 0) {
|
||||||
|
update_fpscr(3);
|
||||||
|
} else if (rounding_mode.compare("VEN") == 0) {
|
||||||
|
update_fpscr(FPSCR::VE);
|
||||||
|
} else {
|
||||||
|
cout << "ILLEGAL ROUNDING METHOD: " << tokens[i] << " in line " << lineno
|
||||||
|
<< ". Exiting..." << endl;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
ppc_state.gpr[3] = src1;
|
ppc_state.gpr[3] = src1;
|
||||||
ppc_state.gpr[4] = src2;
|
ppc_state.gpr[4] = src2;
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ 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.cr = 0;
|
ppc_state.cr = 0;
|
||||||
|
|
||||||
ppc_cur_instruction = opcode;
|
ppc_cur_instruction = opcode;
|
||||||
|
|
||||||
|
@ -271,6 +271,9 @@ static void read_test_float_data() {
|
||||||
|
|
||||||
ntested++;
|
ntested++;
|
||||||
|
|
||||||
|
// switch to default rounding
|
||||||
|
fesetround(FE_TONEAREST);
|
||||||
|
|
||||||
if ((tokens[0].rfind("FCMP") && (ppc_state.fpr[3].int64_r != dest_64)) ||
|
if ((tokens[0].rfind("FCMP") && (ppc_state.fpr[3].int64_r != dest_64)) ||
|
||||||
(ppc_state.fpscr != check_fpscr) ||
|
(ppc_state.fpscr != check_fpscr) ||
|
||||||
(ppc_state.cr != check_cr)) {
|
(ppc_state.cr != check_cr)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user