N64Recomp/include/operations.h

200 lines
4.6 KiB
C++

#ifndef __OPERATIONS_H__
#define __OPERATIONS_H__
#include <unordered_map>
#include "rabbitizer.hpp"
namespace RecompPort {
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<InstrId, UnaryOp> unary_ops;
extern const std::unordered_map<InstrId, BinaryOp> binary_ops;
extern const std::unordered_map<InstrId, ConditionalBranchOp> conditional_branch_ops;
extern const std::unordered_map<InstrId, StoreOp> store_ops;
}
#endif