mirror of
https://github.com/Mr-Wiseguy/N64Recomp.git
synced 2025-12-19 02:20:54 +00:00
Compare commits
6 Commits
mod-tool-r
...
fix-jump-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
950f9f5e15 | ||
|
|
6860826da3 | ||
|
|
7b8b3c1920 | ||
|
|
6e7a5bdb2f | ||
|
|
e76668356b | ||
|
|
3531bc0317 |
@@ -238,15 +238,27 @@ constexpr int get_fpr_double_context_offset(int fpr_index) {
|
||||
return offsetof(recomp_context, f0.d) + sizeof(recomp_context::f0) * fpr_index;
|
||||
}
|
||||
|
||||
constexpr int get_fpr_u32l_context_offset(int fpr_index) {
|
||||
constexpr bool is_fpr_u32l(N64Recomp::Operand operand) {
|
||||
return
|
||||
operand == N64Recomp::Operand::FdU32L ||
|
||||
operand == N64Recomp::Operand::FsU32L ||
|
||||
operand == N64Recomp::Operand::FtU32L;
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr void get_fpr_u32l_context_offset(int fpr_index, sljit_compiler* compiler, int odd_float_address_register, sljit_sw& out, sljit_sw& outw) {
|
||||
if (fpr_index & 1) {
|
||||
// TODO implement odd floats.
|
||||
assert(false);
|
||||
return -1;
|
||||
// return fmt::format("ctx->f_odd[({} - 1) * 2]", fpr_index);
|
||||
assert(compiler != nullptr);
|
||||
// Load ctx->f_odd into the address register.
|
||||
sljit_emit_op1(compiler, SLJIT_MOV_P, odd_float_address_register, 0, SLJIT_MEM1(Registers::ctx), offsetof(recomp_context, f_odd));
|
||||
// sljit_emit_op0(compiler, SLJIT_BREAKPOINT);
|
||||
out = SLJIT_MEM1(odd_float_address_register);
|
||||
// Set a memory offset of ((fpr_index - 1) * 2) * sizeof(*f_odd).
|
||||
outw = ((fpr_index - 1) * 2) * sizeof(*recomp_context::f_odd);
|
||||
}
|
||||
else {
|
||||
return offsetof(recomp_context, f0.u32l) + sizeof(recomp_context::f0) * fpr_index;
|
||||
out = SLJIT_MEM1(Registers::ctx);
|
||||
outw = offsetof(recomp_context, f0.u32l) + sizeof(recomp_context::f0) * fpr_index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +277,10 @@ void get_gpr_values(int gpr, sljit_sw& out, sljit_sw& outw) {
|
||||
}
|
||||
}
|
||||
|
||||
bool get_operand_values(N64Recomp::Operand operand, const N64Recomp::InstructionContext& context, sljit_sw& out, sljit_sw& outw) {
|
||||
bool get_operand_values(N64Recomp::Operand operand, const N64Recomp::InstructionContext& context, sljit_sw& out, sljit_sw& outw,
|
||||
sljit_compiler* compiler, int odd_float_address_register
|
||||
)
|
||||
{
|
||||
using namespace N64Recomp;
|
||||
|
||||
switch (operand) {
|
||||
@@ -303,16 +318,13 @@ bool get_operand_values(N64Recomp::Operand operand, const N64Recomp::Instruction
|
||||
outw = get_fpr_double_context_offset(context.ft);
|
||||
break;
|
||||
case Operand::FdU32L:
|
||||
out = SLJIT_MEM1(Registers::ctx);
|
||||
outw = get_fpr_u32l_context_offset(context.fd);
|
||||
get_fpr_u32l_context_offset(context.fd, compiler, odd_float_address_register, out, outw);
|
||||
break;
|
||||
case Operand::FsU32L:
|
||||
out = SLJIT_MEM1(Registers::ctx);
|
||||
outw = get_fpr_u32l_context_offset(context.fs);
|
||||
get_fpr_u32l_context_offset(context.fs, compiler, odd_float_address_register, out, outw);
|
||||
break;
|
||||
case Operand::FtU32L:
|
||||
out = SLJIT_MEM1(Registers::ctx);
|
||||
outw = get_fpr_u32l_context_offset(context.ft);
|
||||
get_fpr_u32l_context_offset(context.ft, compiler, odd_float_address_register, out, outw);
|
||||
break;
|
||||
case Operand::FdU32H:
|
||||
assert(false);
|
||||
@@ -389,16 +401,30 @@ void N64Recomp::LiveGenerator::process_binary_op(const BinaryOp& op, const Instr
|
||||
if (outputs_to_zero(op.output, ctx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Float u32l input operands are not allowed in a binary operation.
|
||||
if (is_fpr_u32l(op.operands.operands[0]) || is_fpr_u32l(op.operands.operands[1])) {
|
||||
assert(false);
|
||||
errored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// A float u32l output operand is only allowed for lwc1, which has an op type of LW.
|
||||
if (is_fpr_u32l(op.output) && op.type != BinaryOpType::LW) {
|
||||
assert(false);
|
||||
errored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
sljit_sw dst;
|
||||
sljit_sw dstw;
|
||||
sljit_sw src1;
|
||||
sljit_sw src1w;
|
||||
sljit_sw src2;
|
||||
sljit_sw src2w;
|
||||
bool output_good = get_operand_values(op.output, ctx, dst, dstw);
|
||||
bool input0_good = get_operand_values(op.operands.operands[0], ctx, src1, src1w);
|
||||
bool input1_good = get_operand_values(op.operands.operands[1], ctx, src2, src2w);
|
||||
bool output_good = get_operand_values(op.output, ctx, dst, dstw, compiler, Registers::arithmetic_temp2);
|
||||
bool input0_good = get_operand_values(op.operands.operands[0], ctx, src1, src1w, nullptr, 0);
|
||||
bool input1_good = get_operand_values(op.operands.operands[1], ctx, src2, src2w, nullptr, 0);
|
||||
|
||||
if (!output_good || !input0_good || !input1_good) {
|
||||
assert(false);
|
||||
@@ -748,6 +774,10 @@ void N64Recomp::LiveGenerator::process_binary_op(const BinaryOp& op, const Instr
|
||||
case BinaryOpType::LessEqDouble:
|
||||
do_float_compare_op(SLJIT_F_LESS_EQUAL, SLJIT_SET_F_LESS_EQUAL, true);
|
||||
break;
|
||||
case BinaryOpType::False:
|
||||
// Load 0 into condition destination
|
||||
sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_IMM, 0);
|
||||
break;
|
||||
|
||||
// Loads
|
||||
case BinaryOpType::LD:
|
||||
@@ -866,12 +896,19 @@ void N64Recomp::LiveGenerator::process_unary_op(const UnaryOp& op, const Instruc
|
||||
return;
|
||||
}
|
||||
|
||||
// A unary op may have a float u32l as the source or destination, but not both.
|
||||
if (is_fpr_u32l(op.input) && is_fpr_u32l(op.output)) {
|
||||
assert(false);
|
||||
errored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
sljit_sw dst;
|
||||
sljit_sw dstw;
|
||||
sljit_sw src;
|
||||
sljit_sw srcw;
|
||||
bool output_good = get_operand_values(op.output, ctx, dst, dstw);
|
||||
bool input_good = get_operand_values(op.input, ctx, src, srcw);
|
||||
bool output_good = get_operand_values(op.output, ctx, dst, dstw, compiler, Registers::arithmetic_temp3);
|
||||
bool input_good = get_operand_values(op.input, ctx, src, srcw, compiler, Registers::arithmetic_temp3);
|
||||
|
||||
if (!output_good || !input_good) {
|
||||
assert(false);
|
||||
@@ -1089,7 +1126,13 @@ void N64Recomp::LiveGenerator::process_unary_op(const UnaryOp& op, const Instruc
|
||||
emit_l_from_d_func(do_floor_l_d);
|
||||
break;
|
||||
case UnaryOpType::None:
|
||||
jit_op = SLJIT_MOV;
|
||||
// Only write 32 bits to the output is a fpr u32l operand.
|
||||
if (is_fpr_u32l(op.output)) {
|
||||
jit_op = SLJIT_MOV32;
|
||||
}
|
||||
else {
|
||||
jit_op = SLJIT_MOV;
|
||||
}
|
||||
break;
|
||||
case UnaryOpType::ToS32:
|
||||
case UnaryOpType::ToInt32:
|
||||
@@ -1128,7 +1171,7 @@ void N64Recomp::LiveGenerator::process_store_op(const StoreOp& op, const Instruc
|
||||
sljit_sw srcw;
|
||||
sljit_sw imm = (sljit_sw)(int16_t)ctx.imm16;
|
||||
|
||||
get_operand_values(op.value_input, ctx, src, srcw);
|
||||
get_operand_values(op.value_input, ctx, src, srcw, compiler, Registers::arithmetic_temp2);
|
||||
|
||||
// Only LO16 relocs are valid on stores.
|
||||
if (ctx.reloc_type != RelocType::R_MIPS_NONE && ctx.reloc_type != RelocType::R_MIPS_LO16) {
|
||||
@@ -1456,6 +1499,13 @@ void N64Recomp::LiveGenerator::emit_branch_condition(const ConditionalBranchOp&
|
||||
return;
|
||||
}
|
||||
|
||||
// Branch conditions do not allow float u32l operands.
|
||||
if (is_fpr_u32l(op.operands.operands[0]) || is_fpr_u32l(op.operands.operands[1])) {
|
||||
assert(false);
|
||||
errored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
sljit_s32 condition_type;
|
||||
bool cmp_signed = op.operands.operand_operations[0] == UnaryOpType::ToS64;
|
||||
// Comparisons need to be inverted to account for the fact that the generator is expected to generate a code block that only runs if
|
||||
@@ -1509,8 +1559,8 @@ void N64Recomp::LiveGenerator::emit_branch_condition(const ConditionalBranchOp&
|
||||
sljit_sw src2;
|
||||
sljit_sw src2w;
|
||||
|
||||
get_operand_values(op.operands.operands[0], ctx, src1, src1w);
|
||||
get_operand_values(op.operands.operands[1], ctx, src2, src2w);
|
||||
get_operand_values(op.operands.operands[0], ctx, src1, src1w, nullptr, 0);
|
||||
get_operand_values(op.operands.operands[1], ctx, src2, src2w, nullptr, 0);
|
||||
|
||||
// Relocations aren't valid on conditional branches.
|
||||
if(ctx.reloc_type != RelocType::R_MIPS_NONE) {
|
||||
|
||||
@@ -35,6 +35,8 @@ struct ModManifest {
|
||||
std::vector<toml::table> config_options;
|
||||
std::vector<std::string> dependencies;
|
||||
std::vector<std::string> full_dependency_strings;
|
||||
std::vector<std::string> optional_dependencies;
|
||||
std::vector<std::string> full_optional_dependency_strings;
|
||||
};
|
||||
|
||||
struct ModInputs {
|
||||
@@ -323,6 +325,31 @@ ModManifest parse_mod_config_manifest(const std::filesystem::path& basedir, cons
|
||||
});
|
||||
}
|
||||
|
||||
// Optional dependency list (optional)
|
||||
const toml::array& optional_dependency_array = read_toml_array(manifest_table, "optional_dependencies", false);
|
||||
if (!optional_dependency_array.empty()) {
|
||||
// Reserve room for all the dependencies.
|
||||
ret.dependencies.reserve(optional_dependency_array.size());
|
||||
optional_dependency_array.for_each([&ret](const auto& el) {
|
||||
if constexpr (toml::is_string<decltype(el)>) {
|
||||
size_t dependency_id_length;
|
||||
bool dependency_version_has_label;
|
||||
if (!validate_dependency_string(el.template ref<std::string>(), dependency_id_length, dependency_version_has_label)) {
|
||||
throw toml::parse_error("Invalid optional dependency entry", el.source());
|
||||
}
|
||||
if (dependency_version_has_label) {
|
||||
throw toml::parse_error("Dependency versions may not have labels", el.source());
|
||||
}
|
||||
std::string dependency_id = el.template ref<std::string>().substr(0, dependency_id_length);
|
||||
ret.optional_dependencies.emplace_back(dependency_id);
|
||||
ret.full_optional_dependency_strings.emplace_back(el.template ref<std::string>());
|
||||
}
|
||||
else {
|
||||
throw toml::parse_error("Invalid type for optional dependency entry", el.source());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Config schema (optional)
|
||||
const toml::array& config_options_array = read_toml_array(manifest_table, "config_options", false);
|
||||
if (!config_options_array.empty()) {
|
||||
@@ -507,6 +534,10 @@ void write_manifest(const std::filesystem::path& path, const ModManifest& manife
|
||||
output_data.emplace("dependencies", string_vector_to_toml(manifest.full_dependency_strings));
|
||||
}
|
||||
|
||||
if (!manifest.full_optional_dependency_strings.empty()) {
|
||||
output_data.emplace("optional_dependencies", string_vector_to_toml(manifest.full_optional_dependency_strings));
|
||||
}
|
||||
|
||||
if (!manifest.config_options.empty()) {
|
||||
toml::array options_array{};
|
||||
for (const auto& option : manifest.config_options) {
|
||||
@@ -974,11 +1005,11 @@ bool create_mod_zip(const std::filesystem::path& output_dir, const ModConfig& co
|
||||
#ifdef _WIN32
|
||||
std::filesystem::path temp_zip_path = output_path;
|
||||
temp_zip_path.replace_extension(".zip");
|
||||
std::string command_string = fmt::format("powershell -command Compress-Archive -Force -CompressionLevel Optimal -DestinationPath \"{}\" -Path \"{}\",\"{}\",\"{}\"",
|
||||
std::string command_string = fmt::format("powershell -command Compress-Archive -Force -CompressionLevel Optimal -DestinationPath '{}' -Path '{}','{}','{}'",
|
||||
temp_zip_path.string(), (output_dir / symbol_filename).string(), (output_dir / binary_filename).string(), (output_dir / manifest_filename).string());
|
||||
|
||||
for (const auto& cur_file : config.inputs.additional_files) {
|
||||
command_string += fmt::format(",\"{}\"", cur_file.string());
|
||||
command_string += fmt::format(",'{}'", cur_file.string());
|
||||
}
|
||||
|
||||
STARTUPINFOA si{};
|
||||
@@ -1138,8 +1169,9 @@ int main(int argc, const char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the dependencies from the config into the context.
|
||||
// Copy the dependencies and optional dependencies from the config into the context.
|
||||
context.add_dependencies(config.manifest.dependencies);
|
||||
context.add_dependencies(config.manifest.optional_dependencies);
|
||||
|
||||
N64Recomp::ElfParsingConfig elf_config {
|
||||
.bss_section_suffix = {},
|
||||
|
||||
@@ -233,6 +233,8 @@ namespace N64Recomp {
|
||||
//// Mod dependencies and their symbols
|
||||
|
||||
//// Imported values
|
||||
// Dependency names.
|
||||
std::vector<std::string> dependencies;
|
||||
// Mapping of dependency name to dependency index.
|
||||
std::unordered_map<std::string, size_t> dependencies_by_name;
|
||||
// List of symbols imported from dependencies.
|
||||
@@ -276,6 +278,7 @@ namespace N64Recomp {
|
||||
|
||||
size_t dependency_index = dependencies_by_name.size();
|
||||
|
||||
dependencies.emplace_back(id);
|
||||
dependencies_by_name.emplace(id, dependency_index);
|
||||
dependency_events_by_name.resize(dependencies_by_name.size());
|
||||
dependency_imports_by_name.resize(dependencies_by_name.size());
|
||||
@@ -295,6 +298,7 @@ namespace N64Recomp {
|
||||
|
||||
for (const std::string& dep : new_dependencies) {
|
||||
size_t dependency_index = dependencies_by_name.size();
|
||||
dependencies.emplace_back(dep);
|
||||
dependencies_by_name.emplace(dep, dependency_index);
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +321,13 @@ bool N64Recomp::analyze_function(const N64Recomp::Context& context, const N64Rec
|
||||
while (vram < end_address) {
|
||||
// Retrieve the current entry of the jump table
|
||||
// TODO same as above
|
||||
|
||||
// Stop scanning if the end of the ROM is reached.
|
||||
uint32_t rom_addr = vram + func.rom - func.vram;
|
||||
if (rom_addr >= context.rom.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t jtbl_word = byteswap(*reinterpret_cast<const uint32_t*>(&context.rom[rom_addr]));
|
||||
|
||||
if (cur_jtbl.got_offset.has_value() && got_ram_addr.has_value()) {
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace N64Recomp {
|
||||
{ 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 } },
|
||||
{ InstrId::cpu_dmtc1, { UnaryOpType::None, Operand::FsU64, Operand::Rt } },
|
||||
{ InstrId::cpu_dmfc1, { UnaryOpType::None, Operand::Rt, Operand::FsU64 } },
|
||||
// Float operations
|
||||
{ InstrId::cpu_mov_s, { UnaryOpType::None, Operand::Fd, Operand::Fs, true } },
|
||||
{ InstrId::cpu_mov_d, { UnaryOpType::None, Operand::FdDouble, Operand::FsDouble, true } },
|
||||
@@ -98,34 +100,46 @@ namespace N64Recomp {
|
||||
{ InstrId::cpu_mul_d, { BinaryOpType::MulDouble, Operand::FdDouble, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true, true } },
|
||||
{ InstrId::cpu_div_s, { BinaryOpType::DivFloat, Operand::Fd, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true, true } },
|
||||
{ InstrId::cpu_div_d, { BinaryOpType::DivDouble, Operand::FdDouble, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true, true } },
|
||||
// Float comparisons TODO remaining operations and investigate ordered/unordered and default values
|
||||
{ InstrId::cpu_c_lt_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_nge_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_olt_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ult_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_lt_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_nge_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_olt_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ult_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
|
||||
{ InstrId::cpu_c_le_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ngt_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ole_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ule_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_le_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ngt_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ole_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ule_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
|
||||
{ InstrId::cpu_c_eq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ueq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ngl_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_seq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
// Float comparisons TODO investigate ordered/unordered and default values
|
||||
// Single Ordered
|
||||
{ InstrId::cpu_c_f_s, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_eq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_olt_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ole_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_sf_s, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_seq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_lt_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_le_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
// Single Unordered
|
||||
{ InstrId::cpu_c_un_s, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ueq_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ult_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ule_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ngle_s, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ngl_s, { BinaryOpType::EqualFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_nge_s, { BinaryOpType::LessFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
{ InstrId::cpu_c_ngt_s, { BinaryOpType::LessEqFloat, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Fs, Operand::Ft }}, true } },
|
||||
// Double Ordered
|
||||
{ InstrId::cpu_c_f_d, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_eq_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ueq_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ngl_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_olt_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ole_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
/* TODO rename to c_sf_d when fixed in rabbitizer */
|
||||
{ InstrId::cpu_c_df_d, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
/* TODO rename to c_seq_d when fixed in rabbitizer */
|
||||
{ InstrId::cpu_c_deq_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_lt_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_le_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
// Double Unordered
|
||||
{ InstrId::cpu_c_un_d, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ueq_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ult_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ule_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ngle_d, { BinaryOpType::False, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ngl_d, { BinaryOpType::EqualDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_nge_d, { BinaryOpType::LessDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
{ InstrId::cpu_c_ngt_d, { BinaryOpType::LessEqDouble, Operand::Cop1cs, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::FsDouble, Operand::FtDouble }}, true } },
|
||||
|
||||
// Loads
|
||||
{ InstrId::cpu_ld, { BinaryOpType::LD, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Base, Operand::ImmS16 }}} },
|
||||
{ InstrId::cpu_lw, { BinaryOpType::LW, Operand::Rt, {{ UnaryOpType::None, UnaryOpType::None }, { Operand::Base, Operand::ImmS16 }}} },
|
||||
|
||||
Reference in New Issue
Block a user