diff --git a/src/recompilation.cpp b/src/recompilation.cpp
index 5d1d027..5a171c7 100644
--- a/src/recompilation.cpp
+++ b/src/recompilation.cpp
@@ -141,6 +141,8 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
int fs = (int)instr.GetO32_fs();
int ft = (int)instr.GetO32_ft();
+ int cop1_cs = (int)instr.Get_cop1cs();
+
uint16_t imm = instr.Get_immediate();
std::string unsigned_imm_string;
@@ -524,10 +526,10 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
case InstrId::cpu_mfc1:
if ((fs & 1) == 0) {
// even fpr
- print_line("{}{} = ctx->f{}.u32l", ctx_gpr_prefix(rt), rt, fs);
+ print_line("{}{} = (int32_t)ctx->f{}.u32l", ctx_gpr_prefix(rt), rt, fs);
} else {
// odd fpr
- print_line("{}{} = ctx->f{}.u32h", ctx_gpr_prefix(rt), rt, fs - 1);
+ print_line("{}{} = (int32_t)ctx->f{}.u32h", ctx_gpr_prefix(rt), rt, fs - 1);
}
break;
//case InstrId::cpu_dmfc1:
@@ -543,7 +545,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
if ((ft & 1) == 0) {
// even fpr
print_line("ctx->f{}.u32l = MEM_W({}, {}{})", ft, signed_imm_string, ctx_gpr_prefix(base), base);
- print_line("NAN_CHECK(ctx->f{}.fl)", ft);
} else {
// odd fpr
print_line("ctx->f{}.u32h = MEM_W({}, {}{})", ft - 1, signed_imm_string, ctx_gpr_prefix(base), base);
@@ -552,7 +553,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
case InstrId::cpu_ldc1:
if ((ft & 1) == 0) {
print_line("ctx->f{}.u64 = LD({}, {}{})", ft, signed_imm_string, ctx_gpr_prefix(base), base);
- print_line("NAN_CHECK(ctx->f{}.d)", ft);
} else {
fmt::print(stderr, "Invalid operand for ldc1: f{}\n", ft);
return false;
@@ -648,7 +648,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
case InstrId::cpu_mov_s:
if ((fd & 1) == 0 && (fs & 1) == 0) {
// even fpr
- print_line("NAN_CHECK(ctx->f{}.fl)", fs);
print_line("ctx->f{}.fl = ctx->f{}.fl", fd, fs);
} else {
fmt::print(stderr, "Invalid operand(s) for mov.s: f{} f{}\n", fd, fs);
@@ -658,7 +657,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
case InstrId::cpu_mov_d:
if ((fd & 1) == 0 && (fs & 1) == 0) {
// even fpr
- print_line("NAN_CHECK(ctx->f{}.d)", fs);
print_line("ctx->f{}.d = ctx->f{}.d", fd, fs);
} else {
fmt::print(stderr, "Invalid operand(s) for mov.d: f{} f{}\n", fd, fs);
@@ -879,9 +877,19 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F
// return false;
// }
// break;
- // TODO rounding modes
case InstrId::cpu_ctc1:
+ if (cop1_cs != 31) {
+ fmt::print(stderr, "Invalid FP control register for ctc1: {}\n", cop1_cs);
+ return false;
+ }
+ print_line("rounding_mode = ({}{}) & 0x3", ctx_gpr_prefix(rt), rt);
+ break;
case InstrId::cpu_cfc1:
+ if (cop1_cs != 31) {
+ fmt::print(stderr, "Invalid FP control register for cfc1: {}\n", cop1_cs);
+ return false;
+ }
+ print_line("{}{} = rounding_mode", ctx_gpr_prefix(rt), rt);
break;
case InstrId::cpu_cvt_w_s:
if ((fd & 1) == 0 && (fs & 1) == 0) {
@@ -985,6 +993,7 @@ bool RecompPort::recompile_function(const RecompPort::Context& context, const Re
"void {}(uint8_t* rdram, recomp_context* ctx) {{\n"
// these variables shouldn't need to be preserved across function boundaries, so make them local for more efficient output
" uint64_t hi = 0, lo = 0, result = 0;\n"
+ " unsigned int rounding_mode = DEFAULT_ROUNDING_MODE;\n"
" int c1cs = 0; \n", // cop1 conditional signal
func.name);
diff --git a/test/RecompFuncs/RecompFuncs.vcxproj b/test/RecompFuncs/RecompFuncs.vcxproj
index 0cf8357..91f3d18 100644
--- a/test/RecompFuncs/RecompFuncs.vcxproj
+++ b/test/RecompFuncs/RecompFuncs.vcxproj
@@ -117,6 +117,7 @@
$(SolutionDir)..
true
+ false