mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-14 08:12:19 +00:00
Reorganized headers and add recomp.h from modern runtime
This commit is contained in:
parent
adaca23f09
commit
1aa4ad6518
17 changed files with 308 additions and 21 deletions
|
@ -159,14 +159,8 @@ project(OfflineModRecomp)
|
|||
add_executable(OfflineModRecomp)
|
||||
|
||||
target_sources(OfflineModRecomp PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../sljit/sljit_src/sljitLir.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/OfflineModRecomp/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/OfflineModRecomp/sljit_generator.cpp
|
||||
)
|
||||
|
||||
target_include_directories(OfflineModRecomp PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../sljit/sljit_src
|
||||
)
|
||||
|
||||
target_link_libraries(OfflineModRecomp fmt rabbitizer tomlplusplus::tomlplusplus N64Recomp)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <vector>
|
||||
#include <span>
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "rabbitizer.hpp"
|
||||
|
||||
static std::vector<uint8_t> read_file(const std::filesystem::path& path, bool& found) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <cstdlib>
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/ostream.h"
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
293
include/recomp.h
Normal file
293
include/recomp.h
Normal file
|
@ -0,0 +1,293 @@
|
|||
#ifndef __RECOMP_H__
|
||||
#define __RECOMP_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
// Compiler definition to disable inter-procedural optimization, allowing multiple functions to be in a single file without breaking interposition.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC's __declspec(noinline) seems to disable inter-procedural optimization entirely, so it's all that's needed.
|
||||
#define RECOMP_FUNC __declspec(noinline)
|
||||
#elif defined(__clang__)
|
||||
// Clang has no dedicated IPO attribute, so we use a combination of other attributes to give the desired behavior.
|
||||
// The inline keyword allows multiple definitions during linking, and extern forces clang to emit an externally visible definition.
|
||||
// Weak forces Clang to not perform any IPO as the symbol can be interposed, which prevents actual inlining due to the inline keyword.
|
||||
// Add noinline on for good measure, which doesn't conflict with the inline keyword as they have different meanings.
|
||||
#define RECOMP_FUNC extern inline __attribute__((weak,noinline))
|
||||
#elif defined(__GNUC__)
|
||||
// Use GCC's attribute for disabling inter-procedural optimizations.
|
||||
#define RECOMP_FUNC __attribute__((noipa))
|
||||
#else
|
||||
#error "No RECOMP_FUNC definition for this compiler"
|
||||
#endif
|
||||
|
||||
typedef uint64_t gpr;
|
||||
|
||||
#define SIGNED(val) \
|
||||
((int64_t)(val))
|
||||
|
||||
#define ADD32(a, b) \
|
||||
((gpr)(int32_t)((a) + (b)))
|
||||
|
||||
#define SUB32(a, b) \
|
||||
((gpr)(int32_t)((a) - (b)))
|
||||
|
||||
#define MEM_W(offset, reg) \
|
||||
(*(int32_t*)(rdram + ((((reg) + (offset))) - 0xFFFFFFFF80000000)))
|
||||
|
||||
#define MEM_H(offset, reg) \
|
||||
(*(int16_t*)(rdram + ((((reg) + (offset)) ^ 2) - 0xFFFFFFFF80000000)))
|
||||
|
||||
#define MEM_B(offset, reg) \
|
||||
(*(int8_t*)(rdram + ((((reg) + (offset)) ^ 3) - 0xFFFFFFFF80000000)))
|
||||
|
||||
#define MEM_HU(offset, reg) \
|
||||
(*(uint16_t*)(rdram + ((((reg) + (offset)) ^ 2) - 0xFFFFFFFF80000000)))
|
||||
|
||||
#define MEM_BU(offset, reg) \
|
||||
(*(uint8_t*)(rdram + ((((reg) + (offset)) ^ 3) - 0xFFFFFFFF80000000)))
|
||||
|
||||
#define SD(val, offset, reg) { \
|
||||
*(uint32_t*)(rdram + ((((reg) + (offset) + 4)) - 0xFFFFFFFF80000000)) = (uint32_t)((gpr)(val) >> 0); \
|
||||
*(uint32_t*)(rdram + ((((reg) + (offset) + 0)) - 0xFFFFFFFF80000000)) = (uint32_t)((gpr)(val) >> 32); \
|
||||
}
|
||||
|
||||
static inline uint64_t load_doubleword(uint8_t* rdram, gpr reg, gpr offset) {
|
||||
uint64_t ret = 0;
|
||||
uint64_t lo = (uint64_t)(uint32_t)MEM_W(reg, offset + 4);
|
||||
uint64_t hi = (uint64_t)(uint32_t)MEM_W(reg, offset + 0);
|
||||
ret = (lo << 0) | (hi << 32);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LD(offset, reg) \
|
||||
load_doubleword(rdram, offset, reg)
|
||||
|
||||
static inline gpr do_lwl(uint8_t* rdram, gpr initial_value, gpr offset, gpr reg) {
|
||||
// Calculate the overall address
|
||||
gpr address = (offset + reg);
|
||||
|
||||
// Load the aligned word
|
||||
gpr word_address = address & ~0x3;
|
||||
uint32_t loaded_value = MEM_W(0, word_address);
|
||||
|
||||
// Mask the existing value and shift the loaded value appropriately
|
||||
gpr misalignment = address & 0x3;
|
||||
gpr masked_value = initial_value & ~(0xFFFFFFFFu << (misalignment * 8));
|
||||
loaded_value <<= (misalignment * 8);
|
||||
|
||||
// Cast to int32_t to sign extend first
|
||||
return (gpr)(int32_t)(masked_value | loaded_value);
|
||||
}
|
||||
|
||||
static inline gpr do_lwr(uint8_t* rdram, gpr initial_value, gpr offset, gpr reg) {
|
||||
// Calculate the overall address
|
||||
gpr address = (offset + reg);
|
||||
|
||||
// Load the aligned word
|
||||
gpr word_address = address & ~0x3;
|
||||
uint32_t loaded_value = MEM_W(0, word_address);
|
||||
|
||||
// Mask the existing value and shift the loaded value appropriately
|
||||
gpr misalignment = address & 0x3;
|
||||
gpr masked_value = initial_value & ~(0xFFFFFFFFu >> (24 - misalignment * 8));
|
||||
loaded_value >>= (24 - misalignment * 8);
|
||||
|
||||
// Cast to int32_t to sign extend first
|
||||
return (gpr)(int32_t)(masked_value | loaded_value);
|
||||
}
|
||||
|
||||
static inline void do_swl(uint8_t* rdram, gpr offset, gpr reg, gpr val) {
|
||||
// Calculate the overall address
|
||||
gpr address = (offset + reg);
|
||||
|
||||
// Get the initial value of the aligned word
|
||||
gpr word_address = address & ~0x3;
|
||||
uint32_t initial_value = MEM_W(0, word_address);
|
||||
|
||||
// Mask the initial value and shift the input value appropriately
|
||||
gpr misalignment = address & 0x3;
|
||||
uint32_t masked_initial_value = initial_value & ~(0xFFFFFFFFu >> (misalignment * 8));
|
||||
uint32_t shifted_input_value = ((uint32_t)val) >> (misalignment * 8);
|
||||
MEM_W(0, word_address) = masked_initial_value | shifted_input_value;
|
||||
}
|
||||
|
||||
static inline void do_swr(uint8_t* rdram, gpr offset, gpr reg, gpr val) {
|
||||
// Calculate the overall address
|
||||
gpr address = (offset + reg);
|
||||
|
||||
// Get the initial value of the aligned word
|
||||
gpr word_address = address & ~0x3;
|
||||
uint32_t initial_value = MEM_W(0, word_address);
|
||||
|
||||
// Mask the initial value and shift the input value appropriately
|
||||
gpr misalignment = address & 0x3;
|
||||
uint32_t masked_initial_value = initial_value & ~(0xFFFFFFFFu << (24 - misalignment * 8));
|
||||
uint32_t shifted_input_value = ((uint32_t)val) << (24 - misalignment * 8);
|
||||
MEM_W(0, word_address) = masked_initial_value | shifted_input_value;
|
||||
}
|
||||
|
||||
#define S32(val) \
|
||||
((int32_t)(val))
|
||||
|
||||
#define U32(val) \
|
||||
((uint32_t)(val))
|
||||
|
||||
#define S64(val) \
|
||||
((int64_t)(val))
|
||||
|
||||
#define U64(val) \
|
||||
((uint64_t)(val))
|
||||
|
||||
#define MUL_S(val1, val2) \
|
||||
((val1) * (val2))
|
||||
|
||||
#define MUL_D(val1, val2) \
|
||||
((val1) * (val2))
|
||||
|
||||
#define DIV_S(val1, val2) \
|
||||
((val1) / (val2))
|
||||
|
||||
#define DIV_D(val1, val2) \
|
||||
((val1) / (val2))
|
||||
|
||||
#define CVT_S_W(val) \
|
||||
((float)((int32_t)(val)))
|
||||
|
||||
#define CVT_D_W(val) \
|
||||
((double)((int32_t)(val)))
|
||||
|
||||
#define CVT_D_S(val) \
|
||||
((double)(val))
|
||||
|
||||
#define CVT_S_D(val) \
|
||||
((float)(val))
|
||||
|
||||
#define TRUNC_W_S(val) \
|
||||
((int32_t)(val))
|
||||
|
||||
#define TRUNC_W_D(val) \
|
||||
((int32_t)(val))
|
||||
|
||||
#define TRUNC_L_S(val) \
|
||||
((int64_t)(val))
|
||||
|
||||
#define TRUNC_L_D(val) \
|
||||
((int64_t)(val))
|
||||
|
||||
#define DEFAULT_ROUNDING_MODE 0
|
||||
|
||||
static inline int32_t do_cvt_w_s(float val, unsigned int rounding_mode) {
|
||||
switch (rounding_mode) {
|
||||
case 0: // round to nearest value
|
||||
return (int32_t)lroundf(val);
|
||||
case 1: // round to zero (truncate)
|
||||
return (int32_t)val;
|
||||
case 2: // round to positive infinity (ceil)
|
||||
return (int32_t)ceilf(val);
|
||||
case 3: // round to negative infinity (floor)
|
||||
return (int32_t)floorf(val);
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CVT_W_S(val) \
|
||||
do_cvt_w_s(val, rounding_mode)
|
||||
|
||||
static inline int32_t do_cvt_w_d(double val, unsigned int rounding_mode) {
|
||||
switch (rounding_mode) {
|
||||
case 0: // round to nearest value
|
||||
return (int32_t)lround(val);
|
||||
case 1: // round to zero (truncate)
|
||||
return (int32_t)val;
|
||||
case 2: // round to positive infinity (ceil)
|
||||
return (int32_t)ceil(val);
|
||||
case 3: // round to negative infinity (floor)
|
||||
return (int32_t)floor(val);
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CVT_W_D(val) \
|
||||
do_cvt_w_d(val, rounding_mode)
|
||||
|
||||
#define NAN_CHECK(val) \
|
||||
assert(val == val)
|
||||
|
||||
//#define NAN_CHECK(val)
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
float fl;
|
||||
float fh;
|
||||
};
|
||||
struct {
|
||||
uint32_t u32l;
|
||||
uint32_t u32h;
|
||||
};
|
||||
uint64_t u64;
|
||||
} fpr;
|
||||
|
||||
typedef struct {
|
||||
gpr r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||
r16, r17, r18, r19, r20, r21, r22, r23,
|
||||
r24, r25, r26, r27, r28, r29, r30, r31;
|
||||
fpr f0, f1, f2, f3, f4, f5, f6, f7,
|
||||
f8, f9, f10, f11, f12, f13, f14, f15,
|
||||
f16, f17, f18, f19, f20, f21, f22, f23,
|
||||
f24, f25, f26, f27, f28, f29, f30, f31;
|
||||
uint64_t hi, lo;
|
||||
uint32_t* f_odd;
|
||||
uint32_t status_reg;
|
||||
uint8_t mips3_float_mode;
|
||||
} recomp_context;
|
||||
|
||||
// Checks if the target is an even float register or that mips3 float mode is enabled
|
||||
#define CHECK_FR(ctx, idx) \
|
||||
assert(((idx) & 1) == 0 || (ctx)->mips3_float_mode)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cop0_status_write(recomp_context* ctx, gpr value);
|
||||
gpr cop0_status_read(recomp_context* ctx);
|
||||
void switch_error(const char* func, uint32_t vram, uint32_t jtbl);
|
||||
void do_break(uint32_t vram);
|
||||
|
||||
typedef void (recomp_func_t)(uint8_t* rdram, recomp_context* ctx);
|
||||
|
||||
recomp_func_t* get_function(int32_t vram);
|
||||
|
||||
#define LOOKUP_FUNC(val) \
|
||||
get_function((int32_t)(val))
|
||||
|
||||
extern int32_t* section_addresses;
|
||||
|
||||
#define LO16(x) \
|
||||
((x) & 0xFFFF)
|
||||
|
||||
#define HI16(x) \
|
||||
(((x) >> 16) + (((x) >> 15) & 1))
|
||||
|
||||
#define RELOC_HI16(section_index, offset) \
|
||||
HI16(section_addresses[section_index] + (offset))
|
||||
|
||||
#define RELOC_LO16(section_index, offset) \
|
||||
LO16(section_addresses[section_index] + (offset))
|
||||
|
||||
void recomp_syscall_handler(uint8_t* rdram, recomp_context* ctx, int32_t instruction_vram);
|
||||
|
||||
void pause_self(uint8_t *rdram);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __GENERATOR_H__
|
||||
#define __GENERATOR_H__
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "operations.h"
|
||||
|
||||
namespace N64Recomp {
|
|
@ -4,7 +4,7 @@
|
|||
#include "rabbitizer.hpp"
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "analysis.h"
|
||||
|
||||
extern "C" const char* RabbitizerRegister_getNameGpr(uint8_t regValue);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
|
||||
namespace N64Recomp {
|
||||
struct JumpTable {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "fmt/format.h"
|
||||
#include "fmt/ostream.h"
|
||||
|
||||
#include "generator.h"
|
||||
#include "recompiler/generator.h"
|
||||
|
||||
struct BinaryOpFields { std::string func_string; std::string infix_string; };
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <toml++/toml.hpp>
|
||||
#include "fmt/format.h"
|
||||
#include "config.h"
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
|
||||
std::filesystem::path concat_if_not_empty(const std::filesystem::path& parent, const std::filesystem::path& child) {
|
||||
if (!child.empty()) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "fmt/format.h"
|
||||
// #include "fmt/ostream.h"
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "elfio/elfio.hpp"
|
||||
|
||||
bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, const N64Recomp::ElfParsingConfig& elf_config, bool dumping_context, std::unordered_map<uint16_t, std::vector<N64Recomp::DataSymbol>>& data_syms) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "fmt/format.h"
|
||||
#include "fmt/ostream.h"
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "config.h"
|
||||
#include <set>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
|
||||
struct FileHeader {
|
||||
char magic[8]; // N64RSYMS
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "operations.h"
|
||||
#include "recompiler/operations.h"
|
||||
|
||||
namespace N64Recomp {
|
||||
const std::unordered_map<InstrId, UnaryOp> unary_ops {
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
#include "fmt/format.h"
|
||||
#include "fmt/ostream.h"
|
||||
|
||||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
#include "analysis.h"
|
||||
#include "operations.h"
|
||||
#include "generator.h"
|
||||
#include "recompiler/operations.h"
|
||||
#include "recompiler/generator.h"
|
||||
|
||||
enum class JalResolutionResult {
|
||||
NoMatch,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "n64recomp.h"
|
||||
#include "recompiler/context.h"
|
||||
|
||||
const std::unordered_set<std::string> N64Recomp::reimplemented_funcs {
|
||||
// OS initialize functions
|
||||
|
|
Loading…
Add table
Reference in a new issue