From 59f3c95a1832099da19977f65ba15edc96452470 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Tue, 14 Jan 2025 19:04:41 +0100 Subject: [PATCH] Compile rust-mega-drive using rustc_codegen_gcc This still generates binaries for 68020 + stdlib functions are stubbed out. --- 0001-Hackery.patch | 110 +++++++++++ 0001-Patches-to-run-with-gcc.patch | 308 +++++++++++++++++++++++++++++ Dockerfile | 64 ++++++ 3 files changed, 482 insertions(+) create mode 100644 0001-Hackery.patch create mode 100644 0001-Patches-to-run-with-gcc.patch create mode 100644 Dockerfile diff --git a/0001-Hackery.patch b/0001-Hackery.patch new file mode 100644 index 0000000..ccf3ad2 --- /dev/null +++ b/0001-Hackery.patch @@ -0,0 +1,110 @@ +From e2b431ff117b9e58c4a487f6021da5aa54cbbd77 Mon Sep 17 00:00:00 2001 +From: User +Date: Tue, 14 Jan 2025 17:23:55 +0000 +Subject: [PATCH] Hackery + +--- + build_system/build_sysroot/Cargo.toml | 11 +++++++---- + src/base.rs | 1 + + src/gcc_util.rs | 3 +-- + src/lib.rs | 1 + + target_specs/m68k-unknown-linux-gnu.json | 10 +++++----- + 5 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/build_system/build_sysroot/Cargo.toml b/build_system/build_sysroot/Cargo.toml +index 2415207..8076c81 100644 +--- a/build_system/build_sysroot/Cargo.toml ++++ b/build_system/build_sysroot/Cargo.toml +@@ -5,12 +5,14 @@ version = "0.0.0" + resolver = "2" + + [dependencies] ++# rustc-dep-of-std? + core = { path = "./sysroot_src/library/core" } +-compiler_builtins = "0.1" ++compiler_builtins = { version = "0.1" } ++#compiler_builtins = { version = "0.1", features = ['rustc-dep-of-std'] } + alloc = { path = "./sysroot_src/library/alloc" } +-std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } +-test = { path = "./sysroot_src/library/test" } +-proc_macro = { path = "./sysroot_src/library/proc_macro" } ++# std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } ++# test = { path = "./sysroot_src/library/test" } ++# proc_macro = { path = "./sysroot_src/library/proc_macro" } + + [patch.crates-io] + rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } +@@ -35,4 +37,5 @@ codegen-units = 10000 + + [profile.release] + debug = "limited" ++panic = "abort" + #lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed. +diff --git a/src/base.rs b/src/base.rs +index c9701fb..97c28f1 100644 +--- a/src/base.rs ++++ b/src/base.rs +@@ -156,6 +156,7 @@ pub fn compile_codegen_unit( + let target_cpu = gcc_util::target_cpu(tcx.sess); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); ++ context.add_command_line_option("-mcpu=68000"); + } + + if tcx +diff --git a/src/gcc_util.rs b/src/gcc_util.rs +index 560aff4..39b1889 100644 +--- a/src/gcc_util.rs ++++ b/src/gcc_util.rs +@@ -242,8 +242,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> + + fn arch_to_gcc(name: &str) -> &str { + match name { +- "M68020" => "68020", +- _ => name, ++ _ => "68000", + } + } + +diff --git a/src/lib.rs b/src/lib.rs +index f6ad0c7..e19dbcf 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -196,6 +196,7 @@ impl CodegenBackend for GccCodegenBackend { + let context = Context::default(); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); ++ context.add_command_line_option("-mcpu=68000"); + } + + **self.target_info.info.lock().expect("lock") = context.get_target_info(); +diff --git a/target_specs/m68k-unknown-linux-gnu.json b/target_specs/m68k-unknown-linux-gnu.json +index 95ea061..026dc98 100644 +--- a/target_specs/m68k-unknown-linux-gnu.json ++++ b/target_specs/m68k-unknown-linux-gnu.json +@@ -1,17 +1,17 @@ + { + "arch": "m68k", +- "cpu": "M68020", ++ "cpu": "M68000", + "crt-static-respected": true, + "data-layout": "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16", +- "dynamic-linking": true, ++ "dynamic-linking": false, + "env": "gnu", + "has-rpath": true, +- "has-thread-local": true, ++ "has-thread-local": false, + "llvm-target": "m68k-unknown-linux-gnu", + "max-atomic-width": 32, + "os": "linux", +- "position-independent-executables": true, +- "relro-level": "full", ++ "position-independent-executables": false, ++ "relro-level": "none", + "supported-split-debuginfo": [ + "packed", + "unpacked", +-- +2.34.1 + diff --git a/0001-Patches-to-run-with-gcc.patch b/0001-Patches-to-run-with-gcc.patch new file mode 100644 index 0000000..882ffcf --- /dev/null +++ b/0001-Patches-to-run-with-gcc.patch @@ -0,0 +1,308 @@ +From c0bc79d64a1e11d8008f24f063e65b144f3a6067 Mon Sep 17 00:00:00 2001 +From: User +Date: Tue, 14 Jan 2025 08:29:08 +0000 +Subject: [PATCH] Patches to run with gcc + +--- + examples/megapong/entry.S | 154 ++++++++++++++--------------- + examples/megapong/stdlib.S | 21 ++++ + libs/megadrive-graphics/src/lib.rs | 2 +- + libs/megadrive-util/src/panic.rs | 5 +- + share/ldscripts/megadrive.x | 8 +- + 6 files changed, 119 insertions(+), 85 deletions(-) + create mode 100644 examples/megapong/compile.sh + create mode 100644 examples/megapong/stdlib.S + +diff --git a/examples/megapong/entry.S b/examples/megapong/entry.S +index e5343ed..2543eb0 100644 +--- a/examples/megapong/entry.S ++++ b/examples/megapong/entry.S +@@ -6,91 +6,91 @@ + .set HBLANK, _int + .set VBLANK, _vblank + +-.long 0x0 ; Initial Stack Address +-.long START ; Start of program Code +-.long INT ; Bus error +-.long INT ; Address error +-.long INT ; Illegal instruction +-.long INT ; Division by zero +-.long INT ; CHK exception +-.long INT ; TRAPV exception +-.long INT ; Privilage violation +-.long INT ; TRACE exception +-.long INT ; Line-A emulator +-.long INT ; Line-F emulator +-.long INT ; Reserved (NOT USED) +-.long INT ; Co-processor protocol violation +-.long INT ; Format error +-.long INT ; Uninitialized Interrupt +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Spurious Interrupt +-.long INT ; IRQ Level 1 +-.long INT ; IRQ Level 2 (EXT Interrupt) +-.long INT ; IRQ Level 3 +-.long HBLANK ; IRQ Level 4 (VDP Horizontal Interrupt) +-.long INT ; IRQ Level 5 +-.long VBLANK ; IRQ Level 6 (VDP Vertical Interrupt) +-.long INT ; IRQ Level 7 +-.long INT ; TRAP #00 Exception +-.long INT ; TRAP #01 Exception +-.long INT ; TRAP #02 Exception +-.long INT ; TRAP #03 Exception +-.long INT ; TRAP #04 Exception +-.long INT ; TRAP #05 Exception +-.long INT ; TRAP #06 Exception +-.long INT ; TRAP #07 Exception +-.long INT ; TRAP #08 Exception +-.long INT ; TRAP #09 Exception +-.long INT ; TRAP #10 Exception +-.long INT ; TRAP #11 Exception +-.long INT ; TRAP #12 Exception +-.long INT ; TRAP #13 Exception +-.long INT ; TRAP #14 Exception +-.long INT ; TRAP #15 Exception +-.long INT ; (FP) Branch or Set on Unordered Condition +-.long INT ; (FP) Inexact Result +-.long INT ; (FP) Divide by Zero +-.long INT ; (FP) Underflow +-.long INT ; (FP) Operand Error +-.long INT ; (FP) Overflow +-.long INT ; (FP) Signaling NAN +-.long INT ; (FP) Unimplemented Data Type +-.long INT ; MMU Configuration Error +-.long INT ; MMU Illegal Operation Error +-.long INT ; MMU Access Violation Error +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) +-.long INT ; Reserved (NOT USED) ++.long 0x0 ++.long START ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long HBLANK ++.long INT ++.long VBLANK ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT ++.long INT + +-.ascii "SEGA MEGADRIVE " ; SEGA must be the first four chars for TMSS ++.ascii "SEGA MEGADRIVE " + .ascii "(C)2021.JAN " +-.ascii "TESTPROJECT " ; export name ++.ascii "TESTPROJECT " + .ascii " " + .ascii " " +-.ascii "TESTPROJECT " ; domestic (Japanese) name ++.ascii "TESTPROJECT " + .ascii " " + .ascii " " + .ascii "GM MK-0000 -01" +-.short 0x0000 ; checksum - not needed ++.short 0x0000 + .ascii "J6 " +-.long 0x00000000, 0x0007ffff ; ROM start, end +-.long 0x00ff0000, 0x00ffffff ; RAM start, end +-.ascii " " ; no SRAM ++.long 0x00000000, 0x0007ffff ++.long 0x00ff0000, 0x00ffffff ++.ascii " " + .ascii " " + .ascii " " +-.ascii " " ; memo ++.ascii " " + .ascii " " + .ascii " " +-.ascii "F " ; enable any hardware configuration ++.ascii "F " + + .global vblank + _vblank: +@@ -100,14 +100,14 @@ _vblank: + .global _start + .global main + _start: +- move.l #_stack_top, sp +- move.w #0x2500, sr ++ move.l #_stack_top, %sp ++ move.w #0x2500, %sr + jsr _init_runtime +- bra #main ++ bra main + + .global abort + abort: +- bra #abort ++ bra abort + + _int: + rte +diff --git a/examples/megapong/stdlib.S b/examples/megapong/stdlib.S +new file mode 100644 +index 0000000..b614ed5 +--- /dev/null ++++ b/examples/megapong/stdlib.S +@@ -0,0 +1,25 @@ ++.text ++ ++.global memcpy ++memcpy: ++ rts ++ ++.global memcmp ++memcmp: ++ rts ++ ++.global memset ++memset: ++ rts ++ ++.global _Unwind_Resume ++_Unwind_Resume: ++ rts ++ ++.global rust_eh_personality ++rust_eh_personality: ++ rts ++ ++.global __mulsi3 ++__mulsi3: ++ rts +diff --git a/libs/megadrive-graphics/src/lib.rs b/libs/megadrive-graphics/src/lib.rs +index d7aa284..5e7f929 100644 +--- a/libs/megadrive-graphics/src/lib.rs ++++ b/libs/megadrive-graphics/src/lib.rs +@@ -5,7 +5,7 @@ use core::mem::MaybeUninit; + use megadrive_sys::vdp::{Sprite, VDP}; + + pub mod default_ascii { +- include!(concat!(env!("OUT_DIR"), "/default_ascii.rs")); ++ // include!(concat!(env!("OUT_DIR"), "/default_ascii.rs")); + } + mod font; + +diff --git a/libs/megadrive-util/src/panic.rs b/libs/megadrive-util/src/panic.rs +index 8564bbd..edb1663 100644 +--- a/libs/megadrive-util/src/panic.rs ++++ b/libs/megadrive-util/src/panic.rs +@@ -3,7 +3,6 @@ use core::ptr::read_volatile; + + use megadrive_sys::vdp::VDP; + use megadrive_graphics::Renderer; +-use megadrive_graphics::default_ascii::DEFAULT_FONT_1X1; + + static mut NEW_FRAME: u16 = 0; + +@@ -19,7 +18,7 @@ fn panic(_info: &PanicInfo) -> ! { + vdp.enable_display(true); + + // Initialize the default font tiles +- DEFAULT_FONT_1X1.load(&mut vdp); ++ // DEFAULT_FONT_1X1.load(&mut vdp); + + let resolution = vdp.resolution(); + let half_screen_width = (resolution.0 >> 1) as i16; +@@ -36,7 +35,7 @@ fn panic(_info: &PanicInfo) -> ! { + // let mut panic_text: &str = &_info.payload().downcast_ref::<&str>().unwrap(); + let panic_text= "Panic!"; + +- DEFAULT_FONT_1X1.blit_text(&mut renderer, panic_text, x_off as u16, y_off as u16); ++ // DEFAULT_FONT_1X1.blit_text(&mut renderer, panic_text, x_off as u16, y_off as u16); + renderer.render(&mut vdp); + // vsync + wait_for_vblank(); +diff --git a/share/ldscripts/megadrive.x b/share/ldscripts/megadrive.x +index 95e1cf3..c6d91ae 100644 +--- a/share/ldscripts/megadrive.x ++++ b/share/ldscripts/megadrive.x +@@ -22,19 +22,19 @@ SECTIONS + + .data : + { +- ALIGN(4); ++ . = ALIGN(4); + _data_start = .; + *(.data); +- ALIGN(4); ++ . = ALIGN(4); + _data_end = .; + } > RAM AT > ROM + + .bss (NOLOAD) : + { +- ALIGN(4); ++ . = ALIGN(4); + _bss_start = .; + *(.bss); +- ALIGN(4); ++ . = ALIGN(4); + _bss_end = .; + } > RAM AT > ROM + +-- +2.34.1 + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c913740 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +FROM ubuntu:22.04 + +RUN apt-get -y update && apt-get install -y --no-install-recommends git curl ca-certificates build-essential sudo + +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" +# Not sure why/if this is needed +ENV LIBRARY_PATH=/usr/lib +# Make sure we compile to the right target +ENV OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu + +# Clone source repo +RUN git clone https://github.com/rust-lang/rustc_codegen_gcc.git + +# Setup rustup +RUN cd rustc_codegen_gcc && rustup show + +# Install gcc +RUN curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb +RUN dpkg -i gcc-m68k-13.deb + +# Set gcc path in the rustc_codegen project +RUN echo 'gcc-path = "/usr/lib"' > rustc_codegen_gcc/config.toml + +# Git config is needed for ./y.sh prepare +RUN git config --global user.email "user@example.com" +RUN git config --global user.name "User" + +# Apply hacky patch +COPY 0001-Hackery.patch /tmp/0001-Hackery.patch +RUN cd rustc_codegen_gcc && patch -p1 < /tmp/0001-Hackery.patch && rm /tmp/0001-Hackery.patch + +# Build project +# See https://github.com/rust-lang/rustc_codegen_gcc/blob/master/doc/tips.md#how-to-build-a-cross-compiling-libgccjit +RUN cd rustc_codegen_gcc && ./y.sh prepare --cross +RUN cd rustc_codegen_gcc && ./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target /rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json + +# Build "megapong" PoC +RUN git clone https://github.com/ricky26/rust-mega-drive.git +COPY 0001-Patches-to-run-with-gcc.patch /tmp/rust-mega-drive.patch +RUN cd rust-mega-drive && patch -p1