mirror of
https://github.com/Decompollaborate/rabbitizer.git
synced 2025-01-28 00:35:16 +00:00
C++ bindings (#9)
* start making c++ bindings * Add sanity checks * add descriptor methods * setup making c++ library * cpp test * format (not tidy because it breaks everything and the result looks dumb) * Fixes * add missing alias * move stuff to their own files * InstructionRsp bindings * r5900 bindings * almost there * binding for analysis stuff * setters
This commit is contained in:
parent
874863ab77
commit
acee144578
58
Makefile
58
Makefile
@ -3,13 +3,19 @@ DEBUG ?= 0
|
||||
WERROR ?= 0
|
||||
ASAN ?= 0
|
||||
EXPERIMENTAL ?= 0
|
||||
SANITY_CHECKS ?= 1
|
||||
|
||||
CC := clang
|
||||
CXX := clang++
|
||||
AR := ar
|
||||
IINC := -I include
|
||||
IINC_XX := -I include -I cplusplus/include
|
||||
CSTD := -std=c11
|
||||
CXXSTD := -std=c++17
|
||||
CFLAGS := -fPIC
|
||||
CXXFLAGS := -fPIC
|
||||
LDFLAGS := -Lbuild -lrabbitizer
|
||||
LDXXFLAGS := -Lbuild -lrabbitizerpp
|
||||
WARNINGS := -Wall -Wextra -Wpedantic
|
||||
# WARNINGS := -Wall -Wextra -Wpedantic -Wpadded
|
||||
WARNINGS += -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=vla -Werror=switch -Werror=implicit-fallthrough -Werror=unused-function -Werror=unused-parameter -Werror=shadow
|
||||
@ -19,10 +25,11 @@ ifeq ($(CC),gcc)
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),0)
|
||||
OPTFLAGS := -O2 -g
|
||||
OPTFLAGS := -Os -g
|
||||
else
|
||||
OPTFLAGS := -O0 -g3
|
||||
CFLAGS += -DDEVELOPMENT=1
|
||||
CXXFLAGS += -DDEVELOPMENT=1
|
||||
endif
|
||||
|
||||
ifneq ($(WERROR),0)
|
||||
@ -31,10 +38,17 @@ endif
|
||||
|
||||
ifneq ($(ASAN),0)
|
||||
CFLAGS += -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined
|
||||
CXXFLAGS += -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined
|
||||
endif
|
||||
|
||||
ifneq ($(EXPERIMENTAL),0)
|
||||
CFLAGS += -DEXPERIMENTAL
|
||||
CXXFLAGS += -DEXPERIMENTAL
|
||||
endif
|
||||
|
||||
ifneq ($(SANITY_CHECKS),0)
|
||||
CFLAGS += -DRAB_SANITY_CHECKS=1
|
||||
CXXFLAGS += -DRAB_SANITY_CHECKS=1
|
||||
endif
|
||||
|
||||
|
||||
@ -42,21 +56,41 @@ SRC_DIRS := $(shell find src -type d)
|
||||
C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
H_FILES := $(foreach dir,$(IINC),$(wildcard $(dir)/**/*.h))
|
||||
O_FILES := $(foreach f,$(C_FILES:.c=.o),build/$f)
|
||||
DEP_FILES := $(O_FILES:%.o=%.d)
|
||||
|
||||
SRCXX_DIRS := $(shell find cplusplus/src -type d)
|
||||
CXX_FILES := $(foreach dir,$(SRCXX_DIRS),$(wildcard $(dir)/*.cpp))
|
||||
HXX_FILES := $(foreach dir,$(IINC_XX),$(wildcard $(dir)/**/*.hpp))
|
||||
OXX_FILES := $(foreach f,$(CXX_FILES:.cpp=.o),build/$f)
|
||||
|
||||
DEP_FILES := $(O_FILES:%.o=%.d) $(OXX_FILES:%.o=%.d)
|
||||
|
||||
TESTS_DIRS := $(shell find tests -type d)
|
||||
|
||||
STATIC_LIB := build/librabbitizer.a
|
||||
DYNAMIC_LIB := build/librabbitizer.so
|
||||
|
||||
STATIC_LIB_XX := build/librabbitizerpp.a
|
||||
DYNAMIC_LIB_XX := build/librabbitizerpp.so
|
||||
|
||||
# create build directories
|
||||
$(shell mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir)))
|
||||
$(shell mkdir -p $(foreach dir,$(SRC_DIRS) $(SRCXX_DIRS) $(TESTS_DIRS),build/$(dir)))
|
||||
|
||||
|
||||
# Dependencies of libraries
|
||||
|
||||
$(STATIC_LIB): $(O_FILES)
|
||||
$(DYNAMIC_LIB): $(O_FILES)
|
||||
|
||||
$(STATIC_LIB_XX): $(O_FILES) $(OXX_FILES)
|
||||
$(DYNAMIC_LIB_XX): $(O_FILES) $(OXX_FILES)
|
||||
|
||||
|
||||
#### Main Targets ###
|
||||
|
||||
all: static tests
|
||||
|
||||
static: $(STATIC_LIB)
|
||||
dynamic: $(DYNAMIC_LIB)
|
||||
static: $(STATIC_LIB) $(STATIC_LIB_XX)
|
||||
dynamic: $(DYNAMIC_LIB) $(DYNAMIC_LIB_XX)
|
||||
|
||||
clean:
|
||||
$(RM) -rf build
|
||||
@ -66,11 +100,12 @@ distclean: clean
|
||||
|
||||
format:
|
||||
clang-format-11 -i -style=file $(C_FILES)
|
||||
clang-format-11 -i -style=file $(CXX_FILES)
|
||||
|
||||
tidy:
|
||||
clang-tidy-11 -p . --fix --fix-errors $(C_FILES) $(H_FILES) -- $(CSTD) $(OPTFLAGS) $(IINC) $(WARNINGS) $(CFLAGS)
|
||||
|
||||
tests: build/test.elf build/rsptest.elf build/r5900test.elf build/registersTrackerTest.elf
|
||||
tests: build/test.elf build/rsptest.elf build/r5900test.elf build/registersTrackerTest.elf build/tests/cplusplus/test.elf
|
||||
|
||||
.PHONY: all clean distclean format tidy tests
|
||||
.DEFAULT_GOAL := all
|
||||
@ -82,15 +117,22 @@ tests: build/test.elf build/rsptest.elf build/r5900test.elf build/registersTrack
|
||||
build/%.elf: %.c | $(STATIC_LIB)
|
||||
$(CC) -MMD $(CSTD) $(OPTFLAGS) $(IINC) $(WARNINGS) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
build/%.a: $(O_FILES)
|
||||
build/%.elf: %.cpp | $(STATIC_LIB_XX)
|
||||
$(CXX) -MMD $(CXXSTD) $(OPTFLAGS) $(IINC_XX) $(WARNINGS) $(CXXFLAGS) -o $@ $^ $(LDXXFLAGS)
|
||||
|
||||
build/%.a:
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
build/%.so: $(O_FILES)
|
||||
build/%.so:
|
||||
$(CC) -shared -o $@ $^
|
||||
|
||||
build/%.o: %.c
|
||||
# The -MMD flags additionaly creates a .d file with the same name as the .o file.
|
||||
$(CC) -MMD -c $(CSTD) $(OPTFLAGS) $(IINC) $(WARNINGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
build/%.o: %.cpp
|
||||
# The -MMD flags additionaly creates a .d file with the same name as the .o file.
|
||||
$(CXX) -MMD -c $(CXXSTD) $(OPTFLAGS) $(IINC_XX) $(WARNINGS) $(CXXFLAGS) -o $@ $<
|
||||
|
||||
|
||||
-include $(DEP_FILES)
|
||||
|
36
cplusplus/include/analysis/LoPairingInfo.hpp
Normal file
36
cplusplus/include/analysis/LoPairingInfo.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_LO_PAIRING_INFO_HPP
|
||||
#define RABBITIZER_LO_PAIRING_INFO_HPP
|
||||
#pragma once
|
||||
|
||||
#include "analysis/RabbitizerLoPairingInfo.h"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class LoPairingInfo {
|
||||
protected:
|
||||
RabbitizerLoPairingInfo pairingInfo;
|
||||
|
||||
public:
|
||||
LoPairingInfo();
|
||||
LoPairingInfo(const RabbitizerLoPairingInfo &pairingInfo);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the inner RabbitizerLoPairingInfo.
|
||||
* It is recommended to not mess with it unless you know what you are doing.
|
||||
*/
|
||||
RabbitizerLoPairingInfo *getCPtr();
|
||||
const RabbitizerLoPairingInfo *getCPtr() const;
|
||||
|
||||
int getInstrOffset() const;
|
||||
int64_t getValue() const;
|
||||
bool shouldProcess() const;
|
||||
bool isGpRel() const;
|
||||
bool isGpGot() const;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
49
cplusplus/include/analysis/RegistersTracker.hpp
Normal file
49
cplusplus/include/analysis/RegistersTracker.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_REGISTERS_TRACKER_HPP
|
||||
#define RABBITIZER_REGISTERS_TRACKER_HPP
|
||||
#pragma once
|
||||
|
||||
#include "analysis/RabbitizerRegistersTracker.h"
|
||||
|
||||
#include "analysis/LoPairingInfo.hpp"
|
||||
#include "instructions/InstructionBase.hpp"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class RegistersTracker {
|
||||
protected:
|
||||
RabbitizerRegistersTracker tracker;
|
||||
|
||||
public:
|
||||
RegistersTracker();
|
||||
RegistersTracker(const RegistersTracker &other);
|
||||
virtual ~RegistersTracker();
|
||||
|
||||
/**
|
||||
* Returns a pointer to the inner RabbitizerRegistersTracker.
|
||||
* It is recommended to not mess with it unless you know what you are doing.
|
||||
*/
|
||||
RabbitizerRegistersTracker *getCPtr();
|
||||
const RabbitizerRegistersTracker *getCPtr() const;
|
||||
|
||||
bool moveRegisters(const InstructionBase &instr);
|
||||
void overwriteRegisters(const InstructionBase &instr, int instrOffset);
|
||||
void unsetRegistersAfterFuncCall(const InstructionBase &instr, const InstructionBase &prevInstr);
|
||||
bool getAddressIfCanSetType(const InstructionBase &instr, int instrOffset, uint32_t *dstAddress) const;
|
||||
bool getJrInfo(const InstructionBase &instr, int *dstOffset, uint32_t *dstAddress) const;
|
||||
|
||||
void processLui(const InstructionBase &instr, int instrOffset);
|
||||
void processLui(const InstructionBase &instr, int instrOffset, const InstructionBase &prevInstr);
|
||||
void processGpLoad(const InstructionBase &instr, int instrOffset);
|
||||
bool getLuiOffsetForConstant(const InstructionBase &instr, int *dstOffset) const;
|
||||
void processConstant(const InstructionBase &instr, uint32_t value, int offset);
|
||||
LoPairingInfo preprocessLoAndGetInfo(const InstructionBase &instr, int instrOffset);
|
||||
void processLo(const InstructionBase &instr, uint32_t value, int offset);
|
||||
bool hasLoButNoHi(const InstructionBase &instr) const;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
38
cplusplus/include/instructions/InstrId.hpp
Normal file
38
cplusplus/include/instructions/InstrId.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_INSTRID_HPP
|
||||
#define RABBITIZER_INSTRID_HPP
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
namespace InstrId {
|
||||
#define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) \
|
||||
prefix##_##name,
|
||||
|
||||
#define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) \
|
||||
RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__)
|
||||
|
||||
enum class UniqueId {
|
||||
#include "instructions/instr_id/RabbitizerInstrId_cpu.inc"
|
||||
|
||||
#include "instructions/instr_id/RabbitizerInstrId_rsp.inc"
|
||||
|
||||
#include "instructions/instr_id/RabbitizerInstrId_r5900.inc"
|
||||
|
||||
ALL_MAX = RABBITIZER_DEF_INSTR_ID(r5900, , MAX, )
|
||||
};
|
||||
|
||||
#undef RABBITIZER_DEF_INSTR_ID
|
||||
#undef RABBITIZER_DEF_INSTR_ID_ALTNAME
|
||||
|
||||
|
||||
std::string getOpcodeName(UniqueId uniqueId);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
251
cplusplus/include/instructions/InstructionBase.hpp
Normal file
251
cplusplus/include/instructions/InstructionBase.hpp
Normal file
@ -0,0 +1,251 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_INSTRUCTION_BASE_HPP
|
||||
#define RABBITIZER_INSTRUCTION_BASE_HPP
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "instructions/RabbitizerInstruction.h"
|
||||
|
||||
#include "instructions/Registers.hpp"
|
||||
#include "instructions/OperandType.hpp"
|
||||
#include "instructions/InstrId.hpp"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class InstructionBase {
|
||||
protected:
|
||||
RabbitizerInstruction instr;
|
||||
|
||||
InstructionBase() = default;
|
||||
virtual ~InstructionBase() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns a pointer to the inner RabbitizerInstruction.
|
||||
* It is recommended to not mess with it unless you know what you are doing.
|
||||
*/
|
||||
RabbitizerInstruction *getCPtr();
|
||||
const RabbitizerInstruction *getCPtr() const;
|
||||
|
||||
/* getters */
|
||||
|
||||
uint8_t Get_opcode() const;
|
||||
uint8_t Get_sa() const;
|
||||
uint8_t Get_function() const;
|
||||
|
||||
Registers::Cpu::GprO32 GetO32_rs() const;
|
||||
Registers::Cpu::GprO32 GetO32_rt() const;
|
||||
Registers::Cpu::GprO32 GetO32_rd() const;
|
||||
|
||||
Registers::Cpu::GprN32 GetN32_rs() const;
|
||||
Registers::Cpu::GprN32 GetN32_rt() const;
|
||||
Registers::Cpu::GprN32 GetN32_rd() const;
|
||||
|
||||
Registers::Cpu::Cop0 Get_cop0d() const;
|
||||
|
||||
uint32_t Get_instr_index() const;
|
||||
uint16_t Get_immediate() const;
|
||||
|
||||
Registers::Cpu::Cop1O32 GetO32_fs() const;
|
||||
Registers::Cpu::Cop1O32 GetO32_ft() const;
|
||||
Registers::Cpu::Cop1O32 GetO32_fd() const;
|
||||
|
||||
Registers::Cpu::Cop1N32 GetN32_fs() const;
|
||||
Registers::Cpu::Cop1N32 GetN32_ft() const;
|
||||
Registers::Cpu::Cop1N32 GetN32_fd() const;
|
||||
|
||||
Registers::Cpu::Cop1N64 GetN64_fs() const;
|
||||
Registers::Cpu::Cop1N64 GetN64_ft() const;
|
||||
Registers::Cpu::Cop1N64 GetN64_fd() const;
|
||||
|
||||
Registers::Cpu::Cop1Control Get_cop1cs() const;
|
||||
|
||||
Registers::Cpu::Cop2 Get_cop2t() const;
|
||||
|
||||
uint8_t Get_op() const;
|
||||
|
||||
uint32_t Get_code() const;
|
||||
uint32_t Get_code_upper() const;
|
||||
uint32_t Get_code_lower() const;
|
||||
|
||||
uint32_t Get_copraw() const;
|
||||
|
||||
uint8_t Get_fmt() const;
|
||||
uint8_t Get_fc() const;
|
||||
uint8_t Get_cond() const;
|
||||
|
||||
uint8_t Get_tf() const;
|
||||
uint8_t Get_nd() const;
|
||||
uint8_t Get_bc_fmt() const;
|
||||
|
||||
uint8_t Get_stype() const;
|
||||
|
||||
/* getters */
|
||||
|
||||
|
||||
/* setters */
|
||||
|
||||
void Set_opcode(uint8_t val);
|
||||
void Set_sa(uint8_t val);
|
||||
void Set_function(uint8_t val);
|
||||
|
||||
void Set_rs(Registers::Cpu::GprO32 val);
|
||||
void Set_rt(Registers::Cpu::GprO32 val);
|
||||
void Set_rd(Registers::Cpu::GprO32 val);
|
||||
|
||||
void Set_rs(Registers::Cpu::GprN32 val);
|
||||
void Set_rt(Registers::Cpu::GprN32 val);
|
||||
void Set_rd(Registers::Cpu::GprN32 val);
|
||||
|
||||
void Set_cop0d(Registers::Cpu::Cop0 val);
|
||||
|
||||
void Set_instr_index(uint32_t val);
|
||||
void Set_immediate(uint16_t val);
|
||||
|
||||
void Set_fs(Registers::Cpu::Cop1O32 val);
|
||||
void Set_ft(Registers::Cpu::Cop1O32 val);
|
||||
void Set_fd(Registers::Cpu::Cop1O32 val);
|
||||
|
||||
void Set_fs(Registers::Cpu::Cop1N32 val);
|
||||
void Set_ft(Registers::Cpu::Cop1N32 val);
|
||||
void Set_fd(Registers::Cpu::Cop1N32 val);
|
||||
|
||||
void Set_fs(Registers::Cpu::Cop1N64 val);
|
||||
void Set_ft(Registers::Cpu::Cop1N64 val);
|
||||
void Set_fd(Registers::Cpu::Cop1N64 val);
|
||||
|
||||
void Set_cop1cs(Registers::Cpu::Cop1Control val);
|
||||
|
||||
void Set_cop2t(Registers::Cpu::Cop2 val);
|
||||
|
||||
void Set_op(uint8_t val);
|
||||
|
||||
void Set_code(uint32_t val);
|
||||
|
||||
void Set_copraw(uint32_t val);
|
||||
|
||||
void Set_fmt(uint8_t val);
|
||||
void Set_fc(uint8_t val);
|
||||
void Set_cond(uint8_t val);
|
||||
|
||||
void Set_tf(uint8_t val);
|
||||
void Set_nd(uint8_t val);
|
||||
void Set_bc_fmt(uint8_t val);
|
||||
|
||||
void Set_stype(uint8_t val);
|
||||
|
||||
/* setters */
|
||||
|
||||
|
||||
/* more getters */
|
||||
|
||||
uint32_t getRaw() const;
|
||||
|
||||
InstrId::UniqueId getUniqueId() const;
|
||||
uint32_t getVram() const;
|
||||
bool isInHandwrittenFunction() const;
|
||||
|
||||
int32_t getProcessedImmediate() const;
|
||||
uint32_t getInstrIndexAsVram() const;
|
||||
|
||||
int32_t getBranchOffset() const;
|
||||
int32_t getGenericBranchOffset(uint32_t currentVram) const;
|
||||
|
||||
|
||||
std::string getOpcodeName() const;
|
||||
|
||||
/* more getters */
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
void blankOut();
|
||||
|
||||
|
||||
/* Instruction examination */
|
||||
|
||||
bool isImplemented() const;
|
||||
bool isLikelyHandwritten() const;
|
||||
bool isNop() const;
|
||||
bool isUnconditionalBranch() const;
|
||||
bool isJrRa() const;
|
||||
bool isJrNotRa() const;
|
||||
bool hasDelaySlot() const;
|
||||
|
||||
std::string mapInstrToType() const;
|
||||
|
||||
bool sameOpcode(const InstructionBase &other) const;
|
||||
bool sameOpcodeButDifferentArguments(const InstructionBase &other) const;
|
||||
|
||||
bool hasOperand(OperandType operand) const;
|
||||
bool hasOperandAlias(OperandType operand) const;
|
||||
|
||||
uint32_t getValidBits() const;
|
||||
bool isValid() const;
|
||||
|
||||
/* Instruction examination */
|
||||
|
||||
|
||||
/* Instruction descriptor */
|
||||
|
||||
bool isUnknownType() const;
|
||||
bool isJType() const;
|
||||
bool isIType() const;
|
||||
bool isRType() const;
|
||||
bool isRegimmType() const;
|
||||
|
||||
// TODO
|
||||
// RabbitizerInstrSuffix instrSuffix() const;
|
||||
|
||||
bool isBranch() const;
|
||||
bool isBranchLikely() const;
|
||||
bool isJump() const;
|
||||
bool isTrap() const;
|
||||
|
||||
bool isFloat() const;
|
||||
bool isDouble() const;
|
||||
|
||||
bool isUnsigned() const;
|
||||
|
||||
bool modifiesRt() const;
|
||||
bool modifiesRd() const;
|
||||
|
||||
bool notEmitedByCompilers() const;
|
||||
|
||||
bool canBeHi() const;
|
||||
bool canBeLo() const;
|
||||
bool doesLink() const;
|
||||
bool doesDereference() const;
|
||||
bool doesLoad() const;
|
||||
bool doesStore() const;
|
||||
bool maybeIsMove() const;
|
||||
|
||||
bool isPseudo() const;
|
||||
|
||||
/* Instruction descriptor */
|
||||
|
||||
|
||||
/* Disassembly */
|
||||
|
||||
bool mustDisasmAsData() const;
|
||||
|
||||
std::string disassembleOperands() const;
|
||||
std::string disassembleOperands(std::string_view immOverride) const;
|
||||
|
||||
std::string disassembleInstruction(int extraLJust) const;
|
||||
std::string disassembleInstruction(int extraLJust, std::string_view immOverride) const;
|
||||
|
||||
std::string disassembleAsData(int extraLJust) const;
|
||||
|
||||
std::string disassemble(int extraLJust) const;
|
||||
std::string disassemble(int extraLJust, std::string_view immOverride) const;
|
||||
|
||||
/* Disassembly */
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
20
cplusplus/include/instructions/InstructionCpu.hpp
Normal file
20
cplusplus/include/instructions/InstructionCpu.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_INSTRUCTION_CPU_HPP
|
||||
#define RABBITIZER_INSTRUCTION_CPU_HPP
|
||||
#pragma once
|
||||
|
||||
#include "InstructionBase.hpp"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class InstructionCpu : public InstructionBase {
|
||||
public:
|
||||
InstructionCpu(uint32_t word, uint32_t vram);
|
||||
virtual ~InstructionCpu();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
41
cplusplus/include/instructions/InstructionR5900.hpp
Normal file
41
cplusplus/include/instructions/InstructionR5900.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_INSTRUCTION_R5900_HPP
|
||||
#define RABBITIZER_INSTRUCTION_R5900_HPP
|
||||
#pragma once
|
||||
|
||||
#include "InstructionBase.hpp"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class InstructionR5900 : public InstructionBase {
|
||||
public:
|
||||
InstructionR5900(uint32_t word, uint32_t vram);
|
||||
virtual ~InstructionR5900();
|
||||
|
||||
Registers::R5900::VF GetR5900_vfs() const;
|
||||
Registers::R5900::VF GetR5900_vft() const;
|
||||
Registers::R5900::VF GetR5900_vfd() const;
|
||||
|
||||
Registers::R5900::VI GetR5900_vis() const;
|
||||
Registers::R5900::VI GetR5900_vit() const;
|
||||
Registers::R5900::VI GetR5900_vid() const;
|
||||
|
||||
uint8_t GetR5900_mmi_function() const;
|
||||
uint8_t GetR5900_fhi_flo() const;
|
||||
|
||||
uint8_t GetR5900_xyzw_x() const;
|
||||
uint8_t GetR5900_xyzw_y() const;
|
||||
uint8_t GetR5900_xyzw_z() const;
|
||||
uint8_t GetR5900_xyzw_w() const;
|
||||
uint8_t GetR5900_n() const;
|
||||
uint8_t GetR5900_l() const;
|
||||
uint8_t GetR5900_m() const;
|
||||
|
||||
uint8_t GetR5900_imm5() const;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
40
cplusplus/include/instructions/InstructionRsp.hpp
Normal file
40
cplusplus/include/instructions/InstructionRsp.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_INSTRUCTION_RSP_HPP
|
||||
#define RABBITIZER_INSTRUCTION_RSP_HPP
|
||||
#pragma once
|
||||
|
||||
#include "InstructionBase.hpp"
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
class InstructionRsp : public InstructionBase {
|
||||
public:
|
||||
InstructionRsp(uint32_t word, uint32_t vram);
|
||||
virtual ~InstructionRsp();
|
||||
|
||||
Registers::Rsp::Gpr GetRsp_rs() const;
|
||||
Registers::Rsp::Gpr GetRsp_rt() const;
|
||||
Registers::Rsp::Gpr GetRsp_rd() const;
|
||||
|
||||
Registers::Rsp::Cop0 GetRsp_cop0d() const;
|
||||
|
||||
Registers::Rsp::Cop2 GetRsp_cop2t() const;
|
||||
|
||||
Registers::Rsp::Cop2Control GetRsp_cop2cd() const;
|
||||
|
||||
Registers::Rsp::Vector GetRsp_vs() const;
|
||||
Registers::Rsp::Vector GetRsp_vt() const;
|
||||
Registers::Rsp::Vector GetRsp_vd() const;
|
||||
|
||||
uint8_t GetRsp_elementhigh() const;
|
||||
uint8_t GetRsp_elementlow() const;
|
||||
|
||||
uint8_t GetRsp_index() const;
|
||||
uint8_t GetRsp_de() const;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
27
cplusplus/include/instructions/OperandType.hpp
Normal file
27
cplusplus/include/instructions/OperandType.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_OPERAND_TYPE_HPP
|
||||
#define RABBITIZER_OPERAND_TYPE_HPP
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
#define RAB_DEF_OPERAND(prefix, operand) \
|
||||
prefix##_##operand,
|
||||
|
||||
enum class OperandType {
|
||||
RAB_DEF_OPERAND(ALL, INVALID)
|
||||
|
||||
#include "instructions/operands/RabbitizerOperandType_cpu.inc"
|
||||
#include "instructions/operands/RabbitizerOperandType_rsp.inc"
|
||||
#include "instructions/operands/RabbitizerOperandType_r5900.inc"
|
||||
|
||||
RAB_DEF_OPERAND(ALL, MAX)
|
||||
};
|
||||
|
||||
#undef RAB_DEF_OPERAND
|
||||
};
|
||||
|
||||
|
||||
#endif
|
94
cplusplus/include/instructions/Registers.hpp
Normal file
94
cplusplus/include/instructions/Registers.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_REGISTER_HPP
|
||||
#define RABBITIZER_REGISTER_HPP
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace rabbitizer {
|
||||
|
||||
namespace Registers {
|
||||
#define RABBITIZER_DEF_REG(prefix, name, numeric) \
|
||||
prefix##_##name
|
||||
|
||||
#define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric) \
|
||||
prefix##_##name
|
||||
|
||||
namespace Cpu {
|
||||
enum class GprO32 {
|
||||
#include "instructions/registers/RabbitizerRegister_GprO32.inc"
|
||||
};
|
||||
|
||||
enum class GprN32 {
|
||||
#include "instructions/registers/RabbitizerRegister_GprN32.inc"
|
||||
};
|
||||
|
||||
|
||||
enum class Cop0 {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop0.inc"
|
||||
};
|
||||
|
||||
// Float registers
|
||||
enum class Cop1O32 {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop1O32.inc"
|
||||
};
|
||||
|
||||
enum class Cop1N32 {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop1N32.inc"
|
||||
};
|
||||
|
||||
enum class Cop1N64 {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop1N64.inc"
|
||||
};
|
||||
|
||||
enum class Cop1Control {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop1Control.inc"
|
||||
};
|
||||
|
||||
enum class Cop2 {
|
||||
#include "instructions/registers/RabbitizerRegister_Cop2.inc"
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
namespace Rsp {
|
||||
enum class Gpr {
|
||||
#include "instructions/registers/RabbitizerRegister_RspGpr.inc"
|
||||
};
|
||||
|
||||
enum class Cop0 {
|
||||
#include "instructions/registers/RabbitizerRegister_RspCop0.inc"
|
||||
};
|
||||
|
||||
enum class Cop2 {
|
||||
#include "instructions/registers/RabbitizerRegister_RspCop2.inc"
|
||||
};
|
||||
|
||||
enum class Cop2Control {
|
||||
#include "instructions/registers/RabbitizerRegister_RspCop2Control.inc"
|
||||
};
|
||||
|
||||
enum class Vector {
|
||||
#include "instructions/registers/RabbitizerRegister_RspVector.inc"
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
namespace R5900 {
|
||||
enum class VF {
|
||||
#include "instructions/registers/RabbitizerRegister_R5900VF.inc"
|
||||
};
|
||||
|
||||
enum class VI {
|
||||
#include "instructions/registers/RabbitizerRegister_R5900VI.inc"
|
||||
};
|
||||
};
|
||||
|
||||
#undef RABBITIZER_DEF_REG
|
||||
#undef RABBITIZER_DEF_REG_NODOLLAR
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
26
cplusplus/include/rabbitizer.hpp
Normal file
26
cplusplus/include/rabbitizer.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RABBITIZER_HPP
|
||||
#define RABBITIZER_HPP
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "common/RabbitizerVersion.h"
|
||||
#include "common/RabbitizerConfig.h"
|
||||
|
||||
#include "instructions/OperandType.hpp"
|
||||
#include "instructions/InstrId.hpp"
|
||||
//#include "instructions/InstrSuffix.hpp"
|
||||
//#include "instructions/InstrDescriptor.hpp"
|
||||
#include "instructions/Registers.hpp"
|
||||
#include "instructions/InstructionBase.hpp"
|
||||
#include "instructions/InstructionCpu.hpp"
|
||||
#include "instructions/InstructionRsp.hpp"
|
||||
#include "instructions/InstructionR5900.hpp"
|
||||
|
||||
#include "analysis/LoPairingInfo.hpp"
|
||||
#include "analysis/RegistersTracker.hpp"
|
||||
|
||||
|
||||
#endif
|
37
cplusplus/src/analysis/LoPairingInfo.cpp
Normal file
37
cplusplus/src/analysis/LoPairingInfo.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "analysis/LoPairingInfo.hpp"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
|
||||
LoPairingInfo::LoPairingInfo() {
|
||||
|
||||
}
|
||||
LoPairingInfo::LoPairingInfo(const RabbitizerLoPairingInfo &pairingInfo) {
|
||||
this->pairingInfo = pairingInfo;
|
||||
}
|
||||
|
||||
RabbitizerLoPairingInfo *LoPairingInfo::getCPtr() {
|
||||
return &this->pairingInfo;
|
||||
}
|
||||
const RabbitizerLoPairingInfo *LoPairingInfo::getCPtr() const{
|
||||
return &this->pairingInfo;
|
||||
}
|
||||
|
||||
int LoPairingInfo::getInstrOffset() const {
|
||||
return this->pairingInfo.instrOffset;
|
||||
}
|
||||
int64_t LoPairingInfo::getValue() const {
|
||||
return this->pairingInfo.value;
|
||||
}
|
||||
bool LoPairingInfo::shouldProcess() const {
|
||||
return this->pairingInfo.shouldProcess;
|
||||
}
|
||||
bool LoPairingInfo::isGpRel() const {
|
||||
return this->pairingInfo.isGpRel;
|
||||
}
|
||||
bool LoPairingInfo::isGpGot() const {
|
||||
return this->pairingInfo.isGpGot;
|
||||
}
|
67
cplusplus/src/analysis/RegistersTracker.cpp
Normal file
67
cplusplus/src/analysis/RegistersTracker.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "analysis/RegistersTracker.hpp"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
|
||||
RegistersTracker::RegistersTracker() {
|
||||
RabbitizerRegistersTracker_init(&this->tracker, NULL);
|
||||
}
|
||||
RegistersTracker::RegistersTracker(const RegistersTracker &other) {
|
||||
RabbitizerRegistersTracker_init(&this->tracker, &other.tracker);
|
||||
}
|
||||
RegistersTracker::~RegistersTracker() {
|
||||
RabbitizerRegistersTracker_destroy(&this->tracker);
|
||||
}
|
||||
|
||||
|
||||
RabbitizerRegistersTracker *RegistersTracker::getCPtr() {
|
||||
return &this->tracker;
|
||||
}
|
||||
const RabbitizerRegistersTracker *RegistersTracker::getCPtr() const {
|
||||
return &this->tracker;
|
||||
}
|
||||
|
||||
|
||||
bool RegistersTracker::moveRegisters(const InstructionBase &instr) {
|
||||
return RabbitizerRegistersTracker_moveRegisters(&this->tracker, instr.getCPtr());
|
||||
}
|
||||
void RegistersTracker::overwriteRegisters(const InstructionBase &instr, int instrOffset) {
|
||||
RabbitizerRegistersTracker_overwriteRegisters(&this->tracker, instr.getCPtr(), instrOffset);
|
||||
}
|
||||
void RegistersTracker::unsetRegistersAfterFuncCall(const InstructionBase &instr, const InstructionBase &prevInstr) {
|
||||
RabbitizerRegistersTracker_unsetRegistersAfterFuncCall(&this->tracker, instr.getCPtr(), prevInstr.getCPtr());
|
||||
}
|
||||
bool RegistersTracker::getAddressIfCanSetType(const InstructionBase &instr, int instrOffset, uint32_t *dstAddress) const {
|
||||
return RabbitizerRegistersTracker_getAddressIfCanSetType(&this->tracker, instr.getCPtr(), instrOffset, dstAddress);
|
||||
}
|
||||
bool RegistersTracker::getJrInfo(const InstructionBase &instr, int *dstOffset, uint32_t *dstAddress) const {
|
||||
return RabbitizerRegistersTracker_getJrInfo(&this->tracker, instr.getCPtr(), dstOffset, dstAddress);
|
||||
}
|
||||
|
||||
void RegistersTracker::processLui(const InstructionBase &instr, int instrOffset) {
|
||||
RabbitizerRegistersTracker_processLui(&this->tracker, instr.getCPtr(), instrOffset, NULL);
|
||||
}
|
||||
void RegistersTracker::processLui(const InstructionBase &instr, int instrOffset, const InstructionBase &prevInstr) {
|
||||
RabbitizerRegistersTracker_processLui(&this->tracker, instr.getCPtr(), instrOffset, prevInstr.getCPtr());
|
||||
}
|
||||
void RegistersTracker::processGpLoad(const InstructionBase &instr, int instrOffset) {
|
||||
RabbitizerRegistersTracker_processGpLoad(&this->tracker, instr.getCPtr(), instrOffset);
|
||||
}
|
||||
bool RegistersTracker::getLuiOffsetForConstant(const InstructionBase &instr, int *dstOffset) const {
|
||||
return RabbitizerRegistersTracker_getLuiOffsetForConstant(&this->tracker, instr.getCPtr(), dstOffset);
|
||||
}
|
||||
void RegistersTracker::processConstant(const InstructionBase &instr, uint32_t value, int offset) {
|
||||
RabbitizerRegistersTracker_processConstant(&this->tracker, instr.getCPtr(), value, offset);
|
||||
}
|
||||
LoPairingInfo RegistersTracker::preprocessLoAndGetInfo(const InstructionBase &instr, int instrOffset) {
|
||||
return RabbitizerRegistersTracker_preprocessLoAndGetInfo(&this->tracker, instr.getCPtr(), instrOffset);
|
||||
}
|
||||
void RegistersTracker::processLo(const InstructionBase &instr, uint32_t value, int offset) {
|
||||
RabbitizerRegistersTracker_processLo(&this->tracker, instr.getCPtr(), value, offset);
|
||||
}
|
||||
bool RegistersTracker::hasLoButNoHi(const InstructionBase &instr) const {
|
||||
return RabbitizerRegistersTracker_hasLoButNoHi(&this->tracker, instr.getCPtr());
|
||||
}
|
14
cplusplus/src/instructions/InstrId.cpp
Normal file
14
cplusplus/src/instructions/InstrId.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "instructions/InstrId.hpp"
|
||||
|
||||
#include "instructions/RabbitizerInstrId.h"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
std::string InstrId::getOpcodeName(InstrId::UniqueId uniqueId) {
|
||||
RabbitizerInstrId id = static_cast<RabbitizerInstrId>(uniqueId);
|
||||
|
||||
return std::string(RabbitizerInstrId_getOpcodeName(id));
|
||||
}
|
1015
cplusplus/src/instructions/InstructionBase.cpp
Normal file
1015
cplusplus/src/instructions/InstructionBase.cpp
Normal file
File diff suppressed because it is too large
Load Diff
16
cplusplus/src/instructions/InstructionCpu.cpp
Normal file
16
cplusplus/src/instructions/InstructionCpu.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "instructions/InstructionCpu.hpp"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
|
||||
InstructionCpu::InstructionCpu(uint32_t word, uint32_t vram) : InstructionBase() {
|
||||
RabbitizerInstruction_init(&this->instr, word, vram);
|
||||
RabbitizerInstruction_processUniqueId(&this->instr);
|
||||
}
|
||||
|
||||
InstructionCpu::~InstructionCpu() {
|
||||
RabbitizerInstruction_destroy(&this->instr);
|
||||
}
|
121
cplusplus/src/instructions/InstructionR5900.cpp
Normal file
121
cplusplus/src/instructions/InstructionR5900.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "instructions/InstructionR5900.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "instructions/RabbitizerInstructionR5900.h"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
|
||||
InstructionR5900::InstructionR5900(uint32_t word, uint32_t vram) : InstructionBase() {
|
||||
RabbitizerInstructionR5900_init(&this->instr, word, vram);
|
||||
RabbitizerInstructionR5900_processUniqueId(&this->instr);
|
||||
}
|
||||
|
||||
InstructionR5900::~InstructionR5900() {
|
||||
RabbitizerInstructionR5900_destroy(&this->instr);
|
||||
}
|
||||
|
||||
|
||||
Registers::R5900::VF InstructionR5900::GetR5900_vfs() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rs)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vfs' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VF>(RAB_INSTR_R5900_GET_vfs(&this->instr));
|
||||
}
|
||||
|
||||
Registers::R5900::VF InstructionR5900::GetR5900_vft() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rt)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vft' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VF>(RAB_INSTR_R5900_GET_vft(&this->instr));
|
||||
}
|
||||
|
||||
Registers::R5900::VF InstructionR5900::GetR5900_vfd() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rd)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vfd' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VF>(RAB_INSTR_R5900_GET_vfd(&this->instr));
|
||||
}
|
||||
|
||||
Registers::R5900::VI InstructionR5900::GetR5900_vis() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rs)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vis' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VI>(RAB_INSTR_R5900_GET_vis(&this->instr));
|
||||
}
|
||||
|
||||
Registers::R5900::VI InstructionR5900::GetR5900_vit() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rt)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vit' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VI>(RAB_INSTR_R5900_GET_vit(&this->instr));
|
||||
}
|
||||
|
||||
Registers::R5900::VI InstructionR5900::GetR5900_vid() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rd)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vid' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::R5900::VI>(RAB_INSTR_R5900_GET_vid(&this->instr));
|
||||
}
|
||||
|
||||
|
||||
uint8_t InstructionR5900::GetR5900_mmi_function() const {
|
||||
return RAB_INSTR_R5900_GET_mmi_function(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_fhi_flo() const {
|
||||
return RAB_INSTR_R5900_GET_fhi_flo(&this->instr);
|
||||
}
|
||||
|
||||
uint8_t InstructionR5900::GetR5900_xyzw_x() const {
|
||||
return RAB_INSTR_R5900_GET_xyzw_x(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_xyzw_y() const {
|
||||
return RAB_INSTR_R5900_GET_xyzw_y(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_xyzw_z() const {
|
||||
return RAB_INSTR_R5900_GET_xyzw_z(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_xyzw_w() const {
|
||||
return RAB_INSTR_R5900_GET_xyzw_w(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_n() const {
|
||||
return RAB_INSTR_R5900_GET_n(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_l() const {
|
||||
return RAB_INSTR_R5900_GET_l(&this->instr);
|
||||
}
|
||||
uint8_t InstructionR5900::GetR5900_m() const {
|
||||
return RAB_INSTR_R5900_GET_m(&this->instr);
|
||||
}
|
||||
|
||||
uint8_t InstructionR5900::GetR5900_imm5() const {
|
||||
return RAB_INSTR_R5900_GET_imm5(&this->instr);
|
||||
}
|
130
cplusplus/src/instructions/InstructionRsp.cpp
Normal file
130
cplusplus/src/instructions/InstructionRsp.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "instructions/InstructionRsp.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "instructions/RabbitizerInstructionRsp.h"
|
||||
|
||||
using namespace rabbitizer;
|
||||
|
||||
|
||||
InstructionRsp::InstructionRsp(uint32_t word, uint32_t vram) : InstructionBase() {
|
||||
RabbitizerInstructionRsp_init(&this->instr, word, vram);
|
||||
RabbitizerInstructionRsp_processUniqueId(&this->instr);
|
||||
}
|
||||
|
||||
InstructionRsp::~InstructionRsp() {
|
||||
RabbitizerInstructionRsp_destroy(&this->instr);
|
||||
}
|
||||
|
||||
|
||||
Registers::Rsp::Gpr InstructionRsp::GetRsp_rs() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rs)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'rs' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Gpr>(RAB_INSTR_GET_rs(&this->instr));
|
||||
}
|
||||
Registers::Rsp::Gpr InstructionRsp::GetRsp_rt() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rt)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'rt' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Gpr>(RAB_INSTR_GET_rt(&this->instr));
|
||||
}
|
||||
Registers::Rsp::Gpr InstructionRsp::GetRsp_rd() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_rd)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'rd' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Gpr>(RAB_INSTR_GET_rd(&this->instr));
|
||||
}
|
||||
|
||||
Registers::Rsp::Cop0 InstructionRsp::GetRsp_cop0d() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_cop0d)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'cop0d' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Cop0>(RAB_INSTR_GET_cop0d(&this->instr));
|
||||
}
|
||||
|
||||
Registers::Rsp::Cop2 InstructionRsp::GetRsp_cop2t() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_cop2t)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'cop2t' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Cop2>(RAB_INSTR_RSP_GET_cop2t(&this->instr));
|
||||
}
|
||||
|
||||
Registers::Rsp::Cop2Control InstructionRsp::GetRsp_cop2cd() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_cop2t)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'cop2cd' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Cop2Control>(RAB_INSTR_RSP_GET_cop2cd(&this->instr));
|
||||
}
|
||||
|
||||
Registers::Rsp::Vector InstructionRsp::GetRsp_vs() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_vs)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vs' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Vector>(RAB_INSTR_RSP_GET_vs(&this->instr));
|
||||
}
|
||||
Registers::Rsp::Vector InstructionRsp::GetRsp_vt() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_vt)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vt' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Vector>(RAB_INSTR_RSP_GET_vt(&this->instr));
|
||||
}
|
||||
Registers::Rsp::Vector InstructionRsp::GetRsp_vd() const {
|
||||
#ifdef RAB_SANITY_CHECKS
|
||||
if (!hasOperandAlias(OperandType::rsp_vd)) {
|
||||
// TODO: make a rabbitizer exception class
|
||||
throw std::runtime_error("Instruction '" + getOpcodeName() + "' does not have 'vd' operand.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<Registers::Rsp::Vector>(RAB_INSTR_RSP_GET_vd(&this->instr));
|
||||
}
|
||||
|
||||
uint8_t InstructionRsp::GetRsp_elementhigh() const {
|
||||
return RAB_INSTR_RSP_GET_elementhigh(&this->instr);
|
||||
}
|
||||
uint8_t InstructionRsp::GetRsp_elementlow() const {
|
||||
return RAB_INSTR_RSP_GET_elementlow(&this->instr);
|
||||
}
|
||||
|
||||
uint8_t InstructionRsp::GetRsp_index() const {
|
||||
return RAB_INSTR_RSP_GET_index(&this->instr);
|
||||
}
|
||||
uint8_t InstructionRsp::GetRsp_de() const {
|
||||
return RAB_INSTR_RSP_GET_de(&this->instr);
|
||||
}
|
@ -14,11 +14,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RAB_REGISTERS_COUNT 32
|
||||
|
||||
|
||||
typedef struct RabbitizerRegistersTracker {
|
||||
RabbitizerTrackedRegisterState registers[32];
|
||||
RabbitizerTrackedRegisterState registers[RAB_REGISTERS_COUNT];
|
||||
} RabbitizerRegistersTracker;
|
||||
|
||||
// TODO: Change functions which use parameters as a way to return values into actual structs returned by the functions
|
||||
|
||||
NON_NULL(1)
|
||||
void RabbitizerRegistersTracker_init(RabbitizerRegistersTracker *self, const RabbitizerRegistersTracker *other);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#ifndef RABBITIZER_H
|
||||
#define RABBITIZER_H
|
||||
#pragma once
|
||||
|
||||
#include "common/Utils.h"
|
||||
#include "common/RabbitizerVersion.h"
|
||||
|
12
setup.py
12
setup.py
@ -21,18 +21,6 @@ setup(
|
||||
extra_compile_args = [
|
||||
"-std=c11",
|
||||
"-Wall",
|
||||
#"-Wextra",
|
||||
# "-Wpedantic", # binary constants :s
|
||||
#"-Wno-cast-function-type",
|
||||
#"-Werror=implicit-function-declaration",
|
||||
#"-Werror=incompatible-pointer-types",
|
||||
#"-Werror=vla",
|
||||
#"-Werror=switch",
|
||||
#"-Werror=implicit-fallthrough",
|
||||
#"-Werror=unused-function",
|
||||
#"-Werror=unused-parameter",
|
||||
#"-Werror=shadow",
|
||||
# "-Werror",
|
||||
"-g",
|
||||
],
|
||||
),
|
||||
|
@ -155,6 +155,9 @@ bool RabbitizerInstruction_hasOperandAlias(const RabbitizerInstruction *self, Ra
|
||||
if (RabbitizerInstruction_hasOperand(self, RAB_OPERAND_cpu_immediate_base)) {
|
||||
return true;
|
||||
}
|
||||
if (RabbitizerInstruction_hasOperand(self, RAB_OPERAND_cpu_branch_target_label)) {
|
||||
return true;
|
||||
}
|
||||
if (RabbitizerInstruction_hasOperand(self, RAB_OPERAND_rsp_immediate_base)) {
|
||||
return true;
|
||||
}
|
||||
|
16
tests/cplusplus/test.cpp
Normal file
16
tests/cplusplus/test.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-FileCopyrightText: © 2022 Decompollaborate */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "instructions/InstructionCpu.hpp"
|
||||
|
||||
|
||||
int main() {
|
||||
uint32_t word = 0x8D4A7E18; // lw
|
||||
uint32_t vram = 0x80000000;
|
||||
int extraLJust = 5;
|
||||
rabbitizer::InstructionCpu instr(word, vram);
|
||||
|
||||
printf("%08X: %s\n", word, instr.disassemble(extraLJust).c_str());
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user