Add operands for other uses of float registers

This commit is contained in:
Mr-Wiseguy 2024-06-09 00:29:44 -04:00
parent c3de49c944
commit d91f1cf3a8

View file

@ -84,6 +84,21 @@ enum class Operand {
Fd, // FPR
Fs, // FPR
Ft, // FPR
FdDouble, // Double float in fd FPR
FsDouble, // Double float in fs FPR
FtDouble, // Double float in ft FPR
// Raw low 32-bit values of FPRs with handling for mips3 float mode behavior
FdU32L,
FsU32L,
FtU32L,
// Raw high 32-bit values of FPRs with handling for mips3 float mode behavior
FdU32H,
FsU32H,
FtU32H,
// Raw 64-bit values of FPRs
FdU64,
FsU64,
FtU64,
ImmU16, // 16-bit immediate, unsigned
ImmS16, // 16-bit immediate, signed
Sa, // Shift amount
@ -135,6 +150,8 @@ const std::unordered_map<InstrId, UnaryOp> unary_ops {
{ InstrId::cpu_mtlo, { UnaryOpType::None, Operand::Lo, Operand::Rs } },
{ InstrId::cpu_mfhi, { UnaryOpType::None, Operand::Rd, Operand::Hi } },
{ InstrId::cpu_mflo, { UnaryOpType::None, Operand::Rd, Operand::Lo } },
{ InstrId::cpu_mtc1, { UnaryOpType::None, Operand::FsU32L, Operand::Rt } },
{ InstrId::cpu_mfc1, { UnaryOpType::ToInt32, Operand::Rt, Operand::FsU32L } },
};
const std::unordered_map<InstrId, BinaryOp> binary_ops {
@ -201,6 +218,8 @@ const std::unordered_map<InstrId, BinaryOp> binary_ops {
{ InstrId::cpu_ldr, { BinaryOpType::LDR, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
{ InstrId::cpu_lwl, { BinaryOpType::LWL, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
{ InstrId::cpu_lwr, { BinaryOpType::LWR, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
{ InstrId::cpu_lwc1, { BinaryOpType::LW, Operand::FtU32L, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
{ InstrId::cpu_ldc1, { BinaryOpType::LD, Operand::FtU64, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
};
const std::unordered_map<InstrId, ConditionalBranchOp> conditional_branch_ops {
@ -321,6 +340,27 @@ std::string gpr_to_string(int gpr_index) {
return fmt::format("ctx->r{}", gpr_index);
}
std::string fpr_to_string(int fpr_index) {
return fmt::format("ctx->f{}.fl", fpr_index);
}
std::string fpr_double_to_string(int fpr_index) {
return fmt::format("ctx->f{}.d", fpr_index);
}
std::string fpr_u32l_to_string(int fpr_index) {
if (fpr_index & 1) {
return fmt::format("ctx->f_odd[({} - 1) * 2]", fpr_index);
}
else {
return fmt::format("ctx->f{}.u32l", fpr_index);
}
}
std::string fpr_u64_to_string(int fpr_index) {
return fmt::format("ctx->f{}.u64", fpr_index);
}
std::string unsigned_reloc(const InstructionContext& context) {
switch (context.reloc_type) {
case RecompPort::RelocType::R_MIPS_HI16:
@ -348,14 +388,50 @@ void CGenerator::get_operand_string(Operand operand, UnaryOpType operation, cons
operand_string = gpr_to_string(context.rt);
break;
case Operand::Fd:
assert(false);
operand_string = fpr_to_string(context.fd);
break;
case Operand::Fs:
assert(false);
operand_string = fpr_to_string(context.fs);
break;
case Operand::Ft:
operand_string = fpr_to_string(context.ft);
break;
case Operand::FdDouble:
operand_string = fpr_double_to_string(context.fd);
break;
case Operand::FsDouble:
operand_string = fpr_double_to_string(context.fs);
break;
case Operand::FtDouble:
operand_string = fpr_double_to_string(context.ft);
break;
case Operand::FdU32L:
operand_string = fpr_u32l_to_string(context.fd);
break;
case Operand::FsU32L:
operand_string = fpr_u32l_to_string(context.fs);
break;
case Operand::FtU32L:
operand_string = fpr_u32l_to_string(context.ft);
break;
case Operand::FdU32H:
assert(false);
break;
case Operand::FsU32H:
assert(false);
break;
case Operand::FtU32H:
assert(false);
break;
case Operand::FdU64:
operand_string = fpr_u64_to_string(context.fd);
break;
case Operand::FsU64:
operand_string = fpr_u64_to_string(context.fs);
break;
case Operand::FtU64:
operand_string = fpr_u64_to_string(context.ft);
break;
case Operand::ImmU16:
if (context.reloc_type != RecompPort::RelocType::R_MIPS_NONE) {
operand_string = unsigned_reloc(context);
@ -499,6 +575,11 @@ void CGenerator::process_binary_op(std::ostream& output_file, const BinaryOp& op
get_operand_string(op.output, UnaryOpType::None, ctx, output);
get_binary_expr_string(op.type, op.operands, ctx, output, expression);
// TODO remove this after the refactor is done, temporary hack to match the old recompiler output.
if (op.type == BinaryOpType::LD && op.output == Operand::FtU64) {
fmt::print(output_file, "CHECK_FR(ctx, {});\n ", ctx.ft);
}
fmt::print(output_file, "{} = {};\n", output, expression);
}
@ -1044,25 +1125,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
break;
// Cop1 loads/stores
case InstrId::cpu_mtc1:
if ((fs & 1) == 0) {
// even fpr
print_line("ctx->f{}.u32l = {}{}", fs, ctx_gpr_prefix(rt), rt);
}
else {
// odd fpr
print_line("ctx->f_odd[({} - 1) * 2] = {}{}", fs, ctx_gpr_prefix(rt), rt);
}
break;
case InstrId::cpu_mfc1:
if ((fs & 1) == 0) {
// even fpr
print_line("{}{} = (int32_t)ctx->f{}.u32l", ctx_gpr_prefix(rt), rt, fs);
} else {
// odd fpr
print_line("{}{} = (int32_t)ctx->f_odd[({} - 1) * 2]", ctx_gpr_prefix(rt), rt, fs);
}
break;
//case InstrId::cpu_dmfc1:
// if ((fs & 1) == 0) {
// // even fpr
@ -1072,19 +1134,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
// return false;
// }
// break;
case InstrId::cpu_lwc1:
if ((ft & 1) == 0) {
// even fpr
print_line("ctx->f{}.u32l = MEM_W({}, {}{})", ft, signed_imm_string, ctx_gpr_prefix(base), base);
} else {
// odd fpr
print_line("ctx->f_odd[({} - 1) * 2] = MEM_W({}, {}{})", ft, signed_imm_string, ctx_gpr_prefix(base), base);
}
break;
case InstrId::cpu_ldc1:
print_line("CHECK_FR(ctx, {})", ft);
print_line("ctx->f{}.u64 = LD({}, {}{})", ft, signed_imm_string, ctx_gpr_prefix(base), base);
break;
case InstrId::cpu_swc1:
if ((ft & 1) == 0) {
// even fpr