summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortehzz <tehzz@users.noreply.github.com>2022-06-15 20:26:03 -0400
committerGitHub <noreply@github.com>2022-06-15 17:26:03 -0700
commit0f0ff04779ed42818b2b976b889fe71727957592 (patch)
tree5408a05deb1c6af5ea7120c7c8b9fbbf21da9473
parent491f37be4d8f1f0aa3eb3e1e043c3b5c35c974ce (diff)
Add building on macOS (#224)
* build OK macOS * add macOS building instructions * change return type of func_8000546C * prevent gitattributes from removing CRLF from ido binaries
-rw-r--r--.gitattributes23
-rw-r--r--Makefile25
-rw-r--r--README.md17
-rw-r--r--src/staff_ghosts.c2
-rw-r--r--tools/gfxdis_multi.py122
-rw-r--r--tools/ido5.3_recomp/Makefile38
-rwxr-xr-x[-rw-r--r--]tools/ido5.3_recomp/elf.h0
-rwxr-xr-x[-rw-r--r--]tools/ido5.3_recomp/helpers.h0
-rwxr-xr-x[-rw-r--r--]tools/ido5.3_recomp/libc_impl.c93
-rwxr-xr-x[-rw-r--r--]tools/ido5.3_recomp/libc_impl.h4
-rwxr-xr-x[-rw-r--r--]tools/ido5.3_recomp/recomp.cpp108
11 files changed, 295 insertions, 137 deletions
diff --git a/.gitattributes b/.gitattributes
index fcadb2cf9..980b4bf4d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,22 @@
-* text eol=lf
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# force C files to unix endings regardless of host platform
+# for compatibility with IDO cc
+*.c text eol=lf diff=c
+*.h text eol=lf diff=c
+
+# List text files in case git doesn't characterize correctly
+*.s text
+*.in text
+*.js text
+*.md text
+*.py text diff=python
+*.sh text
+*.ld text
+*.inc text
+*.txt text
+*.json text
+*.yaml text
+*.toml text
+*.rs text diff=rust
diff --git a/Makefile b/Makefile
index 6d060627f..cbb4683ca 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,10 @@ ifeq ($(VERSION),us)
TARGET := mk64.us
endif
+### Utility Functions ###
+# Returns the path to the command $(1) if exists. Otherwise returns an empty string.
+find-command = $(shell which $(1) 2>/dev/null)
+
################ Target Executable and Sources ###############
# BUILD_DIR is location where all build artifacts are placed
@@ -110,29 +114,36 @@ TOOLS_DIR := tools
ifeq ($(USE_QEMU_IRIX),1)
# Verify that qemu-irix exists
- QEMU_IRIX := $(shell which qemu-irix)
- ifeq (, $(QEMU_IRIX))
+ QEMU_IRIX := $(call find-command,qemu-irix)
+ ifeq (,$(QEMU_IRIX))
$(error Using the IDO compiler requires qemu-irix. Please install qemu-irix package or set the QEMU_IRIX environment variable to the full qemu-irix binary path)
endif
endif
ifeq ($(USE_QEMU_IRIX),1)
IRIX_ROOT := $(TOOLS_DIR)/ido5.3_compiler
- CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc
+ CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc
else
IDO_ROOT := tools/ido5.3_recomp
- CC := $(IDO_ROOT)/cc
+ CC := $(IDO_ROOT)/cc
endif
AS := $(CROSS)as
-
-CPP := cpp -P -Wno-trigraphs
LD := $(CROSS)ld
AR := $(CROSS)ar
OBJDUMP := $(CROSS)objdump
OBJCOPY := $(CROSS)objcopy
PYTHON := python3
+# Prefer clang as C preprocessor if installed on the system
+ifneq (,$(call find-command,clang))
+ CPP := clang
+ CPPFLAGS := -E -P -x c -Wno-trigraphs
+else
+ CPP := cpp
+ CPPFLAGS := -P -Wno-trigraphs
+endif
+
MIPSISET := -mips2 -32
OPT_FLAGS := -O2
@@ -466,7 +477,7 @@ $(GLOBAL_ASM_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(A
$(GLOBAL_ASM_AUDIO_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) --
$(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) #repeat for other files
- $(CPP) $(VERSION_CFLAGS) -DBUILD_DIR=$(BUILD_DIR) -MMD -MP -MT $@ -MF $@.d -o $@ $<
+ $(CPP) $(CPPFLAGS) $(VERSION_CFLAGS) -DBUILD_DIR=$(BUILD_DIR) -MMD -MP -MT $@ -MF $@.d -o $@ $<
#################### Libultra #####################
diff --git a/README.md b/README.md
index 6efe1b3b8..e14b52c41 100644
--- a/README.md
+++ b/README.md
@@ -49,14 +49,25 @@ Compiling on Windows requires `MSYS2 MinGW x64`. The setup process is a tad inte
[Instructions here](docs/BUILD_WINDOWS.md)
+#### macOS
+
+Install [Homebrew](https://brew.sh), then install the following dependencies:
+```
+brew update
+brew install python3 capstone coreutils make pkg-config tehzz/n64-dev/mips64-elf-binutils
+```
+
+When building, use `gmake` to ensure that homebrew `make` is used instead of the old, macOS system `make`.
+
## Building
Place a US version of Mario Kart 64 called `baserom.us.z64` into the project folder for asset extraction.
Run the following commands after pulling:
-
-* make -C tools
-* make
+```bash
+make -C tools
+make
+```
## Progress
diff --git a/src/staff_ghosts.c b/src/staff_ghosts.c
index ee276d892..cd65ab00f 100644
--- a/src/staff_ghosts.c
+++ b/src/staff_ghosts.c
@@ -237,7 +237,7 @@ void func_80005310(void) {
}
}
-s32 func_8000546C(void) {
+void func_8000546C(void) {
u32 temp_a0;
u32 temp_a1;
UNUSED u16 unk;
diff --git a/tools/gfxdis_multi.py b/tools/gfxdis_multi.py
index 44d5ff077..d424b662d 100644
--- a/tools/gfxdis_multi.py
+++ b/tools/gfxdis_multi.py
@@ -1,62 +1,62 @@
-#!/usr/bin/env python3
-import os, sys
-
-# ./gfx.py input_file_no_extension startHex
-if (sys.argv[1] == "-h" or sys.argv[1] == ""):
- print("How to use: ")
- print("Create copy of .bin named: filename_copy.bin")
- print("./gfx.py input_file_no_extension startHex iterations symbol_name")
- print("iterations are in 0x10")
- sys.exit(0)
-
-# make sure to copy the .bin file and name it: filename_copy.bin
-
-# copy of bin to prevent read/write conflicts between gfxdis and python
-# Did it this way without testing. Just assumed there would be conflicts
-
-# startHex no 0x
-
-debug = False
-
-execStr = "./gfxdis.f3dex -f "+sys.argv[1]+".bin -a "
-
-start = int(sys.argv[2], 16)
-
-r = open(sys.argv[1]+"_copy.bin", "rb")
-r.seek(start)
-
-bRunIt = True
-
-it = int(sys.argv[3]) * 2 # iterations. *2 for 16 bytes per line
-i = 0
-calls = 0
-
-offset = int(0)
-
-for i in range(it):
- if bRunIt:
- if (len(sys.argv) > 4): # if symbol_name arg exists
- print("Gfx "+sys.argv[4]+str(hex(offset+start).split('x')[-1].upper())+"[] = ")
-
- os.system(execStr+hex(offset+start))
- if debug:
- print((execStr+hex(offset+start)))
- bRunIt = False
- calls += 1
-
- r.seek(start+offset)
- data = r.read(4).hex().upper()
- if data == "B8000000":
- bRunIt = True
- if debug:
- print("Running next: "+hex(offset+start))
-
- if str(data) == "00000000":
- print("Found no DL command");
- break;
-
- offset += 8
-
-print("Program exited at: "+hex(offset+start))
-print("Ran gfxdis "+str(calls)+ " times.")
+#!/usr/bin/env python3
+import os, sys
+
+# ./gfx.py input_file_no_extension startHex
+if (sys.argv[1] == "-h" or sys.argv[1] == ""):
+ print("How to use: ")
+ print("Create copy of .bin named: filename_copy.bin")
+ print("./gfx.py input_file_no_extension startHex iterations symbol_name")
+ print("iterations are in 0x10")
+ sys.exit(0)
+
+# make sure to copy the .bin file and name it: filename_copy.bin
+
+# copy of bin to prevent read/write conflicts between gfxdis and python
+# Did it this way without testing. Just assumed there would be conflicts
+
+# startHex no 0x
+
+debug = False
+
+execStr = "./gfxdis.f3dex -f "+sys.argv[1]+".bin -a "
+
+start = int(sys.argv[2], 16)
+
+r = open(sys.argv[1]+"_copy.bin", "rb")
+r.seek(start)
+
+bRunIt = True
+
+it = int(sys.argv[3]) * 2 # iterations. *2 for 16 bytes per line
+i = 0
+calls = 0
+
+offset = int(0)
+
+for i in range(it):
+ if bRunIt:
+ if (len(sys.argv) > 4): # if symbol_name arg exists
+ print("Gfx "+sys.argv[4]+str(hex(offset+start).split('x')[-1].upper())+"[] = ")
+
+ os.system(execStr+hex(offset+start))
+ if debug:
+ print((execStr+hex(offset+start)))
+ bRunIt = False
+ calls += 1
+
+ r.seek(start+offset)
+ data = r.read(4).hex().upper()
+ if data == "B8000000":
+ bRunIt = True
+ if debug:
+ print("Running next: "+hex(offset+start))
+
+ if str(data) == "00000000":
+ print("Found no DL command");
+ break;
+
+ offset += 8
+
+print("Program exited at: "+hex(offset+start))
+print("Ran gfxdis "+str(calls)+ " times.")
r.close() \ No newline at end of file
diff --git a/tools/ido5.3_recomp/Makefile b/tools/ido5.3_recomp/Makefile
index 3f4e30d57..750be8805 100644
--- a/tools/ido5.3_recomp/Makefile
+++ b/tools/ido5.3_recomp/Makefile
@@ -9,7 +9,34 @@ acpp: OPT_CFLAGS := -O2
RECOMP := recomp
-#ugen_c.c: RECOMP_FLAGS := --conservative
+# determine host OS for flags
+ UNAME_S := $(shell uname -s)
+ UNAME_P := $(shell uname -p)
+
+ifeq ($(UNAME_S),Darwin)
+ HOST_OS := macOS
+else ifeq ($(UNAME_S),Linux)
+ HOST_OS := linux
+else ifeq ($(OS),Windows_NT)
+ HOST_OS := cygwin
+else
+ $(error Unsupported host OS for Makefile)
+endif
+
+CFLAGS := -fno-strict-aliasing -Wno-tautological-compare
+CLIBS := -lm
+
+ifeq ($(HOST_OS),macOS)
+ CFLAGS += -Wno-deprecated-declarations
+ ifeq (,$(findstring arm,$(shell uname -p)))
+ # only add flags on x86_64 macOS
+ CFLAGS += -fno-pie
+ endif
+else
+ CFLAGS += -no-pie
+endif
+
+ugen_c.c: RECOMP_FLAGS := --conservative
all: cc cfe uopt ugen as1 acpp copt ujoin uld umerge usplit err.english.cc
@@ -17,10 +44,10 @@ clean:
$(RM) cc* cfe* uopt* ugen* as1* acpp* copt* ujoin* uld* umerge* usplit* err.english.cc $(RECOMP) libc_impl.o
$(RECOMP): recomp.cpp
- $(CXX) $^ -o $@ -std=c++11 -O2 -Dugen53 -Wno-switch `pkg-config --cflags --libs capstone`
+ $(CXX) $^ -o $@ -std=c++11 -O2 -Wno-switch `pkg-config --cflags --libs capstone`
libc_impl.o: libc_impl.c libc_impl.h
- $(CC) $< -c -fno-strict-aliasing -O2 -DIDO53
+ $(CC) $< -c -O2 -DIDO53 $(CFLAGS)
err.english.cc: $(IRIX_ROOT)/usr/lib/err.english.cc
cp $^ $@
@@ -29,9 +56,10 @@ cc_c.c: $(IRIX_ROOT)/usr/bin/cc $(RECOMP)
./$(RECOMP) $< > $@
%_c.c: $(IRIX_ROOT)/usr/lib/% $(RECOMP)
- ./$(RECOMP) $< > $@
+ ./$(RECOMP) $(RECOMP_FLAGS) $< > $@
%: %_c.c libc_impl.o
- $(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) -fno-strict-aliasing -lm -no-pie
+ $(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) $(CFLAGS) $(CLIBS)
.PHONY: all clean
+.DEFAULT_TARGET := all
diff --git a/tools/ido5.3_recomp/elf.h b/tools/ido5.3_recomp/elf.h
index 91ba5fe20..91ba5fe20 100644..100755
--- a/tools/ido5.3_recomp/elf.h
+++ b/tools/ido5.3_recomp/elf.h
diff --git a/tools/ido5.3_recomp/helpers.h b/tools/ido5.3_recomp/helpers.h
index b2bd23517..b2bd23517 100644..100755
--- a/tools/ido5.3_recomp/helpers.h
+++ b/tools/ido5.3_recomp/helpers.h
diff --git a/tools/ido5.3_recomp/libc_impl.c b/tools/ido5.3_recomp/libc_impl.c
index 7a7d47b9c..76eb34fed 100644..100755
--- a/tools/ido5.3_recomp/libc_impl.c
+++ b/tools/ido5.3_recomp/libc_impl.c
@@ -16,8 +16,10 @@
#ifdef __CYGWIN__
#include <windows.h>
#endif
+
#ifdef __APPLE__
- #include <mach-o/dyld.h>
+#include <mach-o/dyld.h>
+#include <mach/vm_page_size.h>
#endif
#include <sys/mman.h>
@@ -186,21 +188,39 @@ static char bin_dir[PATH_MAX + 1];
#endif
static int g_file_max = 3;
-#ifdef __CYGWIN__
+
+/* Compilation Target/Emulation Host Page Size Determination */
+#if defined(__CYGWIN__) || (defined(__linux__) && defined(__aarch64__))
+#define RUNTIME_PAGESIZE
+/* ARM64 linux can have page sizes of 4kb, 16kb, or 64kb */
+/* Set in main before running the translated code */
static size_t g_Pagesize;
-#endif
+
+#define TRUNC_PAGE(x) ((x) & ~(g_Pagesize - 1))
+#define ROUND_PAGE(x) (TRUNC_PAGE((x) + (g_Pagesize - 1)))
+
+#elif defined(__APPLE__)
+/* https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code */
+#define TRUNC_PAGE(x) (trunc_page((x)))
+#define ROUND_PAGE(x) (round_page((x)))
+
+#else
+/* A fixed 4KB page size for x64 linux (is there anything else?) */
+#define TRUNC_PAGE(x) ((x) & ~(0x1000 - 1))
+#define ROUND_PAGE(x) (TRUNC_PAGE((x) + (0x1000 - 1)))
+#endif /* PageSize Macros */
static uint8_t *memory_map(size_t length)
{
#ifdef __CYGWIN__
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
- g_Pagesize = sysconf(_SC_PAGESIZE);
- assert(((uintptr_t)mem & (g_Pagesize-1)) == 0);
#else
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif
+
+ assert(TRUNC_PAGE((uintptr_t)mem) == (uintptr_t)mem);
if (mem == MAP_FAILED) {
- perror("mmap");
+ perror("mmap (memory_map)");
exit(1);
}
return mem;
@@ -210,20 +230,26 @@ static void memory_allocate(uint8_t *mem, uint32_t start, uint32_t end)
{
assert(start >= MEM_REGION_START);
assert(end <= MEM_REGION_START + MEM_REGION_SIZE);
+ // `start` will be passed to mmap,
+ // so it has to be host aligned in order to keep the guest's pages valid
+ assert(start == TRUNC_PAGE(start));
#ifdef __CYGWIN__
- uintptr_t _start = ((uintptr_t)mem + start) & ~(g_Pagesize-1);
- uintptr_t _end = ((uintptr_t)mem + end + (g_Pagesize-1)) & ~(g_Pagesize-1);
+ uintptr_t _start = TRUNC_PAGE((uintptr_t)mem + start);
+ uintptr_t _end = ROUND_PAGE((uintptr_t)mem + end);
if(mprotect((void*)_start, _end - _start, PROT_READ | PROT_WRITE) < 0) {
- perror("mprotect");
+ perror("mprotect (memory_allocate)");
exit(1);
}
#else
- if (mmap(mem + start, end - start, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
- perror("mmap");
+ void *addr = (void *)TRUNC_PAGE((uintptr_t)mem + start);
+ size_t len = end - start;
+
+ if (mmap(addr, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
+ perror("mmap (memory_allocate)");
exit(1);
}
-#endif
+#endif /* __CYGWIN__ */
}
static void memory_unmap(uint8_t *mem, size_t length)
@@ -273,6 +299,9 @@ int main(int argc, char *argv[]) {
int ret;
find_bin_dir();
+#ifdef RUNTIME_PAGESIZE
+ g_Pagesize = sysconf(_SC_PAGESIZE);
+#endif /* RUNTIME_PAGESIZE */
uint8_t *mem = memory_map(MEM_REGION_SIZE);
mem -= MEM_REGION_START;
@@ -287,7 +316,11 @@ int main(int argc, char *argv[]) {
void mmap_initial_data_range(uint8_t *mem, uint32_t start, uint32_t end) {
custom_libc_data_addr = end;
+#ifdef __APPLE__
+ end += vm_page_size;
+#else
end += 4096;
+#endif /* __APPLE__ */
memory_allocate(mem, start, end);
cur_sbrk = end;
}
@@ -331,8 +364,9 @@ static uint32_t strcpy2(uint8_t *mem, uint32_t dest_addr, uint32_t src_addr) {
uint32_t wrapper_sbrk(uint8_t *mem, int increment) {
uint32_t old = cur_sbrk;
- memory_allocate(mem, old, (old + increment));
- cur_sbrk += increment;
+ size_t alignedInc = ROUND_PAGE(old + increment) - old;
+ memory_allocate(mem, old, old + alignedInc);
+ cur_sbrk += alignedInc;
return old;
}
@@ -434,10 +468,10 @@ uint32_t wrapper_malloc(uint8_t *mem, uint32_t size) {
uint32_t sbrk_request = 0x10000;
if (8 + item_size > sbrk_request) {
sbrk_request = 8 + item_size;
- sbrk_request = (sbrk_request + 0xfff) & ~0xfff;
+ sbrk_request = ROUND_PAGE(sbrk_request);
}
uint32_t left_over = sbrk_request % (8 + item_size);
- sbrk_request -= left_over & ~0xfff;
+ sbrk_request -= left_over & ~(4096 - 1);
mem_allocated += sbrk_request;
++num_sbrks;
node_ptr = wrapper_sbrk(mem, sbrk_request);
@@ -988,6 +1022,30 @@ uint32_t wrapper_strtoul(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr,
return res;
}
+uint64_t wrapper_strtoll(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base) {
+ STRING(nptr)
+ char *endptr = NULL;
+ uint64_t res = strtoll(nptr, endptr_addr != 0 ? &endptr : NULL, base);
+
+ if(endptr != NULL) {
+ MEM_U32(endptr_addr) = nptr_addr + (uint32_t)(endptr - nptr);
+ }
+
+ return res;
+}
+
+uint64_t wrapper_strtoull(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base) {
+ STRING(nptr)
+ char *endptr = NULL;
+ uint64_t res = strtoull(nptr, endptr_addr != 0 ? &endptr : NULL, base);
+
+ if(endptr != NULL) {
+ MEM_U32(endptr_addr) = nptr_addr + (uint32_t)(endptr - nptr);
+ }
+
+ return res;
+}
+
double wrapper_strtod(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr) {
STRING(nptr)
char *endptr = NULL;
@@ -1336,7 +1394,7 @@ int wrapper_ftell(uint8_t *mem, uint32_t fp_addr) {
return res;
}
-int wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
+void wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
(void)wrapper_fseek(mem, fp_addr, 0, SEEK_SET);
struct FILE_irix *f = (struct FILE_irix *)&MEM_U32(fp_addr);
f->_flag &= ~IOERR;
@@ -1787,6 +1845,7 @@ int wrapper_setvbuf(uint8_t *mem, uint32_t fp_addr, uint32_t buf_addr, int mode,
f->_ptr_addr = buf_addr;
f->_cnt = 0;
bufendtab[(fp_addr - IOB_ADDR) / sizeof(struct FILE_irix)] = size;
+ return 0;
}
int wrapper___semgetc(uint8_t *mem, uint32_t fp_addr) {
diff --git a/tools/ido5.3_recomp/libc_impl.h b/tools/ido5.3_recomp/libc_impl.h
index af03e3cfe..4dd53935a 100644..100755
--- a/tools/ido5.3_recomp/libc_impl.h
+++ b/tools/ido5.3_recomp/libc_impl.h
@@ -31,6 +31,8 @@ int wrapper_atol(uint8_t *mem, uint32_t nptr_addr);
double wrapper_atof(uint8_t *mem, uint32_t nptr_addr);
int wrapper_strtol(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
uint32_t wrapper_strtoul(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
+uint64_t wrapper_strtoll(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
+uint64_t wrapper_strtoull(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
double wrapper_strtod(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr);
uint32_t wrapper_strchr(uint8_t *mem, uint32_t str_addr, int c);
uint32_t wrapper_strrchr(uint8_t *mem, uint32_t str_addr, int c);
@@ -49,7 +51,7 @@ uint32_t wrapper_freopen(uint8_t *mem, uint32_t path_addr, uint32_t mode_addr, u
int wrapper_fclose(uint8_t *mem, uint32_t fp_addr);
int wrapper_fflush(uint8_t *mem, uint32_t fp_addr);
int wrapper_ftell(uint8_t *mem, uint32_t fp_addr);
-int wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
+void wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
int wrapper_fseek(uint8_t *mem, uint32_t fp_addr, int offset, int origin);
int wrapper_lseek(uint8_t *mem, int fd, int offset, int whence);
int wrapper_dup(uint8_t *mem, int fd);
diff --git a/tools/ido5.3_recomp/recomp.cpp b/tools/ido5.3_recomp/recomp.cpp
index 45d472ac5..dc991bda3 100644..100755
--- a/tools/ido5.3_recomp/recomp.cpp
+++ b/tools/ido5.3_recomp/recomp.cpp
@@ -3,35 +3,30 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <unistd.h>
+#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
-#if defined(_WIN32) || defined(_WIN64)
-#include <capstone/capstone.h>
-#else
#include <capstone.h>
-#endif
#include "elf.h"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#endif /* _WIN32 && !__CYGWIN__ */
+
#define INSPECT_FUNCTION_POINTERS 0 // set this to 1 when testing a new program, to verify that no false function pointers are found
#ifndef TRACE
#define TRACE 0
#endif
-#ifndef ugen53
-#define ugen53 0
-#endif
-
#define LABELS_64_BIT 1
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
#define u32be(x) (uint32_t)(((x & 0xff) << 24) + ((x & 0xff00) << 8) + ((x & 0xff0000) >> 8) + ((uint32_t)(x) >> 24))
#define u16be(x) (uint16_t)(((x & 0xff) << 8) + ((x & 0xff00) >> 8))
#define read_u32_be(buf) (uint32_t)(((buf)[0] << 24) + ((buf)[1] << 16) + ((buf)[2] << 8) + ((buf)[3]))
@@ -81,6 +76,8 @@ struct Function {
bool referenced_by_function_pointer;
};
+static bool conservative;
+
static csh handle;
static const uint8_t *text_section;
@@ -153,6 +150,8 @@ static const struct {
{"atof", "dp"},
{"strtol", "ippi"},
{"strtoul", "uppi"},
+ {"strtoll", "lppi"},
+ {"strtoull", "jppi"},
{"strtod", "dpp"},
{"strchr", "ppi"},
{"strrchr", "ppi"},
@@ -170,7 +169,7 @@ static const struct {
{"freopen", "pppp"},
{"fclose", "ip"},
{"ftell", "ip"},
- {"rewind", "ip"},
+ {"rewind", "vp"},
{"fseek", "ipii"},
{"lseek", "iiii"},
{"fflush", "ip"},
@@ -286,24 +285,31 @@ static const struct {
static void disassemble(void) {
csh handle;
cs_insn *disasm;
- static size_t disasm_size;
+ size_t disasm_size = 0;
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
- disasm_size = cs_disasm(handle, text_section, text_section_len, text_vaddr, 0, &disasm);
- for (size_t i = 0; i < disasm_size; i++) {
- insns.push_back(Insn());
- Insn& insn = insns.back();
- insn.id = disasm[i].id;
- insn.mnemonic = disasm[i].mnemonic;
- insn.op_str = disasm[i].op_str;
- if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
- insn.op_count = disasm[i].detail->mips.op_count;
- memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
- }
- insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
- insn.linked_insn = -1;
+ insns.reserve(1 + text_section_len / sizeof(uint32_t)); // +1 for dummy instruction
+ while (text_section_len > disasm_size * sizeof(uint32_t)) {
+ size_t disasm_len = disasm_size * sizeof(uint32_t);
+ size_t remaining = text_section_len - disasm_len;
+ size_t current_len = std::min<size_t>(remaining, 1024);
+ size_t cur_disasm_size = cs_disasm(handle, &text_section[disasm_len], current_len, text_vaddr + disasm_len, 0, &disasm);
+ disasm_size += cur_disasm_size;
+ for (size_t i = 0; i < cur_disasm_size; i++) {
+ insns.push_back(Insn());
+ Insn& insn = insns.back();
+ insn.id = disasm[i].id;
+ insn.mnemonic = disasm[i].mnemonic;
+ insn.op_str = disasm[i].op_str;
+ if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
+ insn.op_count = disasm[i].detail->mips.op_count;
+ memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
+ }
+ insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
+ insn.linked_insn = -1;
+ }
+ cs_free(disasm, cur_disasm_size);
}
- cs_free(disasm, disasm_size);
cs_close(&handle);
{
@@ -340,7 +346,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
#define MAX_LOOKBACK 128
// don't attempt to compute addresses for zero offset
// end search after some sane max number of instructions
- int end_search = MAX(0, offset - MAX_LOOKBACK);
+ int end_search = std::max(0, offset - MAX_LOOKBACK);
for (int search = offset - 1; search >= end_search; search--) {
// use an `if` instead of `case` block to allow breaking out of the `for` loop
if (insns[search].id == MIPS_INS_LUI) {
@@ -427,7 +433,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
static void link_with_jalr(int offset)
{
// end search after some sane max number of instructions
- int end_search = MAX(0, offset - MAX_LOOKBACK);
+ int end_search = std::max(0, offset - MAX_LOOKBACK);
for (int search = offset - 1; search >= end_search; search--) {
if (insns[search].operands[0].reg == MIPS_REG_T9) {
if (insns[search].id == MIPS_INS_LW || insns[search].id == MIPS_INS_LI) {
@@ -1640,7 +1646,7 @@ static void dump_instr(int i) {
printf("++cnt; printf(\"pc=0x%08x%s%s\\n\"); ", text_vaddr + i * 4, symbol_name ? " " : "", symbol_name ? symbol_name : "");
}
Insn& insn = insns[i];
- if (!insn.is_jump && !ugen53) {
+ if (!insn.is_jump && !conservative) {
switch (insn_to_type(insn)) {
case TYPE_1S:
if (!(insn.f_livein & map_reg(insn.operands[0].reg))) {
@@ -2160,6 +2166,12 @@ static void dump_instr(int i) {
printf("lo = %s * %s;\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
printf("hi = (uint32_t)((uint64_t)%s * (uint64_t)%s >> 32);\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
break;
+ case MIPS_INS_SQRT:
+ printf("%s = sqrtf(%s);\n", fr(insn.operands[0].reg), fr(insn.operands[1].reg));
+ break;
+ //case MIPS_INS_FSQRT:
+ // printf("%s = sqrtf(%s);\n", wr(insn.operands[0].reg), wr(insn.operands[1].reg));
+ // break;
case MIPS_INS_NEGU:
printf("%s = -%s;\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
break;
@@ -2338,27 +2350,35 @@ static void dump_c(void) {
uint32_t max_addr = 0;
if (data_section_len > 0) {
- min_addr = MIN(min_addr, data_vaddr);
- max_addr = MAX(max_addr, data_vaddr + data_section_len);
+ min_addr = std::min(min_addr, data_vaddr);
+ max_addr = std::max(max_addr, data_vaddr + data_section_len);
}
if (rodata_section_len > 0) {
- min_addr = MIN(min_addr, rodata_vaddr);
- max_addr = MAX(max_addr, rodata_vaddr + rodata_section_len);
+ min_addr = std::min(min_addr, rodata_vaddr);
+ max_addr = std::max(max_addr, rodata_vaddr + rodata_section_len);
}
if (bss_section_len) {
- min_addr = MIN(min_addr, bss_vaddr);
- max_addr = MAX(max_addr, bss_vaddr + bss_section_len);
+ min_addr = std::min(min_addr, bss_vaddr);
+ max_addr = std::max(max_addr, bss_vaddr + bss_section_len);
}
- min_addr = min_addr & ~0xfff;
- max_addr = (max_addr + 0xfff) & ~0xfff;
+ // get pagesize at runtime
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ uint32_t page_size = si.dwPageSize;
+#else
+ uint32_t page_size = sysconf(_SC_PAGESIZE);
+#endif /* _WIN32 && !__CYGWIN__ */
+ min_addr = min_addr & ~(page_size - 1);
+ max_addr = (max_addr + (page_size - 1)) & ~(page_size - 1);
uint32_t stack_bottom = min_addr;
min_addr -= 1 * 1024 * 1024; // 1 MB stack
stack_bottom -= 16; // for main's stack frame
printf("#include \"header.h\"\n");
- if (ugen53) {
+ if (conservative) {
printf("static uint32_t s0, s1, s2, s3, s4, s5, s6, s7, fp;\n");
}
printf("static const uint32_t rodata[] = {\n");
@@ -2486,7 +2506,7 @@ static void dump_c(void) {
dump_function_signature(f, start_addr);
printf(" {\n");
printf("const uint32_t zero = 0;\n");
- if (!ugen53) {
+ if (!conservative) {
printf("uint32_t at = 0, v1 = 0, t0 = 0, t1 = 0, t2 = 0,\n");
printf("t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0,\n");
printf("s6 = 0, s7 = 0, t8 = 0, t9 = 0, gp = 0, fp = 0, s8 = 0, ra = 0;\n");
@@ -2911,8 +2931,14 @@ size_t read_file(const char *file_name, uint8_t **data) {
}
int main(int argc, char *argv[]) {
+ const char *filename = argv[1];
+ if (strcmp(filename, "--conservative") == 0) {
+ conservative = true;
+ filename = argv[2];
+ }
+
uint8_t *data;
- size_t len = read_file(argv[1], &data);
+ size_t len = read_file(filename, &data);
parse_elf(data, len);
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);