Created Generator interface, separated operation types and tables and C generation code into new files

This commit is contained in:
Mr-Wiseguy 2024-06-12 00:05:22 -04:00
parent c4f85867f3
commit d6be2d7a83
6 changed files with 924 additions and 873 deletions

55
include/generator.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef __GENERATOR_H__
#define __GENERATOR_H__
#include "recomp_port.h"
#include "operations.h"
namespace RecompPort {
struct InstructionContext {
int rd;
int rs;
int rt;
int sa;
int fd;
int fs;
int ft;
int cop1_cs;
uint16_t imm16;
RelocType reloc_type;
uint32_t reloc_section_index;
uint32_t reloc_target_section_offset;
};
class Generator {
public:
virtual void process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const = 0;
virtual void process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const = 0;
virtual void process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const = 0;
virtual void emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const = 0;
virtual void emit_branch_close(std::ostream& output_file) const = 0;
virtual void emit_check_fr(std::ostream& output_file, int fpr) const = 0;
virtual void emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const = 0;
};
class CGenerator final : Generator {
public:
CGenerator() = default;
void process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const final;
void process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const final;
void process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const final;
void emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const final;
void emit_branch_close(std::ostream& output_file) const final;
void emit_check_fr(std::ostream& output_file, int fpr) const final;
void emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const final;
private:
void get_operand_string(Operand operand, UnaryOpType operation, const InstructionContext& context, std::string& operand_string) const;
void get_binary_expr_string(BinaryOpType type, const BinaryOperands& operands, const InstructionContext& ctx, const std::string& output, std::string& expr_string) const;
void get_notation(BinaryOpType op_type, std::string& func_string, std::string& infix_string) const;
};
}
#endif

200
include/operations.h Normal file
View file

@ -0,0 +1,200 @@
#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