#ifndef __OPERATIONS_H__ #define __OPERATIONS_H__ #include #include "rabbitizer.hpp" namespace N64Recomp { using InstrId = rabbitizer::InstrId::UniqueId; using Cop0Reg = rabbitizer::Registers::Cpu::Cop0; enum class StoreOpType { SD, SDL, SDR, SW, SWL, SWR, SH, SB, SDC1, SWC1 }; enum class UnaryOpType { None, ToS32, ToU32, ToS64, ToU64, NegateS32, NegateS64, Lui, Mask5, // Mask to 5 bits Mask6, // Mask to 5 bits ToInt32, // Functionally equivalent to ToS32, only exists for parity with old codegen Negate, AbsFloat, AbsDouble, SqrtFloat, SqrtDouble, ConvertSFromW, ConvertWFromS, ConvertDFromW, ConvertWFromD, ConvertDFromS, ConvertSFromD, ConvertDFromL, ConvertLFromD, ConvertSFromL, ConvertLFromS, TruncateWFromS, TruncateWFromD, RoundWFromS, RoundWFromD, CeilWFromS, CeilWFromD, FloorWFromS, FloorWFromD }; enum class BinaryOpType { // Addition/subtraction Add32, Sub32, Add64, Sub64, // Float arithmetic AddFloat, AddDouble, SubFloat, SubDouble, MulFloat, MulDouble, DivFloat, DivDouble, // Bitwise And64, Or64, Nor64, Xor64, Sll32, Sll64, Srl32, Srl64, Sra32, Sra64, // Comparisons Equal, NotEqual, Less, LessEq, Greater, GreaterEq, // Loads LD, LW, LWU, LH, LHU, LB, LBU, LDL, LDR, LWL, LWR, // Fixed result True, False, COUNT, }; enum class Operand { Rd, // GPR Rs, // GPR Rt, // GPR 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 Sa32, // Shift amount plus 32 Cop1cs, // Coprocessor 1 Condition Signal Hi, Lo, Zero, Base = Rs, // Alias for Rs for loads }; struct StoreOp { StoreOpType type; Operand value_input; }; struct UnaryOp { UnaryOpType operation; Operand output; Operand input; // Whether the FR bit needs to be checked for odd float registers for this instruction. bool check_fr = false; // Whether the input need to be checked for being NaN. bool check_nan = false; }; struct BinaryOperands { // Operation to apply to each operand before applying the binary operation to them. UnaryOpType operand_operations[2]; // The source of the input operands. Operand operands[2]; }; struct BinaryOp { // The type of binary operation this represents. BinaryOpType type; // The output operand. Operand output; // The input operands. BinaryOperands operands; // Whether the FR bit needs to be checked for odd float registers for this instruction. bool check_fr = false; // Whether the inputs need to be checked for being NaN. bool check_nan = false; }; struct ConditionalBranchOp { // The type of binary operation to use for this compare BinaryOpType comparison; // The input operands. BinaryOperands operands; // Whether this jump should link for returns. bool link; // Whether this jump has "likely" behavior (doesn't execute the delay slot if skipped). bool likely; }; extern const std::unordered_map unary_ops; extern const std::unordered_map binary_ops; extern const std::unordered_map conditional_branch_ops; extern const std::unordered_map store_ops; } #endif