commit 1b11e9dca9efcdb09fd2917b96b240e43c8ec91d
parent a84e4ca4303eb3dcad5cf34ca83c2f119019ef1e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 22 Apr 2026 11:17:23 -0700
Vendor AArch64 catm hex2 source
Diffstat:
3 files changed, 148 insertions(+), 12 deletions(-)
diff --git a/bootstrap.sh b/bootstrap.sh
@@ -17,7 +17,7 @@
# 0) hex0-seed + hex0_<A>.hex0 -> hex0
# 1) hex0 + hex1_<A>.hex0 -> hex1
# 2) hex1 + hex2_<A>.hex1 -> hex2-0
-# 2b) (hex1|hex2-0) + catm_<A>.(hex1|hex2) -> catm (arch-specific)
+# 2b) hex2-0 + catm_<A>.hex2 -> catm
# 3a) catm : ELF header + M0_<A>.hex2 -> M0.hex2
# 3b) hex2-0 : M0.hex2 -> M0
#
@@ -29,12 +29,11 @@ set -eu
ARCH=$1
OUT=$2
-# Map lispcc's lowercase ARCH to stage0-posix's dir name and the two files
-# whose extensions differ across arches (catm's source + assembler).
+# Map lispcc's lowercase ARCH to stage0-posix's dir name.
case "$ARCH" in
- aarch64) A=AArch64 ; CATM_SRC=catm_AArch64.hex1 ; CATM_ASM=hex1 ;;
- amd64) A=AMD64 ; CATM_SRC=catm_AMD64.hex2 ; CATM_ASM=hex2-0 ;;
- riscv64) A=riscv64 ; CATM_SRC=catm_riscv64.hex2 ; CATM_ASM=hex2-0 ;;
+ aarch64) A=AArch64 ;;
+ amd64) A=AMD64 ;;
+ riscv64) A=riscv64 ;;
*) echo "bootstrap.sh: unsupported arch '$ARCH'" >&2 ; exit 1 ;;
esac
@@ -65,6 +64,6 @@ fi
"$OUT"/hex0 "$S"/"$A"/hex1_"$A".hex0 "$OUT"/hex1
"$OUT"/hex1 "$S"/"$A"/hex2_"$A".hex1 "$OUT"/hex2-0
-"$OUT"/"$CATM_ASM" "$S"/"$A"/"$CATM_SRC" "$OUT"/catm
+"$OUT"/hex2-0 "$S"/"$A"/catm_"$A".hex2 "$OUT"/catm
"$OUT"/catm "$OUT"/M0.hex2 "$S"/"$A"/ELF-"$ARCH".hex2 "$S"/"$A"/M0_"$A".hex2
"$OUT"/hex2-0 "$OUT"/M0.hex2 "$OUT"/M0
diff --git a/populate-upstream.sh b/populate-upstream.sh
@@ -9,7 +9,7 @@
# $A/hex0_$A.hex0
# $A/hex1_$A.hex0
# $A/hex2_$A.hex1
-# $A/catm_$A.(hex1|hex2) extension differs across arches
+# $A/catm_$A.hex2 vendored in src/ for AArch64, mirrored from upstream elsewhere
# $A/M0_$A.hex2
# $A/ELF-<arch>.hex2 used by both bootstrap.sh (M0.hex2 link) and
# the Makefile's final program link
@@ -29,9 +29,9 @@ fi
for A in AArch64 AMD64 riscv64; do
case "$A" in
- AArch64) arch=aarch64 ; CATM=catm_AArch64.hex1 ;;
- AMD64) arch=amd64 ; CATM=catm_AMD64.hex2 ;;
- riscv64) arch=riscv64 ; CATM=catm_riscv64.hex2 ;;
+ AArch64) arch=aarch64 ;;
+ AMD64) arch=amd64 ;;
+ riscv64) arch=riscv64 ;;
esac
mkdir -p "$OUT/bootstrap-seeds/POSIX/$A" "$OUT/$A"
@@ -40,7 +40,11 @@ for A in AArch64 AMD64 riscv64; do
cp "$S/$A/hex0_$A.hex0" "$OUT/$A/"
cp "$S/$A/hex1_$A.hex0" "$OUT/$A/"
cp "$S/$A/hex2_$A.hex1" "$OUT/$A/"
- cp "$S/$A/$CATM" "$OUT/$A/"
+ if [ "$A" = AArch64 ]; then
+ cp src/catm_AArch64.hex2 "$OUT/$A/"
+ else
+ cp "$S/$A/catm_$A.hex2" "$OUT/$A/"
+ fi
cp "$S/$A/M0_$A.hex2" "$OUT/$A/"
cp "$S/$A/ELF-$arch.hex2" "$OUT/$A/"
done
diff --git a/src/catm_AArch64.hex2 b/src/catm_AArch64.hex2
@@ -0,0 +1,133 @@
+## Copyright (C) 2019 Jeremiah Orians
+## Copyright (C) 2020 Sanne Wouda
+## This file is part of stage0.
+##
+## stage0 is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## stage0 is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with stage0. If not, see <http://www.gnu.org/licenses/>.
+
+
+ # Register usage:
+ # X15 => OUTPUT
+ # X14 => Buffer
+ # X13 => INPUT
+
+
+## ELF Header
+
+:ELF_base
+
+7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number
+
+02 # e_ident[EI_CLASS] Indicating 64 bit
+01 # e_ident[EI_DATA] Indicating little endianness
+01 # e_ident[EI_VERSION] Indicating original elf
+
+03 # e_ident[EI_OSABI] Set at 3 because FreeBSD is strict
+00 # e_ident[EI_ABIVERSION] See above
+
+00 00 00 00 00 00 00 # e_ident[EI_PAD]
+02 00 # e_type Indicating Executable
+B7 00 # e_machine Indicating AArch64
+01 00 00 00 # e_version Indicating original elf
+
+&ELF_text 00 00 00 00 # e_entry Address of the entry point
+%ELF_program_headers>ELF_base 00 00 00 00 # e_phoff Address of program header table
+00 00 00 00 00 00 00 00 # e_shoff Address of section header table
+
+00 00 00 00 # e_flags
+40 00 # e_ehsize Indicating our 64 Byte header
+
+38 00 # e_phentsize size of a program header table
+01 00 # e_phnum number of entries in program table
+
+00 00 # e_shentsize size of a section header table
+00 00 # e_shnum number of entries in section table
+
+00 00 # e_shstrndx index of the section names
+
+:ELF_program_headers
+:ELF_program_header__text
+01 00 00 00 # ph_type: PT-LOAD = 1
+07 00 00 00 # ph_flags: PF-X|PF-W|PF-R = 7
+00 00 00 00 00 00 00 00 # ph_offset
+&ELF_base 00 00 00 00 # ph_vaddr
+&ELF_base 00 00 00 00 # ph_physaddr
+%ELF_end>ELF_base 00 00 00 00 # ph_filesz
+%ELF_end>ELF_base 00 00 00 00 # ph_memsz
+01 00 00 00 00 00 00 00 # ph_align
+
+:ELF_text
+
+# Where the ELF Header is going to hit
+# Simply jump to _start
+# Our main function
+:_start
+ e10f41f8 ; LDR_X1_[SP,16]_WB # Get the actual output name
+ 600c8092 ; SET_X0_TO_FCNTL_H_AT_FDCWD # AT_FDCWD, relative to current working directory
+ 224880d2 ; SET_X2_TO_577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC
+ 033080d2 ; SET_X3_TO_384 # Prepare file as RW for owner only (600 in octal)
+ 080780d2 ; SET_X8_TO_SYS_OPENAT # The syscall number for openat(), aarch64 has no open()
+ 010000d4 ; SYSCALL # Now open that file
+ ef0300aa ; SET_X15_FROM_X0 # Preserve the file pointer we were given
+
+ c81a80d2 ; SET_X8_TO_SYS_BRK # the Syscall # for SYS_BRK
+ 000080d2 ; SET_X0_TO_0 # Get current brk
+ 010000d4 ; SYSCALL # Let the kernel do the work
+ ee0300aa ; SET_X14_FROM_X0 # Set our malloc pointer
+
+ c81a80d2 ; SET_X8_TO_SYS_BRK # the Syscall # for SYS_BRK
+ e0030eaa ; SET_X0_FROM_X14 # Using current pointer
+ 00004491 ; ADD_X0_X0_0x100000 # Allocate 1MB
+ 010000d4 ; SYSCALL # Let the kernel do the work
+
+ e4030091 ; SET_X4_FROM_SP
+:core
+ 818c40f8 ; LDR_X1_[X4,8]_WB # Get the actual input name
+ 3f0000f1 ; CMP_X1_TO_0 # Check for null string
+ 41000054 ; SKIP_INST_NE # Hit null be done
+ ^~done 14 ; ^~done FBRANCH
+
+ 600c8092 ; SET_X0_TO_FCNTL_H_AT_FDCWD # AT_FDCWD, relative to current working directory
+ 020080d2 ; SET_X2_TO_0 # prepare read_only
+ 030080d2 ; SET_X3_TO_0 # prevent any interactions
+ 080780d2 ; SET_X8_TO_SYS_OPENAT # The syscall number for openat(), aarch64 has no open()
+ 010000d4 ; SYSCALL # Open file!
+ ed0300aa ; SET_X13_FROM_X0 # Protect INPUT
+:keep
+ 0202a0d2 ; SET_X2_TO_0x100000 # set the size of chars we want
+ e1030eaa ; SET_X1_FROM_X14 # Where to put it
+ e0030daa ; SET_X0_FROM_X13 # Where are we reading from
+ e80780d2 ; SET_X8_TO_SYS_READ # the syscall number for read
+ 010000d4 ; SYSCALL # call the Kernel
+
+ e20300aa ; SET_X2_FROM_X0 # Number of bytes to write
+ e1030eaa ; SET_X1_FROM_X14 # What we are writing
+ e0030faa ; SET_X0_FROM_X15 # Write to target file
+ 080880d2 ; SET_X8_TO_SYS_WRITE # the syscall number for write
+ 010000d4 ; SYSCALL # call the Kernel
+
+ 1f0044f1 ; CMP_X0_TO_0x100000 # Check if buffer was fully used
+ 41000054 ; SKIP_INST_NE # Keep looping if was full
+ ^~keep 17 ; ^~keep RBRANCH
+ ^~core 17 ; ^~core RBRANCH # Otherwise move to next file
+
+:done
+ # program completed Successfully
+ 000080d2 ; SET_X0_TO_0 # All is well
+ a80b80d2 ; SET_X8_TO_SYS_EXIT # put the exit syscall number in x8
+ 010000d4 ; SYSCALL # Call it a good day
+
+:ELF_data
+:ELF_end
+:ELF_sym
+:ELF_str