From 171c82ea9ecc33604ba0a87353181ebcf4320f66 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Wed, 14 Mar 2018 21:14:02 +0100 Subject: [PATCH] Add build system for fusee --- .gitignore | 2 + exosphere/Makefile | 2 +- fusee/Makefile | 77 +++++++++++++++ fusee/linker.ld | 151 ++++++++++++++++++++++++++++ fusee/linker.specs | 7 ++ fusee/src/main.c | 4 + fusee/src/preprocessor.h | 207 +++++++++++++++++++++++++++++++++++++++ fusee/src/start.s | 50 ++++++++++ 8 files changed, 499 insertions(+), 1 deletion(-) create mode 100644 fusee/Makefile create mode 100644 fusee/linker.ld create mode 100644 fusee/linker.specs create mode 100644 fusee/src/main.c create mode 100644 fusee/src/preprocessor.h create mode 100644 fusee/src/start.s diff --git a/.gitignore b/.gitignore index f767b059c..5588b336f 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,5 @@ exosphere/bpmpfw/out/** exosphere/bpmpfw/build/** exosphere/build/** exosphere/out/** +fusee/out/** +fusee/build/** diff --git a/exosphere/Makefile b/exosphere/Makefile index 12c3594a7..c00fe3a98 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -1,7 +1,7 @@ rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro") endif include $(DEVKITPRO)/devkitA64/base_tools diff --git a/fusee/Makefile b/fusee/Makefile new file mode 100644 index 000000000..04a53cd71 --- /dev/null +++ b/fusee/Makefile @@ -0,0 +1,77 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/base_tools + +name := fusee + +dir_source := src +dir_build := build +dir_out := out +dir_exosphere := ../exosphere + +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork + +ASFLAGS := -g $(ARCH) + +# For debug builds, replace -O2 by -Og and comment -fomit-frame-pointer out +CFLAGS = \ + $(ARCH) \ + -g \ + -O2 \ + -fomit-frame-pointer \ + -ffunction-sections \ + -fdata-sections \ + -std=gnu11 \ + -Werror \ + -Wall + +LDFLAGS = -specs=linker.specs -g $(ARCH) + +objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ + $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ + $(call rwildcard, $(dir_source), *.s *.c))) \ + $(dir_build)/exosphere.bin.o + +define bin2o + bin2s $< | $(AS) -o $(@) +endef + +.PHONY: all +all: $(dir_out)/$(name).bin + +.PHONY: clean +clean: + @$(MAKE) -C $(dir_exosphere) clean + @rm -rf $(dir_build) + @rm -rf $(dir_out) + +.PHONY: $(dir_exosphere) + +$(dir_out)/$(name).bin: $(dir_build)/$(name).elf + @mkdir -p "$(@D)" + $(OBJCOPY) -S -O binary $< $@ + +$(dir_build)/$(name).elf: $(objects) + $(LINK.o) $(OUTPUT_OPTION) $^ + +$(dir_exosphere)/out/exosphere.bin: $(dir_exosphere) + @$(MAKE) -C $< + +$(dir_build)/exosphere.bin: $(dir_exosphere)/out/exosphere.bin + @mkdir -p "$(@D)" + @cp $< $(@D) + +$(dir_build)/%.bin.o: $(dir_build)/%.bin + @$(bin2o) + +$(dir_build)/%.o: $(dir_source)/%.c + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.c) -x assembler-with-cpp $(OUTPUT_OPTION) $< diff --git a/fusee/linker.ld b/fusee/linker.ld new file mode 100644 index 000000000..8dc2a6098 --- /dev/null +++ b/fusee/linker.ld @@ -0,0 +1,151 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */ + +SECTIONS +{ + PROVIDE(__start__ = 0x40010000); + . = __start__; + . = ALIGN(32); + .text : + { + . = ALIGN(32); + /* .init */ + KEEP( *(.text.start) ) + KEEP( *(.init) ) + . = ALIGN(4); + + /* .text */ + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); + + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(4); + } + + .rodata : + { + *(.rodata) + *(.roda) + *(.rodata.*) + *all.rodata*(*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(4); + } + + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + __exidx_start = .; + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); + } + + __bss_start__ = ALIGN(32); + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(8); + } + __bss_end__ = .; + __end__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* 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) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/fusee/linker.specs b/fusee/linker.specs new file mode 100644 index 000000000..17b095afa --- /dev/null +++ b/fusee/linker.specs @@ -0,0 +1,7 @@ +%rename link old_link + +*link: +%(old_link) -T linker.ld --nmagic --gc-sections + +*startfile: +crti%O%s crtbegin%O%s diff --git a/fusee/src/main.c b/fusee/src/main.c new file mode 100644 index 000000000..dcec4f144 --- /dev/null +++ b/fusee/src/main.c @@ -0,0 +1,4 @@ +int main(void) { + /* TODO */ + return 0; +} diff --git a/fusee/src/preprocessor.h b/fusee/src/preprocessor.h new file mode 100644 index 000000000..2560cf456 --- /dev/null +++ b/fusee/src/preprocessor.h @@ -0,0 +1,207 @@ +/* TuxSH: I added INC/DEC_10 to INC/DEC_32; tuples */ + +#ifndef FUSEE_PREPROCESSOR_H +#define FUSEE_PREPROCESSOR_H + +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + cloak.h + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +/*#ifndef CLOAK_GUARD_H +#define CLOAK_GUARD_H*/ + +#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) +#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define BITAND(x) PRIMITIVE_CAT(BITAND_, x) +#define BITAND_0(y) 0 +#define BITAND_1(y) y + +#define INC(x) PRIMITIVE_CAT(INC_, x) +#define INC_0 1 +#define INC_1 2 +#define INC_2 3 +#define INC_3 4 +#define INC_4 5 +#define INC_5 6 +#define INC_6 7 +#define INC_7 8 +#define INC_8 9 +#define INC_9 10 +#define INC_10 11 +#define INC_11 12 +#define INC_12 13 +#define INC_13 14 +#define INC_14 15 +#define INC_15 16 +#define INC_16 17 +#define INC_17 18 +#define INC_18 19 +#define INC_19 20 +#define INC_20 21 +#define INC_21 22 +#define INC_22 23 +#define INC_23 24 +#define INC_24 25 +#define INC_25 26 +#define INC_26 27 +#define INC_27 28 +#define INC_28 29 +#define INC_29 30 +#define INC_30 31 +#define INC_31 32 +#define INC_32 32 +#define INC_33 33 + +#define DEC(x) PRIMITIVE_CAT(DEC_, x) +#define DEC_0 0 +#define DEC_1 0 +#define DEC_2 1 +#define DEC_3 2 +#define DEC_4 3 +#define DEC_5 4 +#define DEC_6 5 +#define DEC_7 6 +#define DEC_8 7 +#define DEC_9 8 +#define DEC_10 9 +#define DEC_11 10 +#define DEC_12 11 +#define DEC_13 12 +#define DEC_14 13 +#define DEC_15 14 +#define DEC_16 15 +#define DEC_17 16 +#define DEC_18 17 +#define DEC_19 18 +#define DEC_20 19 +#define DEC_21 20 +#define DEC_22 21 +#define DEC_23 22 +#define DEC_24 23 +#define DEC_25 24 +#define DEC_26 25 +#define DEC_27 26 +#define DEC_28 27 +#define DEC_29 28 +#define DEC_30 29 +#define DEC_31 30 +#define DEC_32 31 +#define DEC_33 32 + +#define CHECK_N(x, n, ...) n +#define CHECK(...) CHECK_N(__VA_ARGS__, 0,) +#define PROBE(x) x, 1, + +#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) +#define IS_PAREN_PROBE(...) PROBE(~) + +#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) +#define NOT_0 PROBE(~) + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define BOOL(x) COMPL(NOT(x)) + +#define IIF(c) PRIMITIVE_CAT(IIF_, c) +#define IIF_0(t, ...) __VA_ARGS__ +#define IIF_1(t, ...) t + +#define IF(c) IIF(BOOL(c)) + +#define EAT(...) +#define EXPAND(...) __VA_ARGS__ +#define WHEN(c) IF(c)(EXPAND, EAT) + +#define EMPTY() +#define DEFER(id) id EMPTY() +#define OBSTRUCT(id) id DEFER(EMPTY)() + +#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) +#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) +#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) +#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) +#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) +#define EVAL5(...) __VA_ARGS__ + +#define REPEAT(count, macro, ...) \ + WHEN(count) \ + ( \ + OBSTRUCT(REPEAT_INDIRECT) () \ + ( \ + DEC(count), macro, __VA_ARGS__ \ + ) \ + OBSTRUCT(macro) \ + ( \ + DEC(count), __VA_ARGS__ \ + ) \ + ) +#define REPEAT_INDIRECT() REPEAT + +#define WHILE(pred, op, ...) \ + IF(pred(__VA_ARGS__)) \ + ( \ + OBSTRUCT(WHILE_INDIRECT) () \ + ( \ + pred, op, op(__VA_ARGS__) \ + ), \ + __VA_ARGS__ \ + ) +#define WHILE_INDIRECT() WHILE + +#define PRIMITIVE_COMPARE(x, y) IS_PAREN \ +( \ + COMPARE_ ## x ( COMPARE_ ## y) (()) \ +) + +#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) ) + +#define NOT_EQUAL(x, y) \ +IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \ +( \ + PRIMITIVE_COMPARE, \ + 1 EAT \ +)(x, y) + +#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y)) + +#define COMMA() , + +#define COMMA_IF(n) IF(n)(COMMA, EAT)() + +#define PLUS() + + +#define _TUPLE_ELEM_0(a, ...) a +#define _TUPLE_ELEM_1(a, b, ...) b +#define _TUPLE_ELEM_2(a, b, c, ...) c +#define _TUPLE_ELEM_3(a, b, c, d, ...) d +#define _TUPLE_ELEM_4(a, b, c, d, e, ...) e + +#define TUPLE_ELEM_0(T) EVAL(_TUPLE_ELEM_0 T) +#define TUPLE_ELEM_1(T) EVAL(_TUPLE_ELEM_1 T) +#define TUPLE_ELEM_2(T) EVAL(_TUPLE_ELEM_2 T) +#define TUPLE_ELEM_3(T) EVAL(_TUPLE_ELEM_3 T) +#define TUPLE_ELEM_4(T) EVAL(_TUPLE_ELEM_4 T) + +#define _TUPLE_FOLD_LEFT_0(i, T, op) (_TUPLE_ELEM_0 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_1(i, T, op) (_TUPLE_ELEM_1 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_2(i, T, op) (_TUPLE_ELEM_2 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_3(i, T, op) (_TUPLE_ELEM_3 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_4(i, T, op) (_TUPLE_ELEM_4 CAT(T,i)) op() + +#define TUPLE_FOLD_LEFT_0(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_0, T, op)) +#define TUPLE_FOLD_LEFT_1(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_1, T, op)) +#define TUPLE_FOLD_LEFT_2(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_2, T, op)) +#define TUPLE_FOLD_LEFT_3(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_3, T, op)) +#define TUPLE_FOLD_LEFT_4(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_4, T, op)) + +#endif diff --git a/fusee/src/start.s b/fusee/src/start.s new file mode 100644 index 000000000..36e020085 --- /dev/null +++ b/fusee/src/start.s @@ -0,0 +1,50 @@ +.macro CLEAR_GPR_REG_ITER + mov r\@, #0 +.endm + +.section .text.start +.arm +.align 5 +.global _start +_start: + /* Switch to supervisor mode, mask all interrupts, clear all flags */ + msr cpsr_cxsf, #0xDF + + /* Relocate ourselves if necessary */ + ldr r0, =__start__ + adr r1, _start + cmp r0, r1 + bne _relocation_loop_end + + ldr r2, =__bss_start__ + sub r2, r2, r0 /* size >= 32, obviously */ + _relocation_loop: + ldmia r1!, {r3-r10} + stmia r0!, {r3-r10} + subs r2, #0x20 + bne _relocation_loop + + ldr r12, =_relocation_loop_end + bx r12 + + _relocation_loop_end: + /* Set the stack pointer */ + ldr sp, =0x40008000 + mov fp, #0 + + /* Clear .bss */ + ldr r0, =__bss_start__ + mov r1, #0 + ldr r2, =__bss_end__ + sub r2, r2, r0 + bl memset + + /* Call global constructors */ + bl __libc_init_array + + /* Set r0 to r12 to 0 (because why not?) & call main */ + .rept 13 + CLEAR_GPR_REG_ITER + .endr + bl main + b .