From 25a893cdfe8388f494e54c772c6b20a7ca86457f Mon Sep 17 00:00:00 2001 From: Thar0 <17233964+Thar0@users.noreply.github.com> Date: Tue, 21 Jan 2025 00:02:32 +0000 Subject: [PATCH 1/2] GCC Compiler Support --- Makefile | 87 ++++++++-- spec | 3 + src/gcc_fix/missing_gcc_functions.c | 237 ++++++++++++++++++++++++++++ tools/buildtools/mkldscript.c | 158 ++++++------------- 4 files changed, 359 insertions(+), 126 deletions(-) create mode 100644 src/gcc_fix/missing_gcc_functions.c diff --git a/Makefile b/Makefile index 42f5c2fc47d..53cf2f09cab 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,8 @@ COMPARE ?= 1 NON_MATCHING ?= 0 # If ORIG_COMPILER is 1, compile with QEMU_IRIX and the original compiler ORIG_COMPILER ?= 0 +# If COMPILER is "gcc", compile with GCC instead of IDO. +COMPILER ?= ido # if WERROR is 1, pass -Werror to CC_CHECK, so warnings would be treated as errors WERROR ?= 0 # Keep .mdebug section in build @@ -69,9 +71,18 @@ N64_EMULATOR ?= # Ensure the map file being created using English localization export LANG := C +CFLAGS := +CPPFLAGS := + +ifeq ($(COMPILER),gcc) + CPPFLAGS += -DCOMPILER_GCC + NON_MATCHING := 1 + RUN_CC_CHECK := 0 +endif + ifneq ($(NON_MATCHING),0) - CFLAGS := -DNON_MATCHING - CPPFLAGS := -DNON_MATCHING + CFLAGS += -DNON_MATCHING -DAVOID_UB + CPPFLAGS += -DNON_MATCHING -DAVOID_UB COMPARE := 0 endif @@ -92,8 +103,15 @@ ifneq ($(shell type $(MIPS_BINUTILS_PREFIX)ld >/dev/null 2>/dev/null; echo $$?), $(error Unable to find $(MIPS_BINUTILS_PREFIX)ld. Please install or build MIPS binutils, commonly mips-linux-gnu. (or set MIPS_BINUTILS_PREFIX if your MIPS binutils install uses another prefix)) endif -CC := tools/ido_recomp/$(DETECTED_OS)/7.1/cc -CC_OLD := tools/ido_recomp/$(DETECTED_OS)/5.3/cc +# Detect compiler and set variables appropriately. +ifeq ($(COMPILER),gcc) + CC := $(MIPS_BINUTILS_PREFIX)gcc +else ifeq ($(COMPILER),ido) + CC := tools/ido_recomp/$(DETECTED_OS)/7.1/cc + CC_OLD := tools/ido_recomp/$(DETECTED_OS)/5.3/cc +else +$(error Unsupported compiler. Please use either ido or gcc as the COMPILER variable.) +endif # if ORIG_COMPILER is 1, check that either QEMU_IRIX is set or qemu-irix package installed ifeq ($(ORIG_COMPILER),1) @@ -177,18 +195,36 @@ SFCFLAGS := --matching # We can't use the C preprocessor for this because it won't substitute inside string literals. BUILD_DIR_REPLACE := sed -e 's|$$(BUILD_DIR)|$(BUILD_DIR)|g' -CFLAGS += -G 0 -non_shared -Xcpluscomm -nostdinc -Wab,-r4300_mul +GBI_DEFINES := -DF3DEX_GBI_2 -DF3DEX_GBI_PL -DGBI_DOWHILE -WARNINGS := -fullwarn -verbose -woff 624,649,838,712,516,513,596,564,594,807 -ASFLAGS := -march=vr4300 -32 -G0 -GBI_DEFINES := -DF3DEX_GBI_2 -DF3DEX_GBI_PL -DGBI_DOWHILE -COMMON_DEFINES := -D_MIPS_SZLONG=32 $(GBI_DEFINES) -AS_DEFINES := $(COMMON_DEFINES) -DMIPSEB -D_LANGUAGE_ASSEMBLY -D_ULTRA64 -C_DEFINES := $(COMMON_DEFINES) -DLANGUAGE_C -D_LANGUAGE_C -ENDIAN := -EB +ifeq ($(COMPILER),gcc) + # MIPS options + CFLAGS += -G 0 -march=vr4300 -mtune=vr4300 -mfix4300 -mabi=32 -mno-abicalls -mdivide-breaks + # C dialect options + CFLAGS += -nostdinc -fno-PIC -fno-common -ffreestanding -fbuiltin -fno-builtin-sinf -fno-builtin-cosf -funsigned-char -OPTFLAGS := -O2 -g3 -MIPS_VERSION := -mips2 + WARNINGS := $(CC_CHECK_WARNINGS) + ASFLAGS := -march=vr4300 -32 -G0 + COMMON_DEFINES := $(GBI_DEFINES) + AS_DEFINES := $(COMMON_DEFINES) -DMIPSEB -D_LANGUAGE_ASSEMBLY -D_ULTRA64 + C_DEFINES := $(COMMON_DEFINES) -D_LANGUAGE_C + ENDIAN := + + OPTFLAGS := -Os -ffast-math -ftrapping-math -fno-associative-math + MIPS_VERSION := -mips3 +else + CFLAGS += -G 0 -non_shared -Xcpluscomm -nostdinc -Wab,-r4300_mul + + WARNINGS := -fullwarn -verbose -woff 624,649,838,712,516,513,596,564,594,807 + ASFLAGS := -march=vr4300 -32 -G0 + COMMON_DEFINES := -D_MIPS_SZLONG=32 $(GBI_DEFINES) + AS_DEFINES := $(COMMON_DEFINES) -DMIPSEB -D_LANGUAGE_ASSEMBLY -D_ULTRA64 + C_DEFINES := $(COMMON_DEFINES) -D_LANGUAGE_C + ENDIAN := -EB + + OPTFLAGS := -O2 -g3 + MIPS_VERSION := -mips2 +endif # Use relocations and abi fpr names in the dump OBJDUMP_FLAGS := --disassemble --reloc --disassemble-zeroes -Mreg-names=32 @@ -221,7 +257,12 @@ SPEC := spec # create asm directories $(shell mkdir -p asm data extracted) +ifeq ($(COMPILER),ido) +SRC_DIRS := $(shell find src -type d -not -path src/gcc_fix) +else SRC_DIRS := $(shell find src -type d) +endif + ASM_DIRS := $(shell find asm -type d -not -path "asm/non_matchings*") $(shell find data -type d) ifneq ($(wildcard $(EXTRACTED_DIR)/assets/audio),) @@ -369,6 +410,7 @@ $(shell mkdir -p $(foreach dir, \ $(dir:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%))) endif +ifeq ($(COMPILER),ido) # directory flags $(BUILD_DIR)/src/libultra/os/%.o: OPTFLAGS := -O1 $(BUILD_DIR)/src/libultra/voice/%.o: OPTFLAGS := -O2 @@ -417,7 +459,16 @@ $(BUILD_DIR)/src/audio/%.o: CC := $(ASM_PROC) $(ASM_PROC_FLAGS) $(CC) -- $(AS) $ $(BUILD_DIR)/src/overlays/%.o: CC := $(ASM_PROC) $(ASM_PROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- $(BUILD_DIR)/assets/%.o: CC := $(ASM_PROC) $(ASM_PROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- - +else +# Note that if adding additional assets directories for modding reasons these flags must also be used there +$(BUILD_DIR)/assets/%.o: CFLAGS += -fno-zero-initialized-in-bss -fno-toplevel-reorder +$(BUILD_DIR)/src/%.o: CFLAGS += -fexec-charset=euc-jp +$(BUILD_DIR)/src/libultra/libc/ll.o: OPTFLAGS := -Ofast +$(BUILD_DIR)/src/overlays/%.o: CFLAGS += -fno-merge-constants -mno-explicit-relocs -mno-split-addresses + +# Temporary: Hardcoded pointers in assets (specifically object_dmask and object_osn) +$(BUILD_DIR)/assets/%.o: WARNINGS += -Wno-error=int-conversion +endif $(SHIFTJIS_O_FILES): CC_CHECK_WARNINGS += -Wno-multichar -Wno-type-limits -Wno-overflow @@ -550,9 +601,13 @@ $(BUILD_DIR)/%.o: %.s $(CPP) $(CPPFLAGS) $(IINC) $< | $(AS) $(ASFLAGS) $(IINC) $(ENDIAN) -o $@ $(BUILD_DIR)/assets/text/%.o: assets/text/%.c +ifneq ($(COMPILER),gcc) # Preprocess text with modern cpp for varargs macros $(CPP) -undef -D_LANGUAGE_C -D__sgi $(CPPFLAGS) $(IINC) $< -o $(@:.o=.c) - $(CC) -c $(CFLAGS) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $(@:.o=.c) + $(CC) -c $(CFLAGS) $(IINC) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $(@:.o=.c) +else + $(CC) -c $(CFLAGS) $(IINC) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $< +endif $(BUILD_DIR)/assets/%.o: assets/%.c $(CC) -c $(CFLAGS) $(IINC) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $< diff --git a/spec b/spec index 095afc9bac5..f3f4734c56a 100644 --- a/spec +++ b/spec @@ -244,6 +244,9 @@ beginseg include "$(BUILD_DIR)/src/boot/libc/strcpy.o" include "$(BUILD_DIR)/src/boot/libc/memmove.o" include "$(BUILD_DIR)/src/boot/build.o" +#ifdef COMPILER_GCC + include "$(BUILD_DIR)/src/gcc_fix/missing_gcc_functions.o" +#endif endseg beginseg diff --git a/src/gcc_fix/missing_gcc_functions.c b/src/gcc_fix/missing_gcc_functions.c new file mode 100644 index 00000000000..76bf8e9db6e --- /dev/null +++ b/src/gcc_fix/missing_gcc_functions.c @@ -0,0 +1,237 @@ +/* --------------------------------------------------------------------------------*/ +/* Depending on the toolchain used, an appropriate precompiled libgcc library */ +/* may not exist and cannot be linked against. Until we have a better work around, */ +/* necessary gcc functions are hosted here in order to properly compile. */ +/* This file is NOT a part of the original game and only exists to help gcc work. */ +/* --------------------------------------------------------------------------------*/ + +#include "global.h" + +// Self-hosted libc memory functions, gcc assumes these exist even in a freestanding +// environment and there is no way to tell it otherwise. + +int memcmp(const void* s1, const void* s2, size_t n) { + const u8* m1 = s1; + const u8* m2 = s2; + size_t i; + + for (i = 0; i < n; i++) { + if (m1[i] < m2[i]) { + return -1; + } else if (m1[i] > m2[i]) { + return 1; + } + } + + return 0; +} + +// Conversions involving 64-bit integer types required by the O32 MIPS ABI. + +// f32 -> u64, negative values become 0 +u64 __fixunssfdi(f32 a) { + if (a > 0.0f) { + register union { + f64 f; + u64 i; + } m; + + __asm__("cvt.l.s %0, %1" : "=f"(m.f) : "f"(a)); + return m.i; + } + return 0; +} + +// f64 -> u64, negative values become 0 +u64 __fixunsdfdi(f64 a) { + if (a > 0.0) { + register union { + f64 f; + u64 i; + } m; + + __asm__("cvt.l.d %0, %1" : "=f"(m.f) : "f"(a)); + return m.i; + } + return 0; +} + +// f32 -> s64 +s64 __fixsfdi(f32 c) { + register union { + f64 f; + s64 i; + } m; + + __asm__("cvt.l.s %0, %1" : "=f"(m.f) : "f"(c)); + return m.i; +} + +// f64 -> s64 +s64 __fixdfdi(f64 c) { + register union { + f64 f; + s64 i; + } m; + + __asm__("cvt.l.d %0, %1" : "=f"(m.f) : "f"(c)); + return m.i; +} + +// s64 -> f32 +f32 __floatdisf(s64 c) { + register union { + f64 f; + s64 i; + } m; + register f32 v; + + m.i = c; + __asm__("cvt.s.l %0, %1" : "=f"(v) : "f"(m.f)); + return v; +} + +// s64 -> f64 +f64 __floatdidf(s64 c) { + register union { + f64 f; + s64 i; + } m; + register f64 v; + + m.i = c; + __asm__("cvt.d.l %0, %1" : "=f"(v) : "f"(m.f)); + return v; +} + +// u64 -> f32 +f32 __floatundisf(u64 c) { + register union { + f64 f; + u64 i; + } m; + register f32 v; + + m.i = c; + __asm__("cvt.s.l %0, %1" : "=f"(v) : "f"(m.f)); + if ((s64)c < 0) { + // cvt.s.l assumes signed input, adjust output + v += 4294967296.0f; // 2^32 + } + return v; +} + +// u64 -> f64 +f64 __floatundidf(u64 c) { + register union { + f64 f; + u64 i; + } m; + register f64 v; + + m.i = c; + __asm__("cvt.d.l %0, %1" : "=f"(v) : "f"(m.f)); + if ((s64)c < 0) { + // cvt.d.l assumes signed input, adjust output + v += 18446744073709551616.0; // 2^64 + } + return v; +} + +// Compute x^m by binary exponentiation + +f32 __powisf2(f32 x, s32 m) { + u32 n = (m < 0) ? -m : m; + f32 y = (n % 2 != 0) ? x : 1.0f; + + while (n >>= 1) { + x = x * x; + + if (n % 2 != 0) { + y = y * x; + } + } + return (m < 0) ? (1.0f / y) : y; +} + +// Compute division and modulo of 64-bit signed and unsigned integers + +__asm__(" \n\ + .set push \n\ + .set noreorder \n\ + .set gp=64 \n\ + \n\ +.global __umoddi3 \n\ +__umoddi3: \n\ + .type __umoddi3, @function \n\ + .ent __umoddi3 \n\ + sw $a0, 0x0($sp) \n\ + sw $a1, 0x4($sp) \n\ + sw $a2, 0x8($sp) \n\ + sw $a3, 0xC($sp) \n\ + ld $t6, 0($sp) \n\ + ld $t7, 8($sp) \n\ + dremu $v0, $t6, $t7 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __umoddi3 \n\ + .size __umoddi3, . - __umoddi3 \n\ + \n\ +.global __udivdi3 \n\ +__udivdi3: \n\ + .type __udivdi3, @function \n\ + .ent __udivdi3 \n\ + sw $a0, 0x0($sp) \n\ + sw $a1, 0x4($sp) \n\ + sw $a2, 0x8($sp) \n\ + sw $a3, 0xC($sp) \n\ + ld $t6, 0($sp) \n\ + ld $t7, 8($sp) \n\ + ddivu $v0, $t6, $t7 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __udivdi3 \n\ + .size __udivdi3, . - __udivdi3 \n\ + \n\ +.global __moddi3 \n\ +__moddi3: \n\ + .type __moddi3, @function \n\ + .ent __moddi3 \n\ + sw $a0, 0x0($sp) \n\ + sw $a1, 0x4($sp) \n\ + sw $a2, 0x8($sp) \n\ + sw $a3, 0xC($sp) \n\ + ld $t6, 0($sp) \n\ + ld $t7, 8($sp) \n\ + drem $v0, $t6, $t7 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __moddi3 \n\ + .size __moddi3, . - __moddi3 \n\ + \n\ +.global __divdi3 \n\ +__divdi3: \n\ + .type __divdi3, @function \n\ + .ent __divdi3 \n\ + sw $a0, 0x0($sp) \n\ + sw $a1, 0x4($sp) \n\ + sw $a2, 0x8($sp) \n\ + sw $a3, 0xC($sp) \n\ + ld $t6, 0($sp) \n\ + ld $t7, 8($sp) \n\ + ddiv $v0, $t6, $t7 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __divdi3 \n\ + .size __divdi3, . - __divdi3 \n\ + \n\ + .set pop \n\ + \n"); diff --git a/tools/buildtools/mkldscript.c b/tools/buildtools/mkldscript.c index 6a9a066e4fb..fd425047da1 100644 --- a/tools/buildtools/mkldscript.c +++ b/tools/buildtools/mkldscript.c @@ -42,10 +42,6 @@ static void write_ld_script(FILE* fout) { // initialized data (.text, .data, .rodata, .sdata) - // Increment the start of the section - // if (seg->fields & (1 << STMT_increment)) - // fprintf(fout, " . += 0x%08X;\n", seg->increment); - fprintf(fout, " _%sSegmentRomStartTemp = _RomSize;\n" " _%sSegmentRomStart = _%sSegmentRomStartTemp;\n" @@ -53,11 +49,13 @@ static void write_ld_script(FILE* fout) { seg->name, seg->name, seg->name, seg->name); if (seg->fields & (1 << STMT_after)) - fprintf(fout, "_%sSegmentEnd ", seg->after); + fprintf(fout, "(_%sSegmentEnd + %i) & ~ %i ", seg->after, seg->align - 1, seg->align - 1); else if (seg->fields & (1 << STMT_number)) fprintf(fout, "0x%02X000000 ", seg->number); else if (seg->fields & (1 << STMT_address)) fprintf(fout, "0x%08X ", seg->address); + else + fprintf(fout, "ALIGN(0x%X) ", seg->align); // (AT(_RomSize) isn't necessary, but adds useful "load address" lines to the map file) fprintf(fout, @@ -67,9 +65,6 @@ static void write_ld_script(FILE* fout) { " _%sSegmentTextStart = .;\n", seg->name, seg->name); - if (seg->fields & (1 << STMT_align)) - fprintf(fout, " . = ALIGN(0x%X);\n", seg->align); - for (j = 0; j < seg->includesCount; j++) { fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); if (seg->includes[j].linkerPadding != 0) @@ -91,15 +86,6 @@ static void write_ld_script(FILE* fout) { seg->includes[j].fpath); } - /* - for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.rodata)\n", seg->includes[j].fpath); - - for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sdata)\n", seg->includes[j].fpath); - */ - - // fprintf(fout, " . = ALIGN(0x10);\n"); fprintf(fout, " _%sSegmentDataEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, @@ -108,10 +94,6 @@ static void write_ld_script(FILE* fout) { fprintf(fout, " _%sSegmentRoDataStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) { - fprintf(fout, - " %s (.rodata)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); // Compilers other than IDO, such as GCC, produce different sections such as // the ones named directly below. These sections do not contain values that // need relocating, but we need to ensure that the base .rodata section @@ -120,18 +102,11 @@ static void write_ld_script(FILE* fout) { // the beginning of the entire rodata area in order to remain consistent. // Inconsistencies will lead to various .rodata reloc crashes as a result of // either missing relocs or wrong relocs. - fprintf(fout, - " %s (.rodata.str1.4)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); - fprintf(fout, - " %s (.rodata.cst4)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); - fprintf(fout, - " %s (.rodata.cst8)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + fprintf(fout, " %s (.rodata)\n" + " %s (.rodata.str*)\n" + " %s (.rodata.cst*)\n" + " . = ALIGN(0x10);\n", + seg->includes[j].fpath, seg->includes[j].fpath, seg->includes[j].fpath); } fprintf(fout, " _%sSegmentRoDataEnd = .;\n", seg->name); @@ -215,100 +190,63 @@ static void write_ld_script(FILE* fout) { " }\n" " _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n", seg->name, seg->name, seg->name, seg->name, seg->name); - - // Increment the end of the segment - // if (seg->fields & (1 << STMT_increment)) - // fprintf(fout, " . += 0x%08X;\n", seg->increment); - - // fprintf(fout, " ..%s.ovl ADDR(..%s) + SIZEOF(..%s) :\n" - // /*" ..%s.bss :\n"*/ - // " {\n", - // seg->name, seg->name, seg->name); - // fprintf(fout, " _%sSegmentOvlStart = .;\n", seg->name); - - // for (j = 0; j < seg->includesCount; j++) - // fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); - - ////fprintf(fout, " . = ALIGN(0x10);\n"); - - // fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name); - - // fprintf(fout, "\n }\n"); } fputs(" _RomEnd = _RomSize;\n\n", fout); // Debugging sections fputs( - // mdebug debug sections - " .mdebug : { *(.mdebug) }" - "\n" - " .mdebug.abi32 : { *(.mdebug.abi32) }" - "\n" + // mdebug sections + " .pdr : { *(.pdr) }" "\n" + " .mdebug : { *(.mdebug) }" "\n" + " .mdebug.abi32 : { *(.mdebug.abi32) }" "\n" // DWARF debug sections // Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. // DWARF 1 - " .debug 0 : { *(.debug) }" - "\n" - " .line 0 : { *(.line) }" - "\n" + " .debug 0 : { *(.debug) }" "\n" + " .line 0 : { *(.line) }" "\n" // GNU DWARF 1 extensions - " .debug_srcinfo 0 : { *(.debug_srcinfo) }" - "\n" - " .debug_sfnames 0 : { *(.debug_sfnames) }" - "\n" + " .debug_srcinfo 0 : { *(.debug_srcinfo) }" "\n" + " .debug_sfnames 0 : { *(.debug_sfnames) }" "\n" // DWARF 1.1 and DWARF 2 - " .debug_aranges 0 : { *(.debug_aranges) }" - "\n" - " .debug_pubnames 0 : { *(.debug_pubnames) }" - "\n" + " .debug_aranges 0 : { *(.debug_aranges) }" "\n" + " .debug_pubnames 0 : { *(.debug_pubnames) }" "\n" // DWARF 2 - " .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }" - "\n" - " .debug_abbrev 0 : { *(.debug_abbrev) }" - "\n" - " .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }" - "\n" - " .debug_frame 0 : { *(.debug_frame) }" - "\n" - " .debug_str 0 : { *(.debug_str) }" - "\n" - " .debug_loc 0 : { *(.debug_loc) }" - "\n" - " .debug_macinfo 0 : { *(.debug_macinfo) }" - "\n" + " .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }" "\n" + " .debug_abbrev 0 : { *(.debug_abbrev) }" "\n" + " .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }" "\n" + " .debug_frame 0 : { *(.debug_frame) }" "\n" + " .debug_str 0 : { *(.debug_str) }" "\n" + " .debug_loc 0 : { *(.debug_loc) }" "\n" + " .debug_macinfo 0 : { *(.debug_macinfo) }" "\n" // SGI/MIPS DWARF 2 extensions - " .debug_weaknames 0 : { *(.debug_weaknames) }" - "\n" - " .debug_funcnames 0 : { *(.debug_funcnames) }" - "\n" - " .debug_typenames 0 : { *(.debug_typenames) }" - "\n" - " .debug_varnames 0 : { *(.debug_varnames) }" - "\n" + " .debug_weaknames 0 : { *(.debug_weaknames) }" "\n" + " .debug_funcnames 0 : { *(.debug_funcnames) }" "\n" + " .debug_typenames 0 : { *(.debug_typenames) }" "\n" + " .debug_varnames 0 : { *(.debug_varnames) }" "\n" // DWARF 3 - " .debug_pubtypes 0 : { *(.debug_pubtypes) }" - "\n" - " .debug_ranges 0 : { *(.debug_ranges) }" - "\n" - // DWARF Extension - " .debug_macro 0 : { *(.debug_macro) }" - "\n" - " .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" - "\n", - fout); + " .debug_pubtypes 0 : { *(.debug_pubtypes) }" "\n" + " .debug_ranges 0 : { *(.debug_ranges) }" "\n" + // DWARF 5 + " .debug_addr 0 : { *(.debug_addr) }" "\n" + " .debug_line_str 0 : { *(.debug_line_str) }" "\n" + " .debug_loclists 0 : { *(.debug_loclists) }" "\n" + " .debug_macro 0 : { *(.debug_macro) }" "\n" + " .debug_names 0 : { *(.debug_names) }" "\n" + " .debug_rnglists 0 : { *(.debug_rnglists) }" "\n" + " .debug_str_offsets 0 : { *(.debug_str_offsets) }" "\n" + " .debug_sup 0 : { *(.debug_sup) }\n" + // gnu attributes + " .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" "\n", + fout); // Discard all other sections not mentioned above - fputs(" /DISCARD/ :" - "\n" - " {" - "\n" - " *(*);" - "\n" - " }" - "\n", + fputs(" /DISCARD/ :" "\n" + " {" "\n" + " *(*);" "\n" + " }" "\n" + "}\n", fout); - fputs("}\n", fout); } static void usage(const char* execname) { From ad73b761a3a0cc1e84312eb49f463058dba83837 Mon Sep 17 00:00:00 2001 From: Thar0 <17233964+Thar0@users.noreply.github.com> Date: Thu, 23 Jan 2025 20:42:12 +0000 Subject: [PATCH 2/2] Update mkldscript --- tools/buildtools/mkldscript.c | 161 +++++++++++++++------------------- 1 file changed, 71 insertions(+), 90 deletions(-) diff --git a/tools/buildtools/mkldscript.c b/tools/buildtools/mkldscript.c index fd425047da1..5a53ba2cf28 100644 --- a/tools/buildtools/mkldscript.c +++ b/tools/buildtools/mkldscript.c @@ -18,10 +18,11 @@ // With IDO, the padding of sections to an aligned size makes the section start at aligned addresses out of the box, // so the explicit alignment has no further effect. -struct Segment* g_segments; +struct Segment *g_segments; int g_segmentsCount; -static void write_ld_script(FILE* fout) { +static void write_ld_script(FILE *fout) +{ int i; int j; @@ -31,8 +32,9 @@ static void write_ld_script(FILE* fout) { " _RomStart = _RomSize;\n\n", fout); - for (i = 0; i < g_segmentsCount; i++) { - const struct Segment* seg = &g_segments[i]; + for (i = 0; i < g_segmentsCount; i++) + { + const struct Segment *seg = &g_segments[i]; // align start of ROM segment if (seg->fields & (1 << STMT_romalign)) @@ -42,11 +44,9 @@ static void write_ld_script(FILE* fout) { // initialized data (.text, .data, .rodata, .sdata) - fprintf(fout, - " _%sSegmentRomStartTemp = _RomSize;\n" - " _%sSegmentRomStart = _%sSegmentRomStartTemp;\n" - " ..%s ", - seg->name, seg->name, seg->name, seg->name); + fprintf(fout, " _%sSegmentRomStartTemp = _RomSize;\n" + " _%sSegmentRomStart = _%sSegmentRomStartTemp;\n" + " ..%s ", seg->name, seg->name, seg->name, seg->name); if (seg->fields & (1 << STMT_after)) fprintf(fout, "(_%sSegmentEnd + %i) & ~ %i ", seg->after, seg->align - 1, seg->align - 1); @@ -58,14 +58,14 @@ static void write_ld_script(FILE* fout) { fprintf(fout, "ALIGN(0x%X) ", seg->align); // (AT(_RomSize) isn't necessary, but adds useful "load address" lines to the map file) - fprintf(fout, - ": AT(_RomSize)\n {\n" - " _%sSegmentStart = .;\n" - " . = ALIGN(0x10);\n" - " _%sSegmentTextStart = .;\n", - seg->name, seg->name); - - for (j = 0; j < seg->includesCount; j++) { + fprintf(fout, ": AT(_RomSize)\n {\n" + " _%sSegmentStart = .;\n" + " . = ALIGN(0x10);\n" + " _%sSegmentTextStart = .;\n", + seg->name, seg->name); + + for (j = 0; j < seg->includesCount; j++) + { fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); if (seg->includes[j].linkerPadding != 0) fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding); @@ -74,26 +74,24 @@ static void write_ld_script(FILE* fout) { fprintf(fout, " _%sSegmentTextEnd = .;\n", seg->name); - fprintf(fout, " _%sSegmentTextSize = ABSOLUTE( _%sSegmentTextEnd - _%sSegmentTextStart );\n", seg->name, - seg->name, seg->name); + fprintf(fout, " _%sSegmentTextSize = ABSOLUTE( _%sSegmentTextEnd - _%sSegmentTextStart );\n", seg->name, seg->name, seg->name); fprintf(fout, " _%sSegmentDataStart = .;\n", seg->name); - for (j = 0; j < seg->includesCount; j++) { - fprintf(fout, - " %s (.data)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + for (j = 0; j < seg->includesCount; j++) + { + fprintf(fout, " %s (.data)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); } fprintf(fout, " _%sSegmentDataEnd = .;\n", seg->name); - fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, - seg->name, seg->name); + fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, seg->name, seg->name); fprintf(fout, " _%sSegmentRoDataStart = .;\n", seg->name); - for (j = 0; j < seg->includesCount; j++) { + for (j = 0; j < seg->includesCount; j++) + { // Compilers other than IDO, such as GCC, produce different sections such as // the ones named directly below. These sections do not contain values that // need relocating, but we need to ensure that the base .rodata section @@ -103,24 +101,21 @@ static void write_ld_script(FILE* fout) { // Inconsistencies will lead to various .rodata reloc crashes as a result of // either missing relocs or wrong relocs. fprintf(fout, " %s (.rodata)\n" - " %s (.rodata.str*)\n" - " %s (.rodata.cst*)\n" - " . = ALIGN(0x10);\n", + " %s (.rodata.str*)\n" + " %s (.rodata.cst*)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath, seg->includes[j].fpath, seg->includes[j].fpath); } fprintf(fout, " _%sSegmentRoDataEnd = .;\n", seg->name); - fprintf(fout, " _%sSegmentRoDataSize = ABSOLUTE( _%sSegmentRoDataEnd - _%sSegmentRoDataStart );\n", - seg->name, seg->name, seg->name); + fprintf(fout, " _%sSegmentRoDataSize = ABSOLUTE( _%sSegmentRoDataEnd - _%sSegmentRoDataStart );\n", seg->name, seg->name, seg->name); fprintf(fout, " _%sSegmentSDataStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, - " %s (.sdata)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + fprintf(fout, " %s (.sdata)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); fprintf(fout, " _%sSegmentSDataEnd = .;\n", seg->name); @@ -138,58 +133,44 @@ static void write_ld_script(FILE* fout) { fprintf(fout, " _RomSize += ( _%sSegmentOvlEnd - _%sSegmentTextStart );\n", seg->name, seg->name); - fprintf(fout, - " _%sSegmentRomEndTemp = _RomSize;\n" - "_%sSegmentRomEnd = _%sSegmentRomEndTemp;\n\n", - seg->name, seg->name, seg->name); + fprintf(fout, " _%sSegmentRomEndTemp = _RomSize;\n" + "_%sSegmentRomEnd = _%sSegmentRomEndTemp;\n\n", + seg->name, seg->name, seg->name); // align end of ROM segment if (seg->fields & (1 << STMT_romalign)) fprintf(fout, " _RomSize = (_RomSize + %i) & ~ %i;\n", seg->romalign - 1, seg->romalign - 1); // uninitialized data (.sbss, .scommon, .bss, COMMON) - fprintf(fout, - " ..%s.bss ADDR(..%s) + SIZEOF(..%s) (NOLOAD) :\n" - /*" ..%s.bss :\n"*/ - " {\n" - " . = ALIGN(0x10);\n" - " _%sSegmentBssStart = .;\n", - seg->name, seg->name, seg->name, seg->name); - - if (seg->fields & (1 << STMT_align)) - fprintf(fout, " . = ALIGN(0x%X);\n", seg->align); + fprintf(fout, " ..%s.bss ADDR(..%s) + SIZEOF(..%s) (NOLOAD) :\n" + /*" ..%s.bss :\n"*/ + " {\n" + " . = ALIGN(0x10);\n" + " _%sSegmentBssStart = .;\n", + seg->name, seg->name, seg->name, seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, - " %s (.sbss)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + fprintf(fout, " %s (.sbss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, - " %s (.scommon)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + fprintf(fout, " %s (.scommon)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, - " %s (.bss)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); + fprintf(fout, " %s (.bss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, - " %s (COMMON)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath); - - fprintf(fout, - " . = ALIGN(0x10);\n" - " _%sSegmentBssEnd = .;\n" - " _%sSegmentEnd = .;\n" - " }\n" - " _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n", - seg->name, seg->name, seg->name, seg->name, seg->name); + fprintf(fout, " %s (COMMON)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + + fprintf(fout, " . = ALIGN(0x10);\n" + " _%sSegmentBssEnd = .;\n" + " _%sSegmentEnd = .;\n" + " }\n" + " _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n", + seg->name, seg->name, seg->name, seg->name, seg->name); } fputs(" _RomEnd = _RomSize;\n\n", fout); @@ -237,33 +218,33 @@ static void write_ld_script(FILE* fout) { " .debug_str_offsets 0 : { *(.debug_str_offsets) }" "\n" " .debug_sup 0 : { *(.debug_sup) }\n" // gnu attributes - " .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" "\n", - fout); + " .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" "\n", fout); // Discard all other sections not mentioned above fputs(" /DISCARD/ :" "\n" " {" "\n" " *(*);" "\n" - " }" "\n" - "}\n", - fout); + " }" "\n", fout); + fputs("}\n", fout); } -static void usage(const char* execname) { - fprintf(stderr, - "Nintendo 64 linker script generation tool v0.03\n" - "usage: %s SPEC_FILE LD_SCRIPT\n" - "SPEC_FILE file describing the organization of object files into segments\n" - "LD_SCRIPT filename of output linker script\n", - execname); +static void usage(const char *execname) +{ + fprintf(stderr, "Nintendo 64 linker script generation tool v0.03\n" + "usage: %s SPEC_FILE LD_SCRIPT\n" + "SPEC_FILE file describing the organization of object files into segments\n" + "LD_SCRIPT filename of output linker script\n", + execname); } -int main(int argc, char** argv) { - FILE* ldout; - void* spec; +int main(int argc, char **argv) +{ + FILE *ldout; + void *spec; size_t size; - if (argc != 3) { + if (argc != 3) + { usage(argv[0]); return 1; }