summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTharo <17233964+Thar0@users.noreply.github.com>2025-02-02 21:15:55 +0000
committerGitHub <noreply@github.com>2025-02-02 13:15:55 -0800
commit84a89c8f461886a0bba1d645b3cb9344316fab09 (patch)
tree676e84833bb128ed79a81e45f4b643d58e9c27b3
parent89b7bb0d71f6ef0c9614088ac921820cd539e273 (diff)
GCC Compiler Support (#1791)
* GCC Compiler Support * Update mkldscript
-rw-r--r--Makefile87
-rw-r--r--spec3
-rw-r--r--src/gcc_fix/missing_gcc_functions.c237
-rw-r--r--tools/buildtools/mkldscript.c301
4 files changed, 421 insertions, 207 deletions
diff --git a/Makefile b/Makefile
index a153953d0..cf6c7a229 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
@@ -551,9 +602,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 814df763c..2aaf3b438 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 000000000..76bf8e9db
--- /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 6a9a066e4..5a53ba2cf 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,35 +44,28 @@ 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"
- " ..%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 ", 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,
- ": AT(_RomSize)\n {\n"
- " _%sSegmentStart = .;\n"
- " . = ALIGN(0x10);\n"
- " _%sSegmentTextStart = .;\n",
- seg->name, seg->name);
-
- if (seg->fields & (1 << STMT_align))
- fprintf(fout, " . = ALIGN(0x%X);\n", seg->align);
+ fprintf(fout, ": AT(_RomSize)\n {\n"
+ " _%sSegmentStart = .;\n"
+ " . = ALIGN(0x10);\n"
+ " _%sSegmentTextStart = .;\n",
+ seg->name, seg->name);
- for (j = 0; j < seg->includesCount; j++) {
+ 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);
@@ -79,39 +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);
}
- /*
- 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,
- 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++) {
- fprintf(fout,
- " %s (.rodata)\n"
- " . = ALIGN(0x10);\n",
- seg->includes[j].fpath);
+ 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
@@ -120,32 +100,22 @@ 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);
- 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);
@@ -163,169 +133,118 @@ 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);
-
- // 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");
+ 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);
// 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",
- fout);
+ fputs(" /DISCARD/ :" "\n"
+ " {" "\n"
+ " *(*);" "\n"
+ " }" "\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;
}