mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-14 08:12:19 +00:00
Add operands for other uses of float registers
This commit is contained in:
parent
c3de49c944
commit
d91f1cf3a8
1 changed files with 94 additions and 45 deletions
|
@ -84,6 +84,21 @@ enum class Operand {
|
||||||
Fd, // FPR
|
Fd, // FPR
|
||||||
Fs, // FPR
|
Fs, // FPR
|
||||||
Ft, // 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
|
ImmU16, // 16-bit immediate, unsigned
|
||||||
ImmS16, // 16-bit immediate, signed
|
ImmS16, // 16-bit immediate, signed
|
||||||
Sa, // Shift amount
|
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_mtlo, { UnaryOpType::None, Operand::Lo, Operand::Rs } },
|
||||||
{ InstrId::cpu_mfhi, { UnaryOpType::None, Operand::Rd, Operand::Hi } },
|
{ InstrId::cpu_mfhi, { UnaryOpType::None, Operand::Rd, Operand::Hi } },
|
||||||
{ InstrId::cpu_mflo, { UnaryOpType::None, Operand::Rd, Operand::Lo } },
|
{ 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 {
|
const std::unordered_map<InstrId, BinaryOp> binary_ops {
|
||||||
|
@ -190,17 +207,19 @@ const std::unordered_map<InstrId, BinaryOp> binary_ops {
|
||||||
{ InstrId::cpu_slti, { BinaryOpType::Less, Operand::Rt, {{ UnaryOpType::ToS64, UnaryOpType::None }, { Operand::Rs, Operand::ImmS16 }}} },
|
{ InstrId::cpu_slti, { BinaryOpType::Less, Operand::Rt, {{ UnaryOpType::ToS64, UnaryOpType::None }, { Operand::Rs, Operand::ImmS16 }}} },
|
||||||
{ InstrId::cpu_sltiu, { BinaryOpType::Less, Operand::Rt, {{ UnaryOpType::ToU64, UnaryOpType::None }, { Operand::Rs, Operand::ImmS16 }}} },
|
{ InstrId::cpu_sltiu, { BinaryOpType::Less, Operand::Rt, {{ UnaryOpType::ToU64, UnaryOpType::None }, { Operand::Rs, Operand::ImmS16 }}} },
|
||||||
// Loads
|
// Loads
|
||||||
{ InstrId::cpu_ld, { BinaryOpType::LD, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_ld, { BinaryOpType::LD, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lw, { BinaryOpType::LW, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lw, { BinaryOpType::LW, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lwu, { BinaryOpType::LWU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lwu, { BinaryOpType::LWU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lh, { BinaryOpType::LH, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lh, { BinaryOpType::LH, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lhu, { BinaryOpType::LHU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lhu, { BinaryOpType::LHU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lb, { BinaryOpType::LB, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lb, { BinaryOpType::LB, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_lbu, { BinaryOpType::LBU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_lbu, { BinaryOpType::LBU, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_ldl, { BinaryOpType::LDL, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ InstrId::cpu_ldl, { BinaryOpType::LDL, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
||||||
{ InstrId::cpu_ldr, { BinaryOpType::LDR, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::ImmS16, Operand::Base }}} },
|
{ 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_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_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 {
|
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);
|
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) {
|
std::string unsigned_reloc(const InstructionContext& context) {
|
||||||
switch (context.reloc_type) {
|
switch (context.reloc_type) {
|
||||||
case RecompPort::RelocType::R_MIPS_HI16:
|
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);
|
operand_string = gpr_to_string(context.rt);
|
||||||
break;
|
break;
|
||||||
case Operand::Fd:
|
case Operand::Fd:
|
||||||
assert(false);
|
operand_string = fpr_to_string(context.fd);
|
||||||
break;
|
break;
|
||||||
case Operand::Fs:
|
case Operand::Fs:
|
||||||
assert(false);
|
operand_string = fpr_to_string(context.fs);
|
||||||
break;
|
break;
|
||||||
case Operand::Ft:
|
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);
|
assert(false);
|
||||||
break;
|
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:
|
case Operand::ImmU16:
|
||||||
if (context.reloc_type != RecompPort::RelocType::R_MIPS_NONE) {
|
if (context.reloc_type != RecompPort::RelocType::R_MIPS_NONE) {
|
||||||
operand_string = unsigned_reloc(context);
|
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_operand_string(op.output, UnaryOpType::None, ctx, output);
|
||||||
get_binary_expr_string(op.type, op.operands, ctx, output, expression);
|
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);
|
fmt::print(output_file, "{} = {};\n", output, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,25 +1125,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cop1 loads/stores
|
// 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:
|
//case InstrId::cpu_dmfc1:
|
||||||
// if ((fs & 1) == 0) {
|
// if ((fs & 1) == 0) {
|
||||||
// // even fpr
|
// // even fpr
|
||||||
|
@ -1072,19 +1134,6 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
// break;
|
// 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:
|
case InstrId::cpu_swc1:
|
||||||
if ((ft & 1) == 0) {
|
if ((ft & 1) == 0) {
|
||||||
// even fpr
|
// even fpr
|
||||||
|
|
Loading…
Add table
Reference in a new issue