boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit e77067e3f9ee54059d2c6e972d3265b0088f0cc9
parent fba0661c4e9928254ae9b1a9c2eb4d243a3af53e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun,  3 May 2026 16:53:48 -0700

update to run hex2pp.P1, rm 00-hello which used old hex2

Diffstat:
MMakefile | 11++++-------
MP1/P1-aarch64.M1 | 45+++++++++++++++++++++++++++++++++++++--------
MP1/P1-amd64.M1 | 45+++++++++++++++++++++++++++++++++++++--------
MP1/P1-riscv64.M1 | 45+++++++++++++++++++++++++++++++++++++--------
Mhex2pp/hex2pp.P1 | 2093++++++++++++++++++++++++++++++-------------------------------------------------
Mscripts/boot-run-tests.sh | 23+++++------------------
Dtests/P1/00-hello.P1 | 27---------------------------
Dtests/P1/00-hello.expected | 1-
8 files changed, 904 insertions(+), 1386 deletions(-)

diff --git a/Makefile b/Makefile @@ -210,10 +210,8 @@ P1PP_BUILD_DEPS = scripts/boot-build-p1pp.sh \ vendor/seed/%/ELF.hex2 \ P1/P1-%.M1pp P1/P1.M1pp P1/P1pp.P1pp -# M1pp is built from its self-hosted .P1 source via the seed M0+hex2-0 -# chain (boot-build-p1.sh). hex2pp.P1 hasn't yet caught up to the new -# string-emission contract (bare "..." emits decoded bytes; %bytes is -# gone), so hex2pp is still compiled from hex2pp.c via alpine-gcc. +# M1pp and hex2pp are both built from their self-hosted .P1 sources via +# the seed M0+hex2-0 chain (boot-build-p1.sh). ALPINE_GCC_IMAGES := $(foreach a,$(ALL_ARCHES),build/$(a)/.image-alpine-gcc) $(ALPINE_GCC_IMAGES): build/%/.image-alpine-gcc: scripts/Containerfile.alpine-gcc @@ -231,9 +229,8 @@ ALPINE_GCC = podman run --rm --pull=never --platform $(PLATFORM_$(1)) \ $(M1PP_BINS): build/%/M1pp/M1pp: M1pp/M1pp.P1 $(P1_BUILD_DEPS) $(call PODMAN,$*) sh scripts/boot-build-p1.sh M1pp/M1pp.P1 $@ -$(HEX2PP_BINS): build/%/hex2pp/hex2pp: hex2pp/hex2pp.c build/%/.image-alpine-gcc - mkdir -p $(@D) - $(call ALPINE_GCC,$*) cc -O2 -std=c99 -static hex2pp/hex2pp.c -o $@ +$(HEX2PP_BINS): build/%/hex2pp/hex2pp: hex2pp/hex2pp.P1 $(P1_BUILD_DEPS) + $(call PODMAN,$*) sh scripts/boot-build-p1.sh hex2pp/hex2pp.P1 $@ $(SCHEME1_BINS): build/%/scheme1/scheme1: $(SCHEME1_SRC) $(P1PP_BUILD_DEPS) $(call PODMAN,$*) sh scripts/boot-build-p1pp.sh $@ $(SCHEME1_SRC) diff --git a/P1/P1-aarch64.M1 b/P1/P1-aarch64.M1 @@ -23,7 +23,6 @@ DEFINE la_br 5100001802000014 ## ---- Moves DEFINE mov_a0,a1 E00301AA -DEFINE mov_a0,a2 E00302AA DEFINE mov_a0,a3 E00303AA DEFINE mov_a0,t0 E00309AA DEFINE mov_a0,t1 E0030AAA @@ -36,10 +35,12 @@ DEFINE mov_a2,t0 E20309AA DEFINE mov_a2,t1 E2030AAA DEFINE mov_t0,a0 E90300AA DEFINE mov_t1,a0 EA0300AA +DEFINE mov_t1,t0 EA0309AA DEFINE mov_t2,a0 EB0300AA DEFINE mov_t2,t1 EB030AAA ## ---- Register Arithmetic +DEFINE add_a0,a0,a1 0000018B DEFINE add_a0,a0,a2 0000028B DEFINE add_a0,a0,a3 0000038B DEFINE add_a0,a0,t0 0000098B @@ -56,7 +57,7 @@ DEFINE add_a1,a1,a0 2100008B DEFINE add_a1,a1,a2 2100028B DEFINE add_a1,a1,a3 2100038B DEFINE add_a1,a1,t0 2100098B -DEFINE add_a1,a1,t1 21000A8B +DEFINE add_a1,a1,t2 21000B8B DEFINE add_a1,a2,t0 4100098B DEFINE add_a1,a3,a1 6100018B DEFINE add_a1,t0,a0 2101008B @@ -66,11 +67,10 @@ DEFINE add_a1,t2,t1 61010A8B DEFINE add_a2,a1,a3 2200038B DEFINE add_a2,a1,t0 2200098B DEFINE add_a2,a2,a0 4200008B -DEFINE add_a2,a2,a1 4200018B DEFINE add_a2,a2,a3 4200038B DEFINE add_a2,a2,t0 4200098B DEFINE add_a2,a2,t1 42000A8B -DEFINE add_a2,a2,t2 42000B8B +DEFINE add_a2,a3,a1 6200018B DEFINE add_a2,a3,a2 6200028B DEFINE add_a2,t0,t1 22010A8B DEFINE add_a2,t2,a0 6201008B @@ -78,6 +78,7 @@ DEFINE add_a2,t2,a2 6201028B DEFINE add_a3,a0,a2 0300028B DEFINE add_a3,a1,t1 23000A8B DEFINE add_a3,a1,t2 23000B8B +DEFINE add_a3,a3,a0 6300008B DEFINE add_a3,a3,a1 6300018B DEFINE add_a3,a3,a2 6300028B DEFINE add_a3,a3,t0 6300098B @@ -108,16 +109,18 @@ DEFINE add_t2,t1,t2 4B010B8B DEFINE add_t2,t2,a0 6B01008B DEFINE add_t2,t2,a3 6B01038B DEFINE add_t2,t2,t1 6B010A8B +DEFINE sub_a0,a0,a1 000001CB DEFINE sub_a0,a0,t1 00000ACB +DEFINE sub_a0,a1,a0 200000CB DEFINE sub_a0,a1,t2 20000BCB DEFINE sub_a0,a3,a0 600000CB DEFINE sub_a1,t0,a0 210100CB DEFINE sub_a2,a1,a0 220000CB -DEFINE sub_a2,a1,a3 220003CB DEFINE sub_a2,a2,a2 420002CB DEFINE sub_a2,a2,t0 420009CB DEFINE sub_a2,t0,t1 22010ACB DEFINE sub_a2,t2,a3 620103CB +DEFINE sub_a3,a1,a2 230002CB DEFINE sub_a3,a3,a2 630002CB DEFINE sub_a3,t0,a2 230102CB DEFINE sub_a3,t0,a3 230103CB @@ -128,6 +131,8 @@ DEFINE sub_a3,t2,t1 63010ACB DEFINE sub_t0,a1,a2 290002CB DEFINE sub_t0,t0,a1 290101CB DEFINE sub_t0,t0,t1 29010ACB +DEFINE sub_t0,t1,t0 490109CB +DEFINE sub_t1,t1,t0 4A0109CB DEFINE sub_t2,t1,t0 4B0109CB DEFINE and_a3,a3,a2 6300028A DEFINE or_a0,a0,a2 000002AA @@ -137,13 +142,18 @@ DEFINE xor_a3,a3,a2 630002CA DEFINE shl_a2,a2,a3 4220C39A DEFINE sar_a2,a2,a3 4228C39A DEFINE mul_a0,a0,a3 007C039B +DEFINE mul_a0,a0,t0 007C099B DEFINE mul_a0,t1,t2 407D0B9B +DEFINE mul_a2,a2,t1 427C0A9B DEFINE mul_a3,a3,a2 637C029B DEFINE mul_t0,t0,a1 297D019B +DEFINE mul_t0,t0,t1 297D0A9B DEFINE mul_t2,t0,a2 2B7D029B DEFINE div_a0,a0,a1 000CC19A +DEFINE div_a0,a0,t1 000CCA9A DEFINE div_a2,a2,a3 420CC39A DEFINE rem_a2,a0,a1 100CC19A0282019B +DEFINE rem_a2,a0,t1 100CCA9A02820A9B DEFINE rem_a2,a2,a3 500CC39A028A039B ## ---- Immediate Arithmetic @@ -166,6 +176,7 @@ DEFINE addi_a2,a2,24 42600091 DEFINE addi_a2,a2,48 42C00091 DEFINE addi_a2,t0,1 22050091 DEFINE addi_a2,t2,neg48 62C100D1 +DEFINE addi_a3,a3,neg1 630400D1 DEFINE addi_a3,a3,1 63040091 DEFINE addi_a3,a3,32 63800091 DEFINE addi_a3,t0,32 23810091 @@ -193,8 +204,10 @@ DEFINE addi_t2,t2,1 6B050091 DEFINE addi_t2,t2,7 6B1D0091 DEFINE addi_t2,t2,24 6B610091 DEFINE addi_t2,t2,32 6B810091 +DEFINE andi_a0,a0,255 F01F80D20000108A DEFINE andi_a2,a2,15 F00180D24200108A DEFINE andi_a3,a3,15 F00180D26300108A +DEFINE andi_a3,a3,255 F01F80D26300108A DEFINE andi_a3,t2,255 F01F80D26301108A DEFINE shli_a0,a0,3 00F07DD3 DEFINE shli_a0,a0,4 00EC7CD3 @@ -202,6 +215,7 @@ DEFINE shli_a1,a1,1 21F87FD3 DEFINE shli_a2,t1,3 42F17DD3 DEFINE shli_a3,t0,1 23F97FD3 DEFINE shli_a3,t0,4 23ED7CD3 +DEFINE shli_t0,t0,4 29ED7CD3 DEFINE shli_t1,a2,3 4AF07DD3 DEFINE shli_t2,t0,3 2BF17DD3 DEFINE shri_a2,a3,4 62FC44D3 @@ -265,11 +279,13 @@ DEFINE ld_a3,t1,8 430540F9 DEFINE ld_t0,a0,0 090040F9 DEFINE ld_t0,a0,8 090440F9 DEFINE ld_t0,a0,16 090840F9 +DEFINE ld_t0,a0,24 090C40F9 DEFINE ld_t0,a1,0 290040F9 DEFINE ld_t0,a1,8 290440F9 DEFINE ld_t0,a1,16 290840F9 DEFINE ld_t0,a1,32 291040F9 DEFINE ld_t0,a2,0 490040F9 +DEFINE ld_t0,a3,0 690040F9 DEFINE ld_t0,t0,0 290140F9 DEFINE ld_t0,t2,0 690140F9 DEFINE ld_t0,t2,16 690940F9 @@ -286,6 +302,7 @@ DEFINE ld_t1,a0,24 0A0C40F9 DEFINE ld_t1,a1,0 2A0040F9 DEFINE ld_t1,a1,8 2A0440F9 DEFINE ld_t1,a1,16 2A0840F9 +DEFINE ld_t1,a2,0 4A0040F9 DEFINE ld_t1,a2,8 4A0440F9 DEFINE ld_t1,a2,16 4A0840F9 DEFINE ld_t1,a3,0 6A0040F9 @@ -317,6 +334,7 @@ DEFINE st_a0,a3,8 600400F9 DEFINE st_a0,a3,16 600800F9 DEFINE st_a0,t0,0 200100F9 DEFINE st_a0,t0,8 200500F9 +DEFINE st_a0,t1,0 400100F9 DEFINE st_a0,t2,0 600100F9 DEFINE st_a0,t2,8 600500F9 DEFINE st_a0,t2,16 600900F9 @@ -353,6 +371,7 @@ DEFINE st_a3,a0,0 030000F9 DEFINE st_a3,a1,0 230000F9 DEFINE st_a3,a2,0 430000F9 DEFINE st_a3,t0,24 230D00F9 +DEFINE st_a3,t1,0 430100F9 DEFINE st_a3,t1,8 430500F9 DEFINE st_a3,t2,0 630100F9 DEFINE st_a3,t2,8 630500F9 @@ -365,7 +384,6 @@ DEFINE st_t0,a0,24 090C00F9 DEFINE st_t0,a1,0 290000F9 DEFINE st_t0,a2,0 490000F9 DEFINE st_t0,a3,0 690000F9 -DEFINE st_t0,a3,8 690400F9 DEFINE st_t0,t1,0 490100F9 DEFINE st_t0,t2,0 690100F9 DEFINE st_t0,sp,0 E90B00F9 @@ -390,6 +408,7 @@ DEFINE st_t2,a3,0 6B0000F9 DEFINE st_t2,t0,0 2B0100F9 DEFINE st_t2,t1,0 4B0100F9 DEFINE lb_a0,a0,0 00004039 +DEFINE lb_a0,a2,0 40004039 DEFINE lb_a0,t0,0 20014039 DEFINE lb_a1,a1,0 21004039 DEFINE lb_a1,a3,0 61004039 @@ -401,10 +420,11 @@ DEFINE lb_a3,a0,0 03004039 DEFINE lb_a3,a1,0 23004039 DEFINE lb_a3,a2,0 43004039 DEFINE lb_a3,a3,0 63004039 -DEFINE lb_t0,a3,0 69004039 -DEFINE lb_t0,a3,1 69044039 +DEFINE lb_t0,a0,0 09004039 +DEFINE lb_t0,a0,1 09044039 DEFINE lb_t0,t0,0 29014039 DEFINE lb_t1,t1,0 4A014039 +DEFINE lb_t2,a2,0 4B004039 DEFINE lb_t2,t0,0 2B014039 DEFINE lb_t2,t2,0 6B014039 DEFINE sb_a0,a1,0 20000039 @@ -452,6 +472,7 @@ DEFINE beq_t2,a2 7F0102EB4100005420021FD6 DEFINE beq_t2,a3 7F0103EB4100005420021FD6 DEFINE beq_t2,t1 7F010AEB4100005420021FD6 DEFINE bne_a0,t0 1F0009EB4000005420021FD6 +DEFINE bne_a0,t1 1F000AEB4000005420021FD6 DEFINE bne_a1,a2 3F0002EB4000005420021FD6 DEFINE bne_a1,t0 3F0009EB4000005420021FD6 DEFINE bne_a2,a1 5F0001EB4000005420021FD6 @@ -460,6 +481,8 @@ DEFINE bne_a3,a0 7F0000EB4000005420021FD6 DEFINE bne_a3,a1 7F0001EB4000005420021FD6 DEFINE bne_a3,a2 7F0002EB4000005420021FD6 DEFINE bne_a3,t0 7F0009EB4000005420021FD6 +DEFINE bne_t0,a0 3F0100EB4000005420021FD6 +DEFINE bne_t0,a2 3F0102EB4000005420021FD6 DEFINE bne_t0,t1 3F010AEB4000005420021FD6 DEFINE bne_t0,t2 3F010BEB4000005420021FD6 DEFINE bne_t1,a2 5F0102EB4000005420021FD6 @@ -468,7 +491,9 @@ DEFINE bne_t1,t2 5F010BEB4000005420021FD6 DEFINE bne_t2,a2 7F0102EB4000005420021FD6 DEFINE bne_t2,a3 7F0103EB4000005420021FD6 DEFINE bne_t2,t0 7F0109EB4000005420021FD6 +DEFINE blt_a0,a1 1F0001EB4A00005420021FD6 DEFINE blt_a0,a2 1F0002EB4A00005420021FD6 +DEFINE blt_a0,t1 1F000AEB4A00005420021FD6 DEFINE blt_a1,a0 3F0000EB4A00005420021FD6 DEFINE blt_a1,a2 3F0002EB4A00005420021FD6 DEFINE blt_a1,t0 3F0009EB4A00005420021FD6 @@ -479,7 +504,10 @@ DEFINE blt_a2,t0 5F0009EB4A00005420021FD6 DEFINE blt_a2,t1 5F000AEB4A00005420021FD6 DEFINE blt_a3,a2 7F0002EB4A00005420021FD6 DEFINE blt_a3,t2 7F000BEB4A00005420021FD6 +DEFINE blt_t0,a0 3F0100EB4A00005420021FD6 +DEFINE blt_t0,a2 3F0102EB4A00005420021FD6 DEFINE blt_t0,t1 3F010AEB4A00005420021FD6 +DEFINE blt_t1,a0 5F0100EB4A00005420021FD6 DEFINE blt_t1,a1 5F0101EB4A00005420021FD6 DEFINE blt_t1,t0 5F0109EB4A00005420021FD6 DEFINE blt_t2,a3 7F0103EB4A00005420021FD6 @@ -494,6 +522,7 @@ DEFINE beqz_t2 4B0000B520021FD6 DEFINE bnez_a0 400000B420021FD6 DEFINE bnez_a1 410000B420021FD6 DEFINE bnez_a2 420000B420021FD6 +DEFINE bnez_a3 430000B420021FD6 DEFINE bnez_t0 490000B420021FD6 DEFINE bnez_t1 4A0000B420021FD6 DEFINE bnez_t2 4B0000B420021FD6 diff --git a/P1/P1-amd64.M1 b/P1/P1-amd64.M1 @@ -23,7 +23,6 @@ DEFINE la_br 41BF ## ---- Moves DEFINE mov_a0,a1 4889F7 -DEFINE mov_a0,a2 4889D7 DEFINE mov_a0,a3 4889CF DEFINE mov_a0,t0 4C89D7 DEFINE mov_a0,t1 4C89DF @@ -36,10 +35,12 @@ DEFINE mov_a2,t0 4C89D2 DEFINE mov_a2,t1 4C89DA DEFINE mov_t0,a0 4989FA DEFINE mov_t1,a0 4989FB +DEFINE mov_t1,t0 4D89D3 DEFINE mov_t2,a0 4989F8 DEFINE mov_t2,t1 4D89D8 ## ---- Register Arithmetic +DEFINE add_a0,a0,a1 4889FF4801F7 DEFINE add_a0,a0,a2 4889FF4801D7 DEFINE add_a0,a0,a3 4889FF4801CF DEFINE add_a0,a0,t0 4889FF4C01D7 @@ -56,7 +57,7 @@ DEFINE add_a1,a1,a0 4889F64801FE DEFINE add_a1,a1,a2 4889F64801D6 DEFINE add_a1,a1,a3 4889F64801CE DEFINE add_a1,a1,t0 4889F64C01D6 -DEFINE add_a1,a1,t1 4889F64C01DE +DEFINE add_a1,a1,t2 4889F64C01C6 DEFINE add_a1,a2,t0 4889D64C01D6 DEFINE add_a1,a3,a1 4989F14889CE4C01CE DEFINE add_a1,t0,a0 4C89D64801FE @@ -66,11 +67,10 @@ DEFINE add_a1,t2,t1 4C89C64C01DE DEFINE add_a2,a1,a3 4889F24801CA DEFINE add_a2,a1,t0 4889F24C01D2 DEFINE add_a2,a2,a0 4889D24801FA -DEFINE add_a2,a2,a1 4889D24801F2 DEFINE add_a2,a2,a3 4889D24801CA DEFINE add_a2,a2,t0 4889D24C01D2 DEFINE add_a2,a2,t1 4889D24C01DA -DEFINE add_a2,a2,t2 4889D24C01C2 +DEFINE add_a2,a3,a1 4889CA4801F2 DEFINE add_a2,a3,a2 4989D14889CA4C01CA DEFINE add_a2,t0,t1 4C89D24C01DA DEFINE add_a2,t2,a0 4C89C24801FA @@ -78,6 +78,7 @@ DEFINE add_a2,t2,a2 4989D14C89C24C01CA DEFINE add_a3,a0,a2 4889F94801D1 DEFINE add_a3,a1,t1 4889F14C01D9 DEFINE add_a3,a1,t2 4889F14C01C1 +DEFINE add_a3,a3,a0 4889C94801F9 DEFINE add_a3,a3,a1 4889C94801F1 DEFINE add_a3,a3,a2 4889C94801D1 DEFINE add_a3,a3,t0 4889C94C01D1 @@ -108,16 +109,18 @@ DEFINE add_t2,t1,t2 4D89C14D89D84D01C8 DEFINE add_t2,t2,a0 4D89C04901F8 DEFINE add_t2,t2,a3 4D89C04901C8 DEFINE add_t2,t2,t1 4D89C04D01D8 +DEFINE sub_a0,a0,a1 4889FF4829F7 DEFINE sub_a0,a0,t1 4889FF4C29DF +DEFINE sub_a0,a1,a0 4989F94889F74C29CF DEFINE sub_a0,a1,t2 4889F74C29C7 DEFINE sub_a0,a3,a0 4989F94889CF4C29CF DEFINE sub_a1,t0,a0 4C89D64829FE DEFINE sub_a2,a1,a0 4889F24829FA -DEFINE sub_a2,a1,a3 4889F24829CA DEFINE sub_a2,a2,a2 4989D14889D24C29CA DEFINE sub_a2,a2,t0 4889D24C29D2 DEFINE sub_a2,t0,t1 4C89D24C29DA DEFINE sub_a2,t2,a3 4C89C24829CA +DEFINE sub_a3,a1,a2 4889F14829D1 DEFINE sub_a3,a3,a2 4889C94829D1 DEFINE sub_a3,t0,a2 4C89D14829D1 DEFINE sub_a3,t0,a3 4989C94C89D14C29C9 @@ -128,6 +131,8 @@ DEFINE sub_a3,t2,t1 4C89C14C29D9 DEFINE sub_t0,a1,a2 4989F24929D2 DEFINE sub_t0,t0,a1 4D89D24929F2 DEFINE sub_t0,t0,t1 4D89D24D29DA +DEFINE sub_t0,t1,t0 4D89D14D89DA4D29CA +DEFINE sub_t1,t1,t0 4D89DB4D29D3 DEFINE sub_t2,t1,t0 4D89D84D29D0 DEFINE and_a3,a3,a2 4889C94821D1 DEFINE or_a0,a0,a2 4889FF4809D7 @@ -137,13 +142,18 @@ DEFINE xor_a3,a3,a2 4889C94831D1 DEFINE shl_a2,a2,a3 4889CD4989D14889C949D3E14889E94C89CA DEFINE sar_a2,a2,a3 4889CD4989D14889C949D3F94889E94C89CA DEFINE mul_a0,a0,a3 4889FF480FAFF9 +DEFINE mul_a0,a0,t0 4889FF490FAFFA DEFINE mul_a0,t1,t2 4C89DF490FAFF8 +DEFINE mul_a2,a2,t1 4889D2490FAFD3 DEFINE mul_a3,a3,a2 4889C9480FAFCA DEFINE mul_t0,t0,a1 4D89D24C0FAFD6 +DEFINE mul_t0,t0,t1 4D89D24D0FAFD3 DEFINE mul_t2,t0,a2 4D89D04C0FAFC2 DEFINE div_a0,a0,a1 4889D54989F14889F8489949F7F94889EA4889C7 +DEFINE div_a0,a0,t1 4889D54D89D94889F8489949F7F94889EA4889C7 DEFINE div_a2,a2,a3 4889D54989C94889D0489949F7F94889EA4889C2 DEFINE rem_a2,a0,a1 4889D54989F14889F8489949F7F94889D04889EA4889C2 +DEFINE rem_a2,a0,t1 4889D54D89D94889F8489949F7F94889D04889EA4889C2 DEFINE rem_a2,a2,a3 4889D54989C94889D0489949F7F94889D04889EA4889C2 ## ---- Immediate Arithmetic @@ -166,6 +176,7 @@ DEFINE addi_a2,a2,24 4889D24883C218 DEFINE addi_a2,a2,48 4889D24883C230 DEFINE addi_a2,t0,1 4C89D24883C201 DEFINE addi_a2,t2,neg48 4C89C24883C2D0 +DEFINE addi_a3,a3,neg1 4889C94883C1FF DEFINE addi_a3,a3,1 4889C94883C101 DEFINE addi_a3,a3,32 4889C94883C120 DEFINE addi_a3,t0,32 4C89D14883C120 @@ -193,8 +204,10 @@ DEFINE addi_t2,t2,1 4D89C04983C001 DEFINE addi_t2,t2,7 4D89C04983C007 DEFINE addi_t2,t2,24 4D89C04983C018 DEFINE addi_t2,t2,32 4D89C04983C020 +DEFINE andi_a0,a0,255 4889FF4881E7FF000000 DEFINE andi_a2,a2,15 4889D24883E20F DEFINE andi_a3,a3,15 4889C94883E10F +DEFINE andi_a3,a3,255 4889C94881E1FF000000 DEFINE andi_a3,t2,255 4C89C14881E1FF000000 DEFINE shli_a0,a0,3 4889FF48C1E703 DEFINE shli_a0,a0,4 4889FF48C1E704 @@ -202,6 +215,7 @@ DEFINE shli_a1,a1,1 4889F648C1E601 DEFINE shli_a2,t1,3 4C89DA48C1E203 DEFINE shli_a3,t0,1 4C89D148C1E101 DEFINE shli_a3,t0,4 4C89D148C1E104 +DEFINE shli_t0,t0,4 4D89D249C1E204 DEFINE shli_t1,a2,3 4989D349C1E303 DEFINE shli_t2,t0,3 4D89D049C1E003 DEFINE shri_a2,a3,4 4889CA48C1EA04 @@ -265,11 +279,13 @@ DEFINE ld_a3,t1,8 498B4B08 DEFINE ld_t0,a0,0 4C8B5700 DEFINE ld_t0,a0,8 4C8B5708 DEFINE ld_t0,a0,16 4C8B5710 +DEFINE ld_t0,a0,24 4C8B5718 DEFINE ld_t0,a1,0 4C8B5600 DEFINE ld_t0,a1,8 4C8B5608 DEFINE ld_t0,a1,16 4C8B5610 DEFINE ld_t0,a1,32 4C8B5620 DEFINE ld_t0,a2,0 4C8B5200 +DEFINE ld_t0,a3,0 4C8B5100 DEFINE ld_t0,t0,0 4D8B5200 DEFINE ld_t0,t2,0 4D8B5000 DEFINE ld_t0,t2,16 4D8B5010 @@ -286,6 +302,7 @@ DEFINE ld_t1,a0,24 4C8B5F18 DEFINE ld_t1,a1,0 4C8B5E00 DEFINE ld_t1,a1,8 4C8B5E08 DEFINE ld_t1,a1,16 4C8B5E10 +DEFINE ld_t1,a2,0 4C8B5A00 DEFINE ld_t1,a2,8 4C8B5A08 DEFINE ld_t1,a2,16 4C8B5A10 DEFINE ld_t1,a3,0 4C8B5900 @@ -317,6 +334,7 @@ DEFINE st_a0,a3,8 48897908 DEFINE st_a0,a3,16 48897910 DEFINE st_a0,t0,0 49897A00 DEFINE st_a0,t0,8 49897A08 +DEFINE st_a0,t1,0 49897B00 DEFINE st_a0,t2,0 49897800 DEFINE st_a0,t2,8 49897808 DEFINE st_a0,t2,16 49897810 @@ -353,6 +371,7 @@ DEFINE st_a3,a0,0 48894F00 DEFINE st_a3,a1,0 48894E00 DEFINE st_a3,a2,0 48894A00 DEFINE st_a3,t0,24 49894A18 +DEFINE st_a3,t1,0 49894B00 DEFINE st_a3,t1,8 49894B08 DEFINE st_a3,t2,0 49894800 DEFINE st_a3,t2,8 49894808 @@ -365,7 +384,6 @@ DEFINE st_t0,a0,24 4C895718 DEFINE st_t0,a1,0 4C895600 DEFINE st_t0,a2,0 4C895200 DEFINE st_t0,a3,0 4C895100 -DEFINE st_t0,a3,8 4C895108 DEFINE st_t0,t1,0 4D895300 DEFINE st_t0,t2,0 4D895000 DEFINE st_t0,sp,0 4C89542410 @@ -390,6 +408,7 @@ DEFINE st_t2,a3,0 4C894100 DEFINE st_t2,t0,0 4D894200 DEFINE st_t2,t1,0 4D894300 DEFINE lb_a0,a0,0 480FB67F00 +DEFINE lb_a0,a2,0 480FB67A00 DEFINE lb_a0,t0,0 490FB67A00 DEFINE lb_a1,a1,0 480FB67600 DEFINE lb_a1,a3,0 480FB67100 @@ -401,10 +420,11 @@ DEFINE lb_a3,a0,0 480FB64F00 DEFINE lb_a3,a1,0 480FB64E00 DEFINE lb_a3,a2,0 480FB64A00 DEFINE lb_a3,a3,0 480FB64900 -DEFINE lb_t0,a3,0 4C0FB65100 -DEFINE lb_t0,a3,1 4C0FB65101 +DEFINE lb_t0,a0,0 4C0FB65700 +DEFINE lb_t0,a0,1 4C0FB65701 DEFINE lb_t0,t0,0 4D0FB65200 DEFINE lb_t1,t1,0 4D0FB65B00 +DEFINE lb_t2,a2,0 4C0FB64200 DEFINE lb_t2,t0,0 4D0FB64200 DEFINE lb_t2,t2,0 4D0FB64000 DEFINE sb_a0,a1,0 48887E00 @@ -452,6 +472,7 @@ DEFINE beq_t2,a2 4939D0750341FFE7 DEFINE beq_t2,a3 4939C8750341FFE7 DEFINE beq_t2,t1 4D39D8750341FFE7 DEFINE bne_a0,t0 4C39D7740341FFE7 +DEFINE bne_a0,t1 4C39DF740341FFE7 DEFINE bne_a1,a2 4839D6740341FFE7 DEFINE bne_a1,t0 4C39D6740341FFE7 DEFINE bne_a2,a1 4839F2740341FFE7 @@ -460,6 +481,8 @@ DEFINE bne_a3,a0 4839F9740341FFE7 DEFINE bne_a3,a1 4839F1740341FFE7 DEFINE bne_a3,a2 4839D1740341FFE7 DEFINE bne_a3,t0 4C39D1740341FFE7 +DEFINE bne_t0,a0 4939FA740341FFE7 +DEFINE bne_t0,a2 4939D2740341FFE7 DEFINE bne_t0,t1 4D39DA740341FFE7 DEFINE bne_t0,t2 4D39C2740341FFE7 DEFINE bne_t1,a2 4939D3740341FFE7 @@ -468,7 +491,9 @@ DEFINE bne_t1,t2 4D39C3740341FFE7 DEFINE bne_t2,a2 4939D0740341FFE7 DEFINE bne_t2,a3 4939C8740341FFE7 DEFINE bne_t2,t0 4D39D0740341FFE7 +DEFINE blt_a0,a1 4839F77D0341FFE7 DEFINE blt_a0,a2 4839D77D0341FFE7 +DEFINE blt_a0,t1 4C39DF7D0341FFE7 DEFINE blt_a1,a0 4839FE7D0341FFE7 DEFINE blt_a1,a2 4839D67D0341FFE7 DEFINE blt_a1,t0 4C39D67D0341FFE7 @@ -479,7 +504,10 @@ DEFINE blt_a2,t0 4C39D27D0341FFE7 DEFINE blt_a2,t1 4C39DA7D0341FFE7 DEFINE blt_a3,a2 4839D17D0341FFE7 DEFINE blt_a3,t2 4C39C17D0341FFE7 +DEFINE blt_t0,a0 4939FA7D0341FFE7 +DEFINE blt_t0,a2 4939D27D0341FFE7 DEFINE blt_t0,t1 4D39DA7D0341FFE7 +DEFINE blt_t1,a0 4939FB7D0341FFE7 DEFINE blt_t1,a1 4939F37D0341FFE7 DEFINE blt_t1,t0 4D39D37D0341FFE7 DEFINE blt_t2,a3 4939C87D0341FFE7 @@ -494,6 +522,7 @@ DEFINE beqz_t2 4D85C0750341FFE7 DEFINE bnez_a0 4885FF740341FFE7 DEFINE bnez_a1 4885F6740341FFE7 DEFINE bnez_a2 4885D2740341FFE7 +DEFINE bnez_a3 4885C9740341FFE7 DEFINE bnez_t0 4D85D2740341FFE7 DEFINE bnez_t1 4D85DB740341FFE7 DEFINE bnez_t2 4D85C0740341FFE7 diff --git a/P1/P1-riscv64.M1 b/P1/P1-riscv64.M1 @@ -23,7 +23,6 @@ DEFINE la_br 970F000083EFCF006F008000 ## ---- Moves DEFINE mov_a0,a1 13850500 -DEFINE mov_a0,a2 13050600 DEFINE mov_a0,a3 13850600 DEFINE mov_a0,t0 13850200 DEFINE mov_a0,t1 13050300 @@ -36,10 +35,12 @@ DEFINE mov_a2,t0 13860200 DEFINE mov_a2,t1 13060300 DEFINE mov_t0,a0 93020500 DEFINE mov_t1,a0 13030500 +DEFINE mov_t1,t0 13830200 DEFINE mov_t2,a0 93030500 DEFINE mov_t2,t1 93030300 ## ---- Register Arithmetic +DEFINE add_a0,a0,a1 3305B500 DEFINE add_a0,a0,a2 3305C500 DEFINE add_a0,a0,a3 3305D500 DEFINE add_a0,a0,t0 33055500 @@ -56,7 +57,7 @@ DEFINE add_a1,a1,a0 B385A500 DEFINE add_a1,a1,a2 B385C500 DEFINE add_a1,a1,a3 B385D500 DEFINE add_a1,a1,t0 B3855500 -DEFINE add_a1,a1,t1 B3856500 +DEFINE add_a1,a1,t2 B3857500 DEFINE add_a1,a2,t0 B3055600 DEFINE add_a1,a3,a1 B385B600 DEFINE add_a1,t0,a0 B385A200 @@ -66,11 +67,10 @@ DEFINE add_a1,t2,t1 B3856300 DEFINE add_a2,a1,a3 3386D500 DEFINE add_a2,a1,t0 33865500 DEFINE add_a2,a2,a0 3306A600 -DEFINE add_a2,a2,a1 3306B600 DEFINE add_a2,a2,a3 3306D600 DEFINE add_a2,a2,t0 33065600 DEFINE add_a2,a2,t1 33066600 -DEFINE add_a2,a2,t2 33067600 +DEFINE add_a2,a3,a1 3386B600 DEFINE add_a2,a3,a2 3386C600 DEFINE add_a2,t0,t1 33866200 DEFINE add_a2,t2,a0 3386A300 @@ -78,6 +78,7 @@ DEFINE add_a2,t2,a2 3386C300 DEFINE add_a3,a0,a2 B306C500 DEFINE add_a3,a1,t1 B3866500 DEFINE add_a3,a1,t2 B3867500 +DEFINE add_a3,a3,a0 B386A600 DEFINE add_a3,a3,a1 B386B600 DEFINE add_a3,a3,a2 B386C600 DEFINE add_a3,a3,t0 B3865600 @@ -108,16 +109,18 @@ DEFINE add_t2,t1,t2 B3037300 DEFINE add_t2,t2,a0 B383A300 DEFINE add_t2,t2,a3 B383D300 DEFINE add_t2,t2,t1 B3836300 +DEFINE sub_a0,a0,a1 3305B540 DEFINE sub_a0,a0,t1 33056540 +DEFINE sub_a0,a1,a0 3385A540 DEFINE sub_a0,a1,t2 33857540 DEFINE sub_a0,a3,a0 3385A640 DEFINE sub_a1,t0,a0 B385A240 DEFINE sub_a2,a1,a0 3386A540 -DEFINE sub_a2,a1,a3 3386D540 DEFINE sub_a2,a2,a2 3306C640 DEFINE sub_a2,a2,t0 33065640 DEFINE sub_a2,t0,t1 33866240 DEFINE sub_a2,t2,a3 3386D340 +DEFINE sub_a3,a1,a2 B386C540 DEFINE sub_a3,a3,a2 B386C640 DEFINE sub_a3,t0,a2 B386C240 DEFINE sub_a3,t0,a3 B386D240 @@ -128,6 +131,8 @@ DEFINE sub_a3,t2,t1 B3866340 DEFINE sub_t0,a1,a2 B382C540 DEFINE sub_t0,t0,a1 B382B240 DEFINE sub_t0,t0,t1 B3826240 +DEFINE sub_t0,t1,t0 B3025340 +DEFINE sub_t1,t1,t0 33035340 DEFINE sub_t2,t1,t0 B3035340 DEFINE and_a3,a3,a2 B3F6C600 DEFINE or_a0,a0,a2 3365C500 @@ -137,13 +142,18 @@ DEFINE xor_a3,a3,a2 B3C6C600 DEFINE shl_a2,a2,a3 3316D600 DEFINE sar_a2,a2,a3 3356D640 DEFINE mul_a0,a0,a3 3305D502 +DEFINE mul_a0,a0,t0 33055502 DEFINE mul_a0,t1,t2 33057302 +DEFINE mul_a2,a2,t1 33066602 DEFINE mul_a3,a3,a2 B386C602 DEFINE mul_t0,t0,a1 B382B202 +DEFINE mul_t0,t0,t1 B3826202 DEFINE mul_t2,t0,a2 B383C202 DEFINE div_a0,a0,a1 3345B502 +DEFINE div_a0,a0,t1 33456502 DEFINE div_a2,a2,a3 3346D602 DEFINE rem_a2,a0,a1 3366B502 +DEFINE rem_a2,a0,t1 33666502 DEFINE rem_a2,a2,a3 3366D602 ## ---- Immediate Arithmetic @@ -166,6 +176,7 @@ DEFINE addi_a2,a2,24 13068601 DEFINE addi_a2,a2,48 13060603 DEFINE addi_a2,t0,1 13861200 DEFINE addi_a2,t2,neg48 138603FD +DEFINE addi_a3,a3,neg1 9386F6FF DEFINE addi_a3,a3,1 93861600 DEFINE addi_a3,a3,32 93860602 DEFINE addi_a3,t0,32 93860202 @@ -193,8 +204,10 @@ DEFINE addi_t2,t2,1 93831300 DEFINE addi_t2,t2,7 93837300 DEFINE addi_t2,t2,24 93838301 DEFINE addi_t2,t2,32 93830302 +DEFINE andi_a0,a0,255 1375F50F DEFINE andi_a2,a2,15 1376F600 DEFINE andi_a3,a3,15 93F6F600 +DEFINE andi_a3,a3,255 93F6F60F DEFINE andi_a3,t2,255 93F6F30F DEFINE shli_a0,a0,3 13153500 DEFINE shli_a0,a0,4 13154500 @@ -202,6 +215,7 @@ DEFINE shli_a1,a1,1 93951500 DEFINE shli_a2,t1,3 13163300 DEFINE shli_a3,t0,1 93961200 DEFINE shli_a3,t0,4 93964200 +DEFINE shli_t0,t0,4 93924200 DEFINE shli_t1,a2,3 13133600 DEFINE shli_t2,t0,3 93933200 DEFINE shri_a2,a3,4 13D64600 @@ -265,11 +279,13 @@ DEFINE ld_a3,t1,8 83368300 DEFINE ld_t0,a0,0 83320500 DEFINE ld_t0,a0,8 83328500 DEFINE ld_t0,a0,16 83320501 +DEFINE ld_t0,a0,24 83328501 DEFINE ld_t0,a1,0 83B20500 DEFINE ld_t0,a1,8 83B28500 DEFINE ld_t0,a1,16 83B20501 DEFINE ld_t0,a1,32 83B20502 DEFINE ld_t0,a2,0 83320600 +DEFINE ld_t0,a3,0 83B20600 DEFINE ld_t0,t0,0 83B20200 DEFINE ld_t0,t2,0 83B20300 DEFINE ld_t0,t2,16 83B20301 @@ -286,6 +302,7 @@ DEFINE ld_t1,a0,24 03338501 DEFINE ld_t1,a1,0 03B30500 DEFINE ld_t1,a1,8 03B38500 DEFINE ld_t1,a1,16 03B30501 +DEFINE ld_t1,a2,0 03330600 DEFINE ld_t1,a2,8 03338600 DEFINE ld_t1,a2,16 03330601 DEFINE ld_t1,a3,0 03B30600 @@ -317,6 +334,7 @@ DEFINE st_a0,a3,8 23B4A600 DEFINE st_a0,a3,16 23B8A600 DEFINE st_a0,t0,0 23B0A200 DEFINE st_a0,t0,8 23B4A200 +DEFINE st_a0,t1,0 2330A300 DEFINE st_a0,t2,0 23B0A300 DEFINE st_a0,t2,8 23B4A300 DEFINE st_a0,t2,16 23B8A300 @@ -353,6 +371,7 @@ DEFINE st_a3,a0,0 2330D500 DEFINE st_a3,a1,0 23B0D500 DEFINE st_a3,a2,0 2330D600 DEFINE st_a3,t0,24 23BCD200 +DEFINE st_a3,t1,0 2330D300 DEFINE st_a3,t1,8 2334D300 DEFINE st_a3,t2,0 23B0D300 DEFINE st_a3,t2,8 23B4D300 @@ -365,7 +384,6 @@ DEFINE st_t0,a0,24 233C5500 DEFINE st_t0,a1,0 23B05500 DEFINE st_t0,a2,0 23305600 DEFINE st_t0,a3,0 23B05600 -DEFINE st_t0,a3,8 23B45600 DEFINE st_t0,t1,0 23305300 DEFINE st_t0,t2,0 23B05300 DEFINE st_t0,sp,0 23385100 @@ -390,6 +408,7 @@ DEFINE st_t2,a3,0 23B07600 DEFINE st_t2,t0,0 23B07200 DEFINE st_t2,t1,0 23307300 DEFINE lb_a0,a0,0 03450500 +DEFINE lb_a0,a2,0 03450600 DEFINE lb_a0,t0,0 03C50200 DEFINE lb_a1,a1,0 83C50500 DEFINE lb_a1,a3,0 83C50600 @@ -401,10 +420,11 @@ DEFINE lb_a3,a0,0 83460500 DEFINE lb_a3,a1,0 83C60500 DEFINE lb_a3,a2,0 83460600 DEFINE lb_a3,a3,0 83C60600 -DEFINE lb_t0,a3,0 83C20600 -DEFINE lb_t0,a3,1 83C21600 +DEFINE lb_t0,a0,0 83420500 +DEFINE lb_t0,a0,1 83421500 DEFINE lb_t0,t0,0 83C20200 DEFINE lb_t1,t1,0 03430300 +DEFINE lb_t2,a2,0 83430600 DEFINE lb_t2,t0,0 83C30200 DEFINE lb_t2,t2,0 83C30300 DEFINE sb_a0,a1,0 2380A500 @@ -452,6 +472,7 @@ DEFINE beq_t2,a2 6394C30067800F00 DEFINE beq_t2,a3 6394D30067800F00 DEFINE beq_t2,t1 6394630067800F00 DEFINE bne_a0,t0 6304550067800F00 +DEFINE bne_a0,t1 6304650067800F00 DEFINE bne_a1,a2 6384C50067800F00 DEFINE bne_a1,t0 6384550067800F00 DEFINE bne_a2,a1 6304B60067800F00 @@ -460,6 +481,8 @@ DEFINE bne_a3,a0 6384A60067800F00 DEFINE bne_a3,a1 6384B60067800F00 DEFINE bne_a3,a2 6384C60067800F00 DEFINE bne_a3,t0 6384560067800F00 +DEFINE bne_t0,a0 6384A20067800F00 +DEFINE bne_t0,a2 6384C20067800F00 DEFINE bne_t0,t1 6384620067800F00 DEFINE bne_t0,t2 6384720067800F00 DEFINE bne_t1,a2 6304C30067800F00 @@ -468,7 +491,9 @@ DEFINE bne_t1,t2 6304730067800F00 DEFINE bne_t2,a2 6384C30067800F00 DEFINE bne_t2,a3 6384D30067800F00 DEFINE bne_t2,t0 6384530067800F00 +DEFINE blt_a0,a1 6354B50067800F00 DEFINE blt_a0,a2 6354C50067800F00 +DEFINE blt_a0,t1 6354650067800F00 DEFINE blt_a1,a0 63D4A50067800F00 DEFINE blt_a1,a2 63D4C50067800F00 DEFINE blt_a1,t0 63D4550067800F00 @@ -479,7 +504,10 @@ DEFINE blt_a2,t0 6354560067800F00 DEFINE blt_a2,t1 6354660067800F00 DEFINE blt_a3,a2 63D4C60067800F00 DEFINE blt_a3,t2 63D4760067800F00 +DEFINE blt_t0,a0 63D4A20067800F00 +DEFINE blt_t0,a2 63D4C20067800F00 DEFINE blt_t0,t1 63D4620067800F00 +DEFINE blt_t1,a0 6354A30067800F00 DEFINE blt_t1,a1 6354B30067800F00 DEFINE blt_t1,t0 6354530067800F00 DEFINE blt_t2,a3 63D4D30067800F00 @@ -494,6 +522,7 @@ DEFINE beqz_t2 6394030067800F00 DEFINE bnez_a0 6304050067800F00 DEFINE bnez_a1 6384050067800F00 DEFINE bnez_a2 6304060067800F00 +DEFINE bnez_a3 6384060067800F00 DEFINE bnez_t0 6384020067800F00 DEFINE bnez_t1 6304030067800F00 DEFINE bnez_t2 6384030067800F00 diff --git a/hex2pp/hex2pp.P1 b/hex2pp/hex2pp.P1 @@ -1,9 +1,8 @@ ## hex2pp.P1 -- P1 implementation of the hex2++ assembler/linker. ## -## Mirrors hex2pp/hex2pp.c exactly in observable behaviour. See the C -## file and docs/HEX2pp.md for the full spec; brief summary: +## Mirrors hex2pp/hex2pp.c. See docs/HEX2pp.md for the full spec; brief: ## -## Inputs are concatenated, scanned in two passes. Pass 1 records label +## Single input file, scanned in two passes. Pass 1 records label ## definitions while advancing a position counter (ip). Pass 2 emits ## bytes, resolving label references against the table built in pass 1. ## @@ -14,111 +13,87 @@ ## .align N [PATTERN] -> pad to N-byte boundary ## .fill N B -> N copies of byte B ## .scope / .endscope -> nestable local-label scope +## .ptrsize N -> width of '%' and '&' (4 or 8) ## # ... / ; ... -> line comment ## ## Multi-byte reference values are emitted little-endian by default. ## -## Invocation: -## hex2pp (-f|--file) FILE [(-f|--file) FILE ...] -## [-o|--output OUT] -## [-B|--base-address ADDR] -## [--big-endian | --little-endian] -## [-b|--binary] -## [--non-executable] -## [-h|--help] +## Invocation: hex2pp [-B ADDR] [-E|-e] [-b] [-N] IN OUT ## ## P1 ABI: a0..a3 arg/return, t0..t2 caller-saved temps. Non-leaf ## functions use enter_0 / eret. Entry is the portable p1_main ## (a0=argc, a1=argv); the backend-owned :_start stub captures argc/argv ## from the native entry state and sys_exits p1_main's return value. ## -## chmod note: the seed P1 (P1/P1-<arch>.M1) exposes only sys_openat / -## sys_read / sys_write / sys_exit. Since there is no chmod() syscall in -## the seed, we encode the desired final mode (0750 or 0640) directly in -## openat's mode argument at file-creation time. This achieves the same -## resulting file permissions as the C reference. -## -## Register usage discipline: the seed P1 mnemonic table only defines a -## restricted subset of (dst,src1,src2) and (dst,base,offset) combos. -## To stay within that table this file spills almost everything through -## fixed BSS slots between operations. The naming convention -## ``<func>_<name>`` keeps per-function spill slots from colliding. - -## --- Caps ------------------------------------------------------------------- -## Mirrors hex2pp.c constants (MAX_FILES=64, MAX_INPUT_BYTES=16 MiB, -## MAX_OUTPUT_BYTES=128 MiB, MAX_LABELS=2^20, MAX_TEXT=8 MiB, -## MAX_TOKEN=4096, MAX_SCOPE_DEPTH=32). Stored as 8-byte little-endian. -DEFINE H2_INPUT_CAP 0000000001000000 -DEFINE H2_OUTPUT_CAP 0000000008000000 -DEFINE H2_TEXT_CAP 0000000000800000 -DEFINE H2_LABEL_CAP 0000000000100000 +## chmod note: the seed P1 mnemonic table only exposes openat/read/write/ +## exit. We encode the desired final mode (0750 or 0640) directly in +## openat's mode argument at file-creation time, achieving the same +## resulting file permissions as the C reference's fopen+chmod. + +## --- Caps ------------------------------------------------------------------ +## Mirrors hex2pp.c constants. Stored as 8-byte little-endian. +DEFINE H2_INPUT_CAP 0000000100000000 +DEFINE H2_OUTPUT_CAP 0000000800000000 +DEFINE H2_TEXT_CAP 0000800000000000 +DEFINE H2_LABEL_CAP 0000100000000000 DEFINE H2_TOKEN_CAP 0010000000000000 -DEFINE H2_FILES_CAP 4000000000000000 DEFINE H2_SCOPE_CAP 2000000000000000 -## openat / mode constants (Linux generic) -DEFINE O_RDONLY 0000000000000000 -DEFINE O_WRONLY_CREAT_TRUNC 4102000000000000 -DEFINE MODE_0750 E801000000000000 -DEFINE MODE_0640 A001000000000000 -DEFINE AT_FDCWD 9CFFFFFFFFFFFFFF +## openat / mode constants (Linux generic). +DEFINE H2_O_WRONLY_CREAT_TRUNC 4102000000000000 +DEFINE H2_O_RDONLY 0000000000000000 +DEFINE H2_MODE_0750 E801000000000000 +DEFINE H2_MODE_0640 A001000000000000 +DEFINE H2_AT_FDCWD 9CFFFFFFFFFFFFFF DEFINE ZERO8 '0000000000000000' DEFINE ZERO4 '00000000' ## --- BSS layout (offsets from ELF_end) ------------------------------------- -## ## Each "_ptr" is a one-word slot in the executable's static data; p1_main's -## bss_init_loop initializes each to ELF_end + OFF_*. The arenas live past +## bss_init_loop initializes each to ELF_end + OFF_*. Arenas live past ## ELF_end (covered by the segment's memsz; the loader zero-initializes). ## -## Sizes (mirroring hex2pp.c caps): -## input_paths 64 * 8 = 512 B (char * per file) -## input_starts 64 * 8 = 512 B (offset into input_buf) -## input_lens 64 * 8 = 512 B -## scope_stack 32 * 8 = 256 B -## line_scratch 64 B (decimal render of cur_line) -## name_buf 4096 B -## label_buf 4096 B -## other_buf 4096 B -## pat_buf 4096 B -## ev_bytes 8 B -## df_byte 8 B -## input_buf 16 MiB -## output_buf 128 MiB -## text_buf 8 MiB -## labels 32 MiB (2^20 * 32 B) +## Region sizes (matching the C caps): +## scope_stack 32 * 8 = 256 B +## line_scratch = 64 B +## name_buf = 4096 B +## label_buf = 4096 B +## other_buf = 4096 B +## pat_buf = 4096 B +## ev_bytes = 8 B +## df_byte = 8 B +## input_buf = 16 MiB +## output_buf = 128 MiB +## text_buf = 8 MiB +## labels = 32 MiB (1<<20 * 32 B) ## -## Cumulative offsets, padded for clarity: -DEFINE OFF_input_paths 0000000000000000 -DEFINE OFF_input_starts 0002000000000000 -DEFINE OFF_input_lens 0004000000000000 -DEFINE OFF_scope_stack 0006000000000000 -DEFINE OFF_line_scratch 0007000000000000 -DEFINE OFF_name_buf 4007000000000000 -DEFINE OFF_label_buf 4017000000000000 -DEFINE OFF_other_buf 4027000000000000 -DEFINE OFF_pat_buf 4037000000000000 -DEFINE OFF_ev_bytes 4047000000000000 -DEFINE OFF_df_byte 5047000000000000 -DEFINE OFF_input_buf 0048000000000000 -DEFINE OFF_output_buf 0048000001000000 -DEFINE OFF_text_buf 0048000009000000 -DEFINE OFF_labels 0048000009800000 - -## --- Runtime shell: argv parse -> load files -> two passes -> write -> exit +## Compact cumulative offsets in 8-byte little-endian hex. +DEFINE H2_OFF_scope_stack 0000000000000000 +DEFINE H2_OFF_line_scratch 0001000000000000 +DEFINE H2_OFF_name_buf 4001000000000000 +DEFINE H2_OFF_label_buf 4011000000000000 +DEFINE H2_OFF_other_buf 4021000000000000 +DEFINE H2_OFF_pat_buf 4031000000000000 +DEFINE H2_OFF_ev_bytes 4041000000000000 +DEFINE H2_OFF_df_byte 5041000000000000 +DEFINE H2_OFF_input_buf 0042000000000000 +DEFINE H2_OFF_output_buf 0042100000000000 +DEFINE H2_OFF_text_buf 0042200000000000 +DEFINE H2_OFF_labels 0042300000000000 + +## --- p1_main: argv parse -> load input -> two passes -> write -> exit ------ :p1_main enter_0 - # ---- Save argc / argv FIRST (subsequent setup clobbers a0/a1) --------- - # On entry a0 = argc, a1 = argv (per the backend :_start stub). + # Save argc / argv before anything clobbers them. la_a2 &saved_argc st_a0,a2,0 la_a2 &saved_argv st_a1,a2,0 - # ---- Init BSS pointer slots from ELF_end ------------------------------ + # Init BSS pointer slots from ELF_end via table walk. la_t0 &ELF_end la_t1 &bss_init_tbl la_t2 &bss_init_tbl_end @@ -134,25 +109,19 @@ DEFINE OFF_labels 0048000009800000 b :bss_init_done - # ---- Default ptrsize = 4 ---------------------------------------------- + # Default ptrsize = 4. li_t0 %4 %0 - la_a0 &ptrsize - st_t0,a0,0 - -:arg_loop_init - li_t0 %0 %0 - la_a0 &arg_idx - st_t0,a0,0 + la_a2 &ptrsize + st_t0,a2,0 + # ---- Argv loop -------------------------------------------------------- + # i = 1 + li_t0 %1 %0 + la_a2 &arg_idx + st_t0,a2,0 :arg_loop - # i++; if (i >= argc) goto arg_done. arg_idx is bumped here at the - # top so each handler just `b` back to arg_loop without bookkeeping. - # arg_advance (used by value-taking flags) also increments, so a - # `-B ADDR` pair correctly advances by two argv slots per dispatch. la_a0 &arg_idx ld_t0,a0,0 - addi_t0,t0,1 - st_t0,a0,0 la_a1 &saved_argc ld_t1,a1,0 la_br &arg_done @@ -160,178 +129,156 @@ DEFINE OFF_labels 0048000009800000 la_br &arg_done blt_t1,t0 - # arg_ptr = argv[i] = *(argv + 8*i) + # arg_ptr = argv[i] la_a0 &saved_argv - ld_a0,a0,0 - mov_a1,a0 # a1 = argv - la_a0 &arg_idx - ld_t0,a0,0 - shli_t2,t0,3 # t2 = 8*i - add_a0,t2,a1 # a0 = argv + 8*i - ld_a0,a0,0 # a0 = argv[i] - la_a1 &arg_ptr - st_a0,a1,0 - - # Dispatch on the argument string. Each compare uses str_eq, which - # checks the trailing NUL of the argv string against the option - # constant's known length. Anything not matching a known flag (and - # not starting with '-') is treated as a positional argument: first - # is the input file, second is the output file. + ld_a1,a0,0 + shli_t2,t0,3 + add_a1,a1,t2 + ld_a0,a1,0 + la_a2 &arg_ptr + st_a0,a2,0 - # -B - la_a0 &arg_ptr - ld_a0,a0,0 - la_a1 &opt_dash_B + # Match against known short flags. + la_a1 &opt_B li_a2 %2 %0 la_br &str_eq call - la_br &arg_is_base + la_br &arg_is_B bnez_a0 - # -E la_a0 &arg_ptr ld_a0,a0,0 - la_a1 &opt_dash_E + la_a1 &opt_E li_a2 %2 %0 la_br &str_eq call la_br &arg_is_big bnez_a0 - # -e la_a0 &arg_ptr ld_a0,a0,0 - la_a1 &opt_dash_e + la_a1 &opt_e li_a2 %2 %0 la_br &str_eq call la_br &arg_is_little bnez_a0 - # -b la_a0 &arg_ptr ld_a0,a0,0 - la_a1 &opt_dash_b + la_a1 &opt_b li_a2 %2 %0 la_br &str_eq call la_br &arg_is_binary bnez_a0 - # -N la_a0 &arg_ptr ld_a0,a0,0 - la_a1 &opt_dash_N + la_a1 &opt_N li_a2 %2 %0 la_br &str_eq call la_br &arg_is_nonexec bnez_a0 - # Not a known flag. If it begins with '-' (and isn't just "-"), - # it's an unknown option. Otherwise it's a positional. + # Unrecognised. If first byte is '-' (and string len > 1), error. la_a0 &arg_ptr ld_a0,a0,0 - lb_a0,a0,0 # a0 = first byte - li_t0 %45 %0 # t0 = '-' + lb_t0,a0,0 + li_t1 %45 %0 la_br &arg_is_positional - bne_a0,t0 - la_a0 &arg_ptr - ld_a0,a0,0 - addi_a0,a0,1 - lb_a0,a0,0 # a0 = second byte + bne_t0,t1 + lb_t0,a0,1 la_br &arg_is_positional - beqz_a0 + beqz_t0 la_br &err_unknown_arg b :arg_is_positional - # If input not yet loaded, this is IN. Else if output not yet set, - # this is OUT. Else extra positional → error. - la_a0 &input_count + # First positional = input path; second = output path; third = error. + la_a0 &input_path ld_t0,a0,0 - la_br &arg_pos_is_out + la_br &arg_pos_set_out bnez_t0 - la_a0 &arg_ptr - ld_a0,a0,0 - la_br &load_input - call - la_br &arg_loop + la_a1 &arg_ptr + ld_t0,a1,0 + st_t0,a0,0 + la_br &arg_loop_next b -:arg_pos_is_out +:arg_pos_set_out la_a0 &output_path ld_t0,a0,0 - la_br &err_unknown_arg + la_br &err_extra_positional bnez_t0 - la_a0 &arg_ptr - ld_a0,a0,0 - la_a1 &output_path - st_a0,a1,0 - la_br &arg_loop + la_a1 &arg_ptr + ld_t0,a1,0 + st_t0,a0,0 + la_br &arg_loop_next b -:arg_is_base - la_br &arg_advance - call - la_a0 &arg_ptr - ld_a0,a0,0 - la_br &parse_long_arg +:arg_is_B + # -B requires a value in the next argv slot. + la_a0 &arg_idx + ld_t0,a0,0 + addi_t0,t0,1 + st_t0,a0,0 + la_a1 &saved_argc + ld_t1,a1,0 + la_br &err_missing_value + beq_t0,t1 + la_br &err_missing_value + blt_t1,t0 + la_a0 &saved_argv + ld_a1,a0,0 + shli_t2,t0,3 + add_a1,a1,t2 + ld_a0,a1,0 + la_br &parse_long call la_a1 &base_address st_a0,a1,0 - la_br &arg_loop + la_br &arg_loop_next b + :arg_is_big li_t0 %1 %0 - la_a0 &big_endian - st_t0,a0,0 - la_br &arg_loop + la_a1 &big_endian + st_t0,a1,0 + la_br &arg_loop_next b + :arg_is_little li_t0 %0 %0 - la_a0 &big_endian - st_t0,a0,0 - la_br &arg_loop + la_a1 &big_endian + st_t0,a1,0 + la_br &arg_loop_next b + :arg_is_binary li_t0 %1 %0 - la_a0 &byte_mode - st_t0,a0,0 - la_br &arg_loop + la_a1 &byte_mode + st_t0,a1,0 + la_br &arg_loop_next b + :arg_is_nonexec li_t0 %1 %0 - la_a0 &non_executable - st_t0,a0,0 - la_br &arg_loop + la_a1 &non_executable + st_t0,a1,0 + la_br &arg_loop_next b -## arg_advance(): i++; if (i >= argc) usage error; arg_ptr = argv[i]. -:arg_advance - enter_0 +:arg_loop_next la_a0 &arg_idx ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 - la_a1 &saved_argc - ld_t1,a1,0 - la_br &err_missing_arg_value - beq_t0,t1 - la_br &err_missing_arg_value - blt_t1,t0 - # arg_ptr = argv[i] - la_a0 &saved_argv - ld_a0,a0,0 - mov_a1,a0 - shli_t2,t0,3 - add_a0,t2,a1 - ld_a0,a0,0 - la_a1 &arg_ptr - st_a0,a1,0 - eret + la_br &arg_loop + b :arg_done - la_a0 &input_count + la_a0 &input_path ld_t0,a0,0 la_br &err_missing_positional beqz_t0 @@ -340,13 +287,17 @@ DEFINE OFF_labels 0048000009800000 la_br &err_missing_positional beqz_t0 - # ---- Pass 1: collect labels -------------------------------------------- + # ---- Load input file ------------------------------------------------- + la_br &load_input + call + + # ---- Pass 1 ---------------------------------------------------------- li_t0 %1 %0 la_a0 &pass st_t0,a0,0 la_br &reset_pass_state call - la_br &run_one_pass + la_br &process_input call la_a0 &scope_depth ld_t0,a0,0 @@ -358,13 +309,13 @@ DEFINE OFF_labels 0048000009800000 la_a0 &cur_path st_t0,a0,0 - # ---- Pass 2: emit ------------------------------------------------------ + # ---- Pass 2 ---------------------------------------------------------- li_t0 %2 %0 la_a0 &pass st_t0,a0,0 la_br &reset_pass_state call - la_br &run_one_pass + la_br &process_input call la_a0 &scope_depth ld_t0,a0,0 @@ -401,84 +352,25 @@ DEFINE OFF_labels 0048000009800000 st_t0,a0,0 eret -## run_one_pass(): for i in [0, input_count) call process_file(i). -:run_one_pass - enter_0 - li_t0 %0 %0 - la_a0 &pass_idx - st_t0,a0,0 -:run_one_pass_loop - la_a0 &pass_idx - ld_t0,a0,0 - la_a1 &input_count - ld_t1,a1,0 - la_br &run_one_pass_done - beq_t0,t1 - mov_a0,t0 - la_br &process_file - call - la_a0 &pass_idx - ld_t0,a0,0 - addi_t0,t0,1 - st_t0,a0,0 - la_br &run_one_pass_loop - b -:run_one_pass_done - eret - -## --- File loader ------------------------------------------------------------ -## load_input(a0=path): record path, read file appended into input_buf at -## offset input_total, then advance input_total. Fatal on any I/O failure. +## --- Input loader ---------------------------------------------------------- +## load_input(): openat(input_path), read into input_buf until EOF. :load_input enter_0 - la_a1 &input_count - ld_t0,a1,0 - li_t1 H2_FILES_CAP - la_br &err_too_many_files - beq_t0,t1 - - # Save path into input_paths[input_count]. - la_a1 &input_paths_ptr - ld_a1,a1,0 - shli_t2,t0,3 - add_a1,t2,a1 - st_a0,a1,0 - - # input_starts[input_count] = input_total - la_a1 &input_total - ld_t1,a1,0 - la_a2 &input_starts_ptr - ld_a2,a2,0 - add_a2,t2,a2 - la_a0 &aux_tmp - st_t1,a0,0 - ld_a3,a0,0 - st_a3,a2,0 - - # Stash path for the syscall. a0 was clobbered by &aux_tmp above, - # so re-read the path from input_paths[input_count] (still index 0 - # for our slot since input_count is incremented at li_eof). - la_a0 &input_paths_ptr - ld_a0,a0,0 - ld_a0,a0,0 - la_a1 &li_path - st_a0,a1,0 - - # fd = openat(AT_FDCWD, path, O_RDONLY, 0) + # fd = openat(AT_FDCWD, input_path, O_RDONLY, 0) li_a0 sys_openat - li_a1 AT_FDCWD - la_a2 &li_path + li_a1 H2_AT_FDCWD + la_a2 &input_path ld_a2,a2,0 - li_a3 O_RDONLY + li_a3 H2_O_RDONLY li_t0 %0 %0 syscall la_br &err_open_input bltz_a0 - la_a1 &li_fd + la_a1 &input_fd st_a0,a1,0 :li_read_loop - la_a0 &input_total + la_a0 &input_len ld_t0,a0,0 li_t1 H2_INPUT_CAP la_br &err_input_too_big @@ -486,13 +378,13 @@ DEFINE OFF_labels 0048000009800000 la_br &err_input_too_big blt_t1,t0 - # n = read(fd, input_buf + input_total, INPUT_CAP - input_total) - la_a0 &li_fd + # n = read(fd, input_buf + input_len, INPUT_CAP - input_len) + la_a0 &input_fd ld_a1,a0,0 la_a2 &input_buf_ptr ld_a2,a2,0 add_a2,a2,t0 - sub_a3,t1,t0 # available? sub_a3,t1,t0 — yes + sub_a3,t1,t0 li_a0 sys_read syscall la_br &li_eof @@ -500,8 +392,7 @@ DEFINE OFF_labels 0048000009800000 la_br &err_read bltz_a0 - # input_total += n - la_a1 &input_total + la_a1 &input_len ld_t0,a1,0 add_t0,t0,a0 st_t0,a1,0 @@ -509,92 +400,30 @@ DEFINE OFF_labels 0048000009800000 b :li_eof - # input_lens[input_count] = input_total - input_starts[input_count]. - # The seed has add_a2,a2,t1 but neither add_a2,a2,t2 nor mov_t1,t2, - # so the stride-by-8 result lives in t2 and is then re-loaded as t1 - # via the li_tmp scratch slot. - la_a0 &input_count - ld_t0,a0,0 - shli_t2,t0,3 - la_a3 &li_tmp - st_t2,a3,0 - ld_t1,a3,0 - la_a2 &input_starts_ptr - ld_a2,a2,0 - add_a2,a2,t1 # a2 = &input_starts[i] - ld_a3,a2,0 # a3 = input_starts[i] - la_a0 &input_total - ld_a1,a0,0 # a1 = input_total - # We need (total - start) into a2, but no sub_a2,a1,a3 form exists. - # Spill start through li_tmp -> a0 so we can use sub_a2,a1,a0. - la_a0 &li_tmp - st_a3,a0,0 - ld_a0,a0,0 # a0 = start (re-reads via li_tmp) - sub_a2,a1,a0 # a2 = total - start - # Store into input_lens[i] (reuse the same t1 scaling). - la_a0 &input_lens_ptr - ld_a0,a0,0 - add_a0,a0,t1 - st_a2,a0,0 - - la_a0 &input_count - ld_t0,a0,0 - addi_t0,t0,1 - st_t0,a0,0 eret -## --- Per-file scanner ------------------------------------------------------- - -## process_file(a0=file_idx): set cur_path / cur_line / scan_pos / scan_end -## from the input record, then dispatch character by character. -:process_file +## --- Process input: scan one pass over input_buf --------------------------- +:process_input enter_0 - mov_t0,a0 - shli_t2,t0,3 # t2 = 8*idx - - # cur_path = input_paths[idx] - la_a3 &li_tmp - st_t2,a3,0 - ld_t1,a3,0 # t1 = 8*idx - la_a1 &input_paths_ptr - ld_a1,a1,0 - add_a1,a1,t1 # available add_a1,a1,t1 - ld_a1,a1,0 - la_a2 &cur_path - st_a1,a2,0 - - # cur_line = 1 + # cur_path = input_path; cur_line = 1 + la_a0 &input_path + ld_t0,a0,0 + la_a1 &cur_path + st_t0,a1,0 li_t0 %1 %0 - la_a2 &cur_line - st_t0,a2,0 - - # scan_pos = input_buf + input_starts[idx] - la_a1 &input_starts_ptr - ld_a1,a1,0 - add_a1,a1,t1 - ld_a1,a1,0 # a1 = start offset - la_a2 &input_buf_ptr - ld_a2,a2,0 - mov_a0,a1 - add_a2,a2,a0 # add_a2,a2,a1 NOT listed. Use a2,a2,a0 with a0=a1. - la_a3 &li_tmp - st_a1,a3,0 - ld_a0,a3,0 # a0 = start - add_a2,a2,a0 # available - la_a0 &scan_pos - st_a2,a0,0 + la_a1 &cur_line + st_t0,a1,0 - # scan_end = scan_pos + input_lens[idx] - la_a1 &input_lens_ptr - ld_a1,a1,0 - add_a1,a1,t1 - ld_a1,a1,0 # a1 = len - la_a3 &li_tmp - st_a1,a3,0 - ld_a0,a3,0 - add_a2,a2,a0 - la_a0 &scan_end - st_a2,a0,0 + # scan_pos = input_buf; scan_end = input_buf + input_len + la_a0 &input_buf_ptr + ld_t0,a0,0 + la_a1 &scan_pos + st_t0,a1,0 + la_a0 &input_len + ld_t1,a0,0 + add_t0,t0,t1 + la_a1 &scan_end + st_t0,a1,0 :scan_loop la_br &skip_ws_and_comments @@ -609,43 +438,44 @@ DEFINE OFF_labels 0048000009800000 blt_t1,t0 lb_a0,t0,0 - # Dispatch on c. - li_t1 %58 %0 # ':' - la_br &scan_label_def + li_t1 %58 %0 + la_br &handle_label_def beq_a0,t1 - li_t1 %46 %0 # '.' - la_br &scan_directive + li_t1 %46 %0 + la_br &handle_directive beq_a0,t1 - li_t1 %33 %0 # '!' - la_br &scan_ref + li_t1 %33 %0 + la_br &handle_ref beq_a0,t1 - li_t1 %64 %0 # '@' - la_br &scan_ref + li_t1 %64 %0 + la_br &handle_ref beq_a0,t1 - li_t1 %36 %0 # '$' - la_br &scan_ref + li_t1 %36 %0 + la_br &handle_ref beq_a0,t1 - li_t1 %126 %0 # '~' - la_br &scan_ref + li_t1 %126 %0 + la_br &handle_ref beq_a0,t1 - li_t1 %37 %0 # '%' - la_br &scan_ref + li_t1 %37 %0 + la_br &handle_ref beq_a0,t1 - li_t1 %38 %0 # '&' - la_br &scan_ref + li_t1 %38 %0 + la_br &handle_ref beq_a0,t1 la_br &is_byte_digit call - la_br &scan_byte_stream + la_br &handle_byte_stream bnez_a0 la_br &err_unexpected_char b -:scan_label_def +:handle_label_def + # consume ':' la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 + # name = read_name(name_buf, MAX_TOKEN) la_a0 &name_buf_ptr ld_a0,a0,0 li_a1 H2_TOKEN_CAP @@ -653,40 +483,34 @@ DEFINE OFF_labels 0048000009800000 call la_a1 &name_len st_a0,a1,0 - # dotted = (name[0] == '.') - la_a1 &name_buf_ptr - ld_a1,a1,0 - la_a3 &aux_tmp - st_a1,a3,0 - ld_a3,a3,0 - lb_t0,a3,0 + # dotted = (name[0] == '.') AND scope_depth > 0 + la_a0 &name_buf_ptr + ld_a0,a0,0 + lb_t0,a0,0 li_t1 %46 %0 - la_br &scan_label_undotted + la_br &handle_label_global bne_t0,t1 - # dotted: scope-local only when inside a .scope; otherwise treat as - # an ordinary global label. la_a0 &scope_depth ld_t0,a0,0 - la_br &scan_label_undotted + la_br &handle_label_global beqz_t0 + # scope_id = scope_stack[scope_depth-1] addi_t0,t0,neg1 + la_a1 &scope_stack_ptr + ld_a1,a1,0 shli_t2,t0,3 - la_a3 &sl_tmp - st_t2,a3,0 - ld_t1,a3,0 - la_a0 &scope_stack_ptr - ld_a0,a0,0 - add_a0,a0,t1 # available - ld_a0,a0,0 # a0 = scope id of innermost scope - la_a1 &name_scope - st_a0,a1,0 - la_br &scan_label_define + add_a1,a1,t2 + ld_t0,a1,0 + la_a2 &name_scope + st_t0,a2,0 + la_br &handle_label_dispatch b -:scan_label_undotted +:handle_label_global li_t0 %0 %0 - la_a1 &name_scope - st_t0,a1,0 -:scan_label_define + la_a2 &name_scope + st_t0,a2,0 +:handle_label_dispatch + # Pass 1 only: define_label(name, len, scope) la_a0 &pass ld_t0,a0,0 li_t1 %1 %0 @@ -703,7 +527,8 @@ DEFINE OFF_labels 0048000009800000 la_br &scan_loop b -:scan_directive +:handle_directive + # consume '.' la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 @@ -716,122 +541,114 @@ DEFINE OFF_labels 0048000009800000 la_a1 &name_len st_a0,a1,0 - # Compare against the four known directive names. - li_t1 %5 %0 - la_br &scan_dir_check_4 - la_a3 &aux_tmp - st_t1,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 + # Dispatch by length, then memcmp. + la_a0 &name_len ld_t0,a0,0 - bne_a0,t0 + li_t1 %5 %0 + la_br &dir_check_4 + bne_t0,t1 + # Could be "align" or "scope". la_a0 &name_buf_ptr ld_a0,a0,0 - la_a1 &dir_align + la_a1 &kw_align li_a2 %5 %0 la_br &mem_eq call - la_br &scan_dir_align + la_br &dir_call_align bnez_a0 la_a0 &name_buf_ptr ld_a0,a0,0 - la_a1 &dir_scope + la_a1 &kw_scope li_a2 %5 %0 la_br &mem_eq call - la_br &scan_dir_scope_open + la_br &dir_call_scope bnez_a0 la_br &err_unknown_directive b -:scan_dir_check_4 - la_a0 &name_len - ld_t0,a0,0 +:dir_check_4 li_t1 %4 %0 - la_br &scan_dir_check_8 + la_br &dir_check_8 bne_t0,t1 la_a0 &name_buf_ptr ld_a0,a0,0 - la_a1 &dir_fill + la_a1 &kw_fill li_a2 %4 %0 la_br &mem_eq call - la_br &scan_dir_fill + la_br &dir_call_fill bnez_a0 la_br &err_unknown_directive b -:scan_dir_check_8 - la_a0 &name_len - ld_t0,a0,0 +:dir_check_8 li_t1 %8 %0 - la_br &scan_dir_check_7 + la_br &dir_check_7 bne_t0,t1 la_a0 &name_buf_ptr ld_a0,a0,0 - la_a1 &dir_endscope + la_a1 &kw_endscope li_a2 %8 %0 la_br &mem_eq call - la_br &scan_dir_scope_close + la_br &dir_call_endscope bnez_a0 la_br &err_unknown_directive b -:scan_dir_check_7 - la_a0 &name_len - ld_t0,a0,0 +:dir_check_7 li_t1 %7 %0 la_br &err_unknown_directive bne_t0,t1 la_a0 &name_buf_ptr ld_a0,a0,0 - la_a1 &dir_ptrsize + la_a1 &kw_ptrsize li_a2 %7 %0 la_br &mem_eq call - la_br &scan_dir_ptrsize + la_br &dir_call_ptrsize bnez_a0 la_br &err_unknown_directive b -:scan_dir_align +:dir_call_align la_br &do_align call la_br &scan_loop b -:scan_dir_fill +:dir_call_fill la_br &do_fill call la_br &scan_loop b -:scan_dir_scope_open +:dir_call_scope la_br &do_scope_open call la_br &scan_loop b -:scan_dir_scope_close +:dir_call_endscope la_br &do_scope_close call la_br &scan_loop b -:scan_dir_ptrsize +:dir_call_ptrsize la_br &do_ptrsize call la_br &scan_loop b -:scan_ref - # a0 holds sigil; advance past it then process_reference. +:handle_ref + # a0 holds the sigil byte; advance past it then process_reference. la_a1 &cur_sigil st_a0,a1,0 - la_a1 &scan_pos - ld_t0,a1,0 + la_a0 &scan_pos + ld_t0,a0,0 addi_t0,t0,1 - st_t0,a1,0 + st_t0,a0,0 la_br &process_reference call la_br &scan_loop b -:scan_byte_stream +:handle_byte_stream la_br &parse_byte_stream call la_br &scan_loop @@ -840,7 +657,7 @@ DEFINE OFF_labels 0048000009800000 :scan_done eret -## --- Lex helpers ------------------------------------------------------------ +## --- Lex helpers ----------------------------------------------------------- ## skip_ws_and_comments(): advance scan_pos past whitespace and #/; comments. ## Updates cur_line on '\n'. @@ -858,38 +675,35 @@ DEFINE OFF_labels 0048000009800000 lb_a0,t0,0 la_br &is_space_any call - la_br &swc_after_space_check + la_br &swc_after_ws_check beqz_a0 - # whitespace: advance; if '\n' bump cur_line. - la_a1 &scan_pos - ld_t0,a1,0 + # whitespace: bump cur_line on '\n', advance scan_pos. + la_a0 &scan_pos + ld_t0,a0,0 lb_a0,t0,0 li_t1 %10 %0 la_br &swc_advance - la_a3 &aux_tmp - st_t1,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - bne_a0,t0 - la_a2 &cur_line - la_a0 &aux_tmp - st_a2,a0,0 - ld_t2,a0,0 + bne_a0,t1 + la_a1 &cur_line + ld_t2,a1,0 addi_t2,t2,1 - st_t2,a2,0 + st_t2,a1,0 :swc_advance - la_a1 &scan_pos - ld_t0,a1,0 + la_a0 &scan_pos + ld_t0,a0,0 addi_t0,t0,1 - st_t0,a1,0 + st_t0,a0,0 la_br &swc_loop b -:swc_after_space_check - li_t1 %35 %0 # '#' +:swc_after_ws_check + # is_space_any clobbered a0; re-read the byte at scan_pos. + la_a0 &scan_pos + ld_t0,a0,0 + lb_a0,t0,0 + li_t1 %35 %0 la_br &swc_consume_comment beq_a0,t1 - li_t1 %59 %0 # ';' + li_t1 %59 %0 la_br &swc_consume_comment beq_a0,t1 la_br &swc_done @@ -909,7 +723,8 @@ DEFINE OFF_labels 0048000009800000 la_br &swc_loop beq_a0,t1 addi_t0,t0,1 - st_t0,a0,0 + la_a1 &scan_pos + st_t0,a1,0 la_br &swc_cc_loop b :swc_done @@ -952,10 +767,10 @@ DEFINE OFF_labels 0048000009800000 la_br &siw_done b :siw_advance - la_a1 &scan_pos - ld_t0,a1,0 + la_a0 &scan_pos + ld_t0,a0,0 addi_t0,t0,1 - st_t0,a1,0 + st_t0,a0,0 la_br &siw_loop b :siw_consume_comment @@ -973,7 +788,8 @@ DEFINE OFF_labels 0048000009800000 la_br &siw_done beq_a0,t1 addi_t0,t0,1 - st_t0,a0,0 + la_a1 &scan_pos + st_t0,a1,0 la_br &siw_cc_loop b :siw_done @@ -1005,34 +821,35 @@ DEFINE OFF_labels 0048000009800000 li_a0 %1 %0 ret -## is_name_terminator_c(a0=c) -> a0=0/1. Terminators: whitespace, '-', '#', ';'. +## is_name_terminator(a0=c) -> a0=0/1. Terminators: ws, '-', '>', '#', ';'. ## Spills c into a BSS slot since is_space_any clobbers a0. -:is_name_terminator_c +:is_name_terminator + enter_0 la_a1 &nt_c st_a0,a1,0 la_br &is_space_any call la_br &nt_yes bnez_a0 - la_a1 &nt_c - ld_a0,a1,0 - li_t0 %45 %0 # '-' + la_a0 &nt_c + ld_a0,a0,0 + li_t0 %45 %0 la_br &nt_yes beq_a0,t0 - li_t0 %62 %0 # '>' (synonym for '-') + li_t0 %62 %0 la_br &nt_yes beq_a0,t0 - li_t0 %35 %0 # '#' + li_t0 %35 %0 la_br &nt_yes beq_a0,t0 - li_t0 %59 %0 # ';' + li_t0 %59 %0 la_br &nt_yes beq_a0,t0 li_a0 %0 %0 - ret + eret :nt_yes li_a0 %1 %0 - ret + eret ## is_byte_digit(a0=c) -> a0=0/1. Mode-aware (HEX vs BINARY). :is_byte_digit @@ -1041,45 +858,39 @@ DEFINE OFF_labels 0048000009800000 la_br &ibd_bin bnez_t0 # HEX: 0-9, a-f, A-F - li_t0 %48 %0 + li_t1 %48 %0 la_br &ibd_no - mov_a2,t0 - blt_a0,a2 - li_t0 %57 %0 + blt_a0,t1 + li_t1 %57 %0 la_br &ibd_yes - mov_a2,t0 - blt_a0,a2 + blt_a0,t1 la_br &ibd_yes - beq_a0,t0 - li_t0 %65 %0 + beq_a0,t1 + li_t1 %65 %0 la_br &ibd_no - mov_a2,t0 - blt_a0,a2 - li_t0 %70 %0 + blt_a0,t1 + li_t1 %70 %0 la_br &ibd_yes - mov_a2,t0 - blt_a0,a2 + blt_a0,t1 la_br &ibd_yes - beq_a0,t0 - li_t0 %97 %0 + beq_a0,t1 + li_t1 %97 %0 la_br &ibd_no - mov_a2,t0 - blt_a0,a2 - li_t0 %102 %0 + blt_a0,t1 + li_t1 %102 %0 la_br &ibd_yes - mov_a2,t0 - blt_a0,a2 + blt_a0,t1 la_br &ibd_yes - beq_a0,t0 + beq_a0,t1 la_br &ibd_no b :ibd_bin - li_t0 %48 %0 + li_t1 %48 %0 la_br &ibd_yes - beq_a0,t0 - li_t0 %49 %0 + beq_a0,t1 + li_t1 %49 %0 la_br &ibd_yes - beq_a0,t0 + beq_a0,t1 la_br &ibd_no b :ibd_yes @@ -1094,22 +905,20 @@ DEFINE OFF_labels 0048000009800000 :byte_digit_value li_t0 %57 %0 la_br &bdv_alpha - mov_t1,a0 - blt_t0,t1 # if c > '9', go alpha + blt_t0,a0 li_t1 %48 %0 - sub_a0,a0,t1 # available + sub_a0,a0,t1 ret :bdv_alpha li_t0 %96 %0 la_br &bdv_lower - mov_t1,a0 - blt_t0,t1 # if c > 'a' - 1 (= 96), it's lowercase + blt_t0,a0 li_t1 %55 %0 - sub_a0,a0,t1 # 'A'(65) - 55 = 10 + sub_a0,a0,t1 ret :bdv_lower li_t1 %87 %0 - sub_a0,a0,t1 # 'a'(97) - 87 = 10 + sub_a0,a0,t1 ret ## byte_digit_count() -> a0. 2 for HEX, 8 for BINARY. @@ -1125,7 +934,7 @@ DEFINE OFF_labels 0048000009800000 ret ## read_name(a0=out_buf, a1=max) -> a0=length. Reads scan_pos into out_buf -## until is_name_terminator_c or scan_end. +## until is_name_terminator or scan_end. Fatal on overflow / empty. :read_name enter_0 la_a2 &rn_out @@ -1145,43 +954,31 @@ DEFINE OFF_labels 0048000009800000 la_br &rn_done blt_t1,t0 lb_a0,t0,0 - la_br &is_name_terminator_c + la_br &is_name_terminator call la_br &rn_done bnez_a0 - # overflow check la_a1 &rn_n ld_t0,a1,0 - la_a2 &rn_max - la_a0 &aux_tmp - st_a2,a0,0 + la_a0 &rn_max ld_t1,a0,0 la_br &err_name_too_long beq_t0,t1 - # store char (re-read from scan_pos) - la_a3 &scan_pos - ld_a3,a3,0 - la_a2 &aux_tmp - st_a3,a2,0 - la_a0 &aux_tmp - st_a2,a0,0 - ld_t1,a0,0 - lb_t1,t1,0 - la_a2 &rn_out - ld_a2,a2,0 - add_a2,a2,t0 - sb_t1,a2,0 - # n++ + # store char + la_a0 &scan_pos + ld_a0,a0,0 + lb_a3,a0,0 + la_a1 &rn_out + ld_a1,a1,0 + add_a1,a1,t0 + sb_a3,a1,0 addi_t0,t0,1 la_a1 &rn_n st_t0,a1,0 - # scan_pos++ - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 - st_t0,a3,0 + st_t0,a0,0 la_br &rn_loop b :rn_done @@ -1192,7 +989,7 @@ DEFINE OFF_labels 0048000009800000 eret ## read_directive_name(a0=out_buf, a1=max) -> a0=length. Like read_name but -## terminates on the first non-alpha byte. +## terminates on first non-alpha byte. :read_directive_name enter_0 la_a2 &rn_out @@ -1212,26 +1009,22 @@ DEFINE OFF_labels 0048000009800000 la_br &rdn_done blt_t1,t0 lb_a0,t0,0 - # Reject if not [A-Za-z] + # accept [A-Za-z] li_t1 %65 %0 la_br &rdn_check_lower - mov_a2,t1 - blt_a0,a2 + blt_a0,t1 li_t1 %90 %0 la_br &rdn_consume - mov_a2,t1 - blt_a0,a2 + blt_a0,t1 la_br &rdn_consume beq_a0,t1 :rdn_check_lower li_t1 %97 %0 la_br &rdn_done - mov_a2,t1 - blt_a0,a2 + blt_a0,t1 li_t1 %122 %0 la_br &rdn_consume - mov_a2,t1 - blt_a0,a2 + blt_a0,t1 la_br &rdn_consume beq_a0,t1 la_br &rdn_done @@ -1240,9 +1033,7 @@ DEFINE OFF_labels 0048000009800000 la_a1 &rn_n ld_t0,a1,0 la_a2 &rn_max - la_a0 &aux_tmp - st_a2,a0,0 - ld_t1,a0,0 + ld_t1,a2,0 la_br &err_name_too_long beq_t0,t1 la_a2 &rn_out @@ -1252,12 +1043,10 @@ DEFINE OFF_labels 0048000009800000 addi_t0,t0,1 la_a1 &rn_n st_t0,a1,0 - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 - st_t0,a3,0 + st_t0,a0,0 la_br &rdn_loop b :rdn_done @@ -1267,7 +1056,7 @@ DEFINE OFF_labels 0048000009800000 beqz_a0 eret -## read_decimal() -> a0=value (i64). Fatal on no digits. +## read_decimal() -> a0=value. Fatal on no digits. :read_decimal enter_0 li_t0 %0 %0 @@ -1287,36 +1076,26 @@ DEFINE OFF_labels 0048000009800000 lb_a0,t0,0 li_t1 %48 %0 la_br &rd_done - mov_a2,t1 - blt_a0,a2 + blt_a0,t1 li_t1 %57 %0 la_br &rd_done - mov_a1,a0 - blt_t1,a1 + blt_t1,a0 # acc = acc * 10 + (c - '0') la_a1 &rd_val - ld_t0,a1,0 + ld_a2,a1,0 li_t1 %10 %0 - la_a3 &rd_tmp - st_t1,a3,0 - la_a1 &aux_tmp - st_a3,a1,0 - ld_a1,a1,0 # a1 = 10 - mul_t0,t0,a1 # t0 = acc * 10 + mul_a2,a2,t1 li_t1 %48 %0 - sub_a0,a0,t1 # a0 = c - 48 - add_t0,t0,a0 - la_a1 &rd_val - st_t0,a1,0 + sub_a0,a0,t1 + add_a2,a2,a0 + st_a2,a1,0 li_t0 %1 %0 la_a1 &rd_saw st_t0,a1,0 - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 - st_t0,a3,0 + st_t0,a0,0 la_br &rd_loop b :rd_done @@ -1330,9 +1109,9 @@ DEFINE OFF_labels 0048000009800000 ## --- Byte stream / single byte literal ------------------------------------- -## parse_byte_stream(): consume free-flowing digits (intermixed with -## whitespace and #/; comments) and emit_byte them. Stops at first non- -## digit non-whitespace non-comment byte. +## parse_byte_stream(): consume free-flowing digits (intermixed with ws and +## #/; comments) and emit_byte them. Stops at first non-digit non-ws +## non-comment byte. :parse_byte_stream enter_0 li_t0 %0 %0 @@ -1354,9 +1133,7 @@ DEFINE OFF_labels 0048000009800000 call la_br &pbs_consume_ws bnez_a0 - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 lb_a0,t0,0 li_t1 %35 %0 @@ -1369,46 +1146,42 @@ DEFINE OFF_labels 0048000009800000 call la_br &pbs_done beqz_a0 - # Save and consume the digit char. - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + # consume one digit + la_a0 &scan_pos ld_t0,a0,0 lb_a0,t0,0 addi_t0,t0,1 - st_t0,a3,0 + la_a1 &scan_pos + st_t0,a1,0 la_a1 &pbs_c st_a0,a1,0 - # acc = (acc << shift_per_digit) | nibble + # acc = (acc << shift) | digit la_a1 &byte_mode ld_t1,a1,0 - la_br &pbs_bin_step + la_br &pbs_bin bnez_t1 - # HEX + # HEX: shift 4 + digit_value la_a1 &pbs_acc ld_t0,a1,0 - shli_a3,t0,4 # a3 = acc << 4 + shli_a3,t0,4 la_a1 &pbs_c ld_a0,a1,0 la_br &byte_digit_value call - mov_t0,a0 - add_a3,a3,t0 # available + add_a3,a3,a0 la_a1 &pbs_acc st_a3,a1,0 la_br &pbs_bump b -:pbs_bin_step - # BINARY +:pbs_bin la_a1 &pbs_acc ld_t0,a1,0 - shli_a3,t0,1 # a3 = acc << 1 + shli_a3,t0,1 la_a1 &pbs_c ld_a0,a1,0 li_t1 %48 %0 sub_a0,a0,t1 - mov_t0,a0 - add_a3,a3,t0 + add_a3,a3,a0 la_a1 &pbs_acc st_a3,a1,0 :pbs_bump @@ -1421,15 +1194,11 @@ DEFINE OFF_labels 0048000009800000 la_a1 &pbs_have ld_t0,a1,0 la_br &pbs_loop - la_a3 &aux_tmp - st_a0,a3,0 - ld_t1,a3,0 - bne_t0,t1 - # have == digits_per_byte: emit and reset + bne_t0,a0 + # full byte: emit la_a1 &pbs_acc - ld_t2,a1,0 # t2 = acc - andi_a3,t2,255 - mov_a0,a3 # available mov_a0,a3 + ld_a0,a1,0 + andi_a0,a0,255 la_br &emit_byte call li_t0 %0 %0 @@ -1440,32 +1209,21 @@ DEFINE OFF_labels 0048000009800000 la_br &pbs_loop b :pbs_consume_ws - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 lb_a0,t0,0 li_t1 %10 %0 la_br &pbs_ws_advance - la_a3 &aux_tmp - st_t1,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - bne_a0,t0 - la_a2 &cur_line - la_a0 &aux_tmp - st_a2,a0,0 - ld_t2,a0,0 + bne_a0,t1 + la_a1 &cur_line + ld_t2,a1,0 addi_t2,t2,1 - st_t2,a2,0 + st_t2,a1,0 :pbs_ws_advance - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 addi_t0,t0,1 - st_t0,a3,0 + st_t0,a0,0 la_br &pbs_loop b :pbs_consume_comment @@ -1483,19 +1241,19 @@ DEFINE OFF_labels 0048000009800000 la_br &pbs_loop beq_a0,t1 addi_t0,t0,1 - st_t0,a0,0 + la_a1 &scan_pos + st_t0,a1,0 la_br &pbs_cc_loop b :pbs_done la_a0 &pbs_have ld_t0,a0,0 - la_br &err_pbs_incomplete + la_br &err_byte_stream_short bnez_t0 eret -## parse_one_byte(a0=out_byte_addr): read a single byte literal (exactly -## byte_digit_count contiguous digits, no internal whitespace). Fatal on -## malformed input. +## parse_one_byte(a0=out_addr): read a single byte literal (exactly +## byte_digit_count contiguous digits, no internal whitespace). :parse_one_byte enter_0 la_a1 &p1b_out @@ -1505,33 +1263,26 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 la_a1 &p1b_have st_t0,a1,0 - la_a1 &p1b_done - st_t0,a1,0 :p1b_loop - la_a0 &p1b_done - ld_t0,a0,0 - la_br &p1b_finish - bnez_t0 la_a0 &scan_pos ld_t0,a0,0 la_a1 &scan_end ld_t1,a1,0 - la_br &p1b_finish + la_br &p1b_done beq_t0,t1 - la_br &p1b_finish + la_br &p1b_done blt_t1,t0 lb_a0,t0,0 la_br &is_byte_digit call - la_br &p1b_finish + la_br &p1b_done beqz_a0 - la_a3 &scan_pos - la_a0 &aux_tmp - st_a3,a0,0 + la_a0 &scan_pos ld_t0,a0,0 lb_a0,t0,0 addi_t0,t0,1 - st_t0,a3,0 + la_a1 &scan_pos + st_t0,a1,0 la_a1 &p1b_c st_a0,a1,0 la_a1 &byte_mode @@ -1545,22 +1296,20 @@ DEFINE OFF_labels 0048000009800000 ld_a0,a1,0 la_br &byte_digit_value call - mov_t0,a0 - add_a3,a3,t0 + add_a3,a3,a0 la_a1 &p1b_acc st_a3,a1,0 la_br &p1b_bump b :p1b_bin + la_a1 &p1b_acc + ld_t0,a1,0 + shli_a3,t0,1 la_a1 &p1b_c ld_a0,a1,0 li_t1 %48 %0 sub_a0,a0,t1 - la_a1 &p1b_acc - ld_t0,a1,0 - shli_a3,t0,1 - mov_t0,a0 - add_a3,a3,t0 + add_a3,a3,a0 la_a1 &p1b_acc st_a3,a1,0 :p1b_bump @@ -1573,37 +1322,27 @@ DEFINE OFF_labels 0048000009800000 la_a1 &p1b_have ld_t0,a1,0 la_br &p1b_loop - la_a3 &aux_tmp - st_a0,a3,0 - ld_t1,a3,0 - bne_t0,t1 - # Got a full byte; record into *p1b_out and mark done. + bne_t0,a0 + # got full byte: write to *out_addr and return la_a1 &p1b_acc - ld_t2,a1,0 - andi_a3,t2,255 - la_a0 &p1b_out - ld_a0,a0,0 - sb_a3,a0,0 - li_t0 %1 %0 - la_a1 &p1b_done - st_t0,a1,0 - la_br &p1b_loop - b -:p1b_finish - la_a1 &p1b_done - ld_t0,a1,0 - la_br &err_byte_lit_bad - beqz_t0 - la_a1 &p1b_have - ld_t0,a1,0 + ld_a0,a1,0 + andi_a0,a0,255 + la_a1 &p1b_out + ld_a1,a1,0 + sb_a0,a1,0 + eret +:p1b_done + la_a0 &p1b_have + ld_t0,a0,0 la_br &err_byte_lit_bad bnez_t0 - eret + la_br &err_byte_lit_bad + b ## --- Label table ----------------------------------------------------------- ## intern(a0=src, a1=len) -> a0=offset into text_buf. Copies bytes plus a -## NUL terminator. Fatal on overflow. +## NUL terminator. :intern enter_0 la_a2 &intern_src @@ -1615,22 +1354,17 @@ DEFINE OFF_labels 0048000009800000 la_a2 &intern_orig st_a3,a2,0 # if (text_used + len + 1 > TEXT_CAP) fatal - add_a2,a1,a3 # a2 = a1 + a3 = len + text_used + add_a2,a3,a1 addi_a2,a2,1 li_t0 H2_TEXT_CAP la_br &err_text_overflow - mov_t1,a0 - blt_t0,t1 - # dst = text_buf + text_used. There's no add_a0,a0,a3 in the seed, - # so route the offset through t0. + blt_t0,a2 + # dst = text_buf + text_used la_a0 &text_buf_ptr ld_a0,a0,0 - la_a2 &intern_orig - ld_t0,a2,0 - add_a0,a0,t0 + add_a0,a0,a3 la_a2 &intern_dst st_a0,a2,0 - # copy len bytes li_t0 %0 %0 la_a1 &intern_i st_t0,a1,0 @@ -1655,12 +1389,12 @@ DEFINE OFF_labels 0048000009800000 la_br &intern_copy_loop b :intern_copy_done - # NUL terminator at dst[len] + # NUL terminator la_a2 &intern_dst ld_a2,a2,0 la_a1 &intern_len ld_t0,a1,0 - add_a2,a2,t0 # available add_a2,a2,t0 + add_a2,a2,t0 li_t1 %0 %0 sb_t1,a2,0 # text_used += len + 1 @@ -1671,33 +1405,20 @@ DEFINE OFF_labels 0048000009800000 add_a3,a3,a1 addi_a3,a3,1 st_a3,a2,0 - # return original text_used la_a0 &intern_orig ld_a0,a0,0 eret -## label_addr(a0=index) -> a0 = &labels[index]. Leaf. labels are 32 B. -## Result is shipped through la_const_32 since neither mov_a0,a2 nor an -## add_a0,a*,t* combo with the right operands exists in the seed table. +## label_addr(a0=index) -> a0 = &labels[index]. Each label is 32 B. :label_addr - mov_t0,a0 - la_a3 &la_const_32 - li_t1 %32 %0 - st_t1,a3,0 - la_a1 &aux_tmp - st_a3,a1,0 + li_t0 %32 %0 + mul_a0,a0,t0 + la_a1 &labels_ptr ld_a1,a1,0 - mul_t0,t0,a1 # t0 = 32 * index - la_a2 &labels_ptr - ld_a2,a2,0 - add_a2,a2,t0 # a2 = labels + 32*index - la_a3 &la_const_32 - st_a2,a3,0 # spill result - ld_a0,a3,0 # reload into a0 + add_a0,a0,a1 ret -## name_eq(a0=label_addr, a1=src, a2=len) -> a0=0/1. Compares the label's -## interned name against (src, len). Leaf-ish (calls mem_eq). +## name_eq(a0=label_ptr, a1=src, a2=len) -> a0=0/1. :name_eq enter_0 la_a3 &ne_label @@ -1709,18 +1430,14 @@ DEFINE OFF_labels 0048000009800000 # if (label->name_len != len) return 0 ld_t0,a0,8 la_br &ne_no - la_a3 &aux_tmp - st_a2,a3,0 - ld_t1,a3,0 - bne_t0,t1 - # bytes - ld_a3,a0,0 # name_off + bne_t0,a2 + # bytes equal? + la_a0 &ne_label + ld_a0,a0,0 + ld_a3,a0,0 la_a0 &text_buf_ptr ld_a0,a0,0 - la_a2 &ne_tmp - st_a3,a2,0 - ld_t0,a2,0 - add_a0,a0,t0 + add_a0,a0,a3 la_a1 &ne_src ld_a1,a1,0 la_a2 &ne_len @@ -1732,8 +1449,7 @@ DEFINE OFF_labels 0048000009800000 li_a0 %0 %0 eret -## define_label(a0=src, a1=len, a2=scope_id): record at labels[label_count]. -## Fatal on duplicate (within same scope) or overflow. +## define_label(a0=src, a1=len, a2=scope_id). :define_label enter_0 la_a3 &dl_src @@ -1742,7 +1458,6 @@ DEFINE OFF_labels 0048000009800000 st_a1,a3,0 la_a3 &dl_scope st_a2,a3,0 - li_t0 %0 %0 la_a0 &dl_i st_t0,a0,0 @@ -1756,15 +1471,10 @@ DEFINE OFF_labels 0048000009800000 mov_a0,t0 la_br &label_addr call - # a0 = &labels[i] la_a3 &dl_label st_a0,a3,0 # scope match? - mov_a1,a0 - mov_a2,a1 - addi_a2,a2,24 - ld_a0,a2,0 - mov_t0,a0 + ld_t0,a0,24 la_a1 &dl_scope ld_t1,a1,0 la_br &dl_dup_next @@ -1790,7 +1500,6 @@ DEFINE OFF_labels 0048000009800000 la_br &dl_dup_loop b :dl_dup_done - la_a0 &label_count ld_t0,a0,0 li_t1 H2_LABEL_CAP @@ -1798,7 +1507,6 @@ DEFINE OFF_labels 0048000009800000 beq_t0,t1 la_br &err_too_many_labels blt_t1,t0 - # name_off = intern(src, len) la_a0 &dl_src ld_a0,a0,0 @@ -1808,7 +1516,6 @@ DEFINE OFF_labels 0048000009800000 call la_a3 &dl_name_off st_a0,a3,0 - # &labels[label_count] la_a0 &label_count ld_a0,a0,0 @@ -1820,14 +1527,10 @@ DEFINE OFF_labels 0048000009800000 la_a1 &dl_name_off ld_t0,a1,0 st_t0,a0,0 - # name_len: st_t0,a0,8 is missing from the seed; the equivalent - # st_t0,a3,8 IS available, so move the base to a3 first via the - # dl_label scratch slot. - la_a3 &dl_label - ld_a3,a3,0 + # name_len la_a1 &dl_len ld_t0,a1,0 - st_t0,a3,8 + st_t0,a0,8 # target_ip la_a1 &ip ld_t0,a1,0 @@ -1843,26 +1546,20 @@ DEFINE OFF_labels 0048000009800000 st_t0,a0,0 eret -## lookup_label(a0=src, a1=len) -> a0=target_ip. Fatal on undefined. +## lookup_label(a0=src, a1=len) -> a0=target_ip. :lookup_label enter_0 la_a2 &ll_src st_a0,a2,0 la_a2 &ll_len st_a1,a2,0 - la_a3 &aux_tmp - st_a0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - lb_t0,t0,0 + # dotted? (first byte == '.' AND scope_depth > 0) + lb_t0,a0,0 li_t1 %46 %0 la_br &ll_undotted bne_t0,t1 - # Dotted but only meaningful inside a .scope; otherwise fall through - # to the global-name lookup. - la_a0 &scope_depth - ld_t0,a0,0 + la_a3 &scope_depth + ld_t0,a3,0 la_br &ll_undotted beqz_t0 addi_t0,t0,neg1 @@ -1871,16 +1568,13 @@ DEFINE OFF_labels 0048000009800000 :ll_dot_outer la_a0 &ll_d ld_t0,a0,0 - la_br &ll_undefined_local + la_br &err_undefined_local bltz_t0 la_a1 &scope_stack_ptr ld_a1,a1,0 shli_t2,t0,3 - la_a3 &ll_tmp - st_t2,a3,0 - ld_t1,a3,0 - add_a1,a1,t1 - ld_t1,a1,0 # t1 = sid + add_a1,a1,t2 + ld_t1,a1,0 la_a0 &ll_sid st_t1,a0,0 li_t0 %0 %0 @@ -1898,11 +1592,7 @@ DEFINE OFF_labels 0048000009800000 call la_a3 &ll_label st_a0,a3,0 - mov_a1,a0 - mov_a2,a1 - addi_a2,a2,24 - ld_a0,a2,0 - mov_t0,a0 + ld_t0,a0,24 la_a1 &ll_sid ld_t1,a1,0 la_br &ll_dot_inner_next @@ -1919,7 +1609,7 @@ DEFINE OFF_labels 0048000009800000 beqz_a0 la_a0 &ll_label ld_a0,a0,0 - ld_a0,a0,16 # target_ip + ld_a0,a0,16 eret :ll_dot_inner_next la_a0 &ll_i @@ -1945,18 +1635,14 @@ DEFINE OFF_labels 0048000009800000 ld_t0,a0,0 la_a1 &label_count ld_t1,a1,0 - la_br &ll_undefined_global + la_br &err_undefined_label beq_t0,t1 mov_a0,t0 la_br &label_addr call la_a3 &ll_label st_a0,a3,0 - mov_a1,a0 - mov_a2,a1 - addi_a2,a2,24 - ld_a0,a2,0 - mov_t0,a0 + ld_t0,a0,24 la_br &ll_undotted_next bnez_t0 la_a0 &ll_label @@ -1980,23 +1666,15 @@ DEFINE OFF_labels 0048000009800000 st_t0,a0,0 la_br &ll_undotted_loop b -:ll_undefined_local - la_br &err_undefined_local - b -:ll_undefined_global - la_br &err_undefined_label - b - -## --- Reference processor ---------------------------------------------------- -## process_reference(): cur_sigil already set by the dispatcher; scan_pos -## already past the sigil byte. Reads label and (optional) -other, -## advances ip on pass 1, and emits the resolved value on pass 2. +## --- Reference processor --------------------------------------------------- +## process_reference(): cur_sigil already set; scan_pos already past sigil. +## Reads label and (optional) -other, advances ip on pass 1, emits on pass 2. :process_reference enter_0 la_br &set_sigil_info call - # Require non-terminator. + # require non-terminator (label name follows) la_a0 &scan_pos ld_t0,a0,0 la_a1 &scan_end @@ -2006,7 +1684,7 @@ DEFINE OFF_labels 0048000009800000 la_br &err_sigil_no_label blt_t1,t0 lb_a0,t0,0 - la_br &is_name_terminator_c + la_br &is_name_terminator call la_br &err_sigil_no_label bnez_a0 @@ -2021,8 +1699,7 @@ DEFINE OFF_labels 0048000009800000 li_t0 %0 %0 la_a0 &pr_has_other st_t0,a0,0 - # Optional separator (- or >) followed by OTHER. '>' is a synonym - # for '-', accepted for hex2 compatibility. + # optional '-' or '>' OTHER la_a0 &scan_pos ld_t0,a0,0 la_a1 &scan_end @@ -2032,19 +1709,19 @@ DEFINE OFF_labels 0048000009800000 la_br &pr_after_other blt_t1,t0 lb_a0,t0,0 - li_t1 %45 %0 # '-' + li_t1 %45 %0 la_br &pr_consume_sep beq_a0,t1 - li_t1 %62 %0 # '>' + li_t1 %62 %0 la_br &pr_consume_sep beq_a0,t1 la_br &pr_after_other b :pr_consume_sep - la_a1 &scan_pos - ld_t0,a1,0 + la_a0 &scan_pos + ld_t0,a0,0 addi_t0,t0,1 - st_t0,a1,0 + st_t0,a0,0 la_a1 &scan_end ld_t1,a1,0 la_br &err_minus_no_label @@ -2052,7 +1729,7 @@ DEFINE OFF_labels 0048000009800000 la_br &err_minus_no_label blt_t1,t0 lb_a0,t0,0 - la_br &is_name_terminator_c + la_br &is_name_terminator call la_br &err_minus_no_label bnez_a0 @@ -2072,17 +1749,11 @@ DEFINE OFF_labels 0048000009800000 li_t1 %1 %0 la_br &pr_pass2 bne_t0,t1 - # ip += pr_width. Route width through t2 since add_t1,t1,t* (t* in - # {t0,t2}) is the only fitting form in the seed. + # ip += pr_width la_a0 &ip ld_t1,a0,0 la_a1 &pr_width - ld_t0,a1,0 - la_a3 &pr_tmp - st_t0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t2,a0,0 + ld_t2,a1,0 add_t1,t1,t2 st_t1,a0,0 eret @@ -2105,16 +1776,11 @@ DEFINE OFF_labels 0048000009800000 ld_a1,a1,0 la_br &lookup_label call - la_a1 &pr_t_other - st_a0,a1,0 - # value = t_label - t_other - la_a0 &pr_t_label - ld_a1,a0,0 - la_a0 &pr_t_other - ld_a0,a0,0 - sub_a2,a1,a0 # available: a2 = a1 - a0 + la_a1 &pr_t_label + ld_a1,a1,0 + sub_a0,a1,a0 la_a1 &pr_value - st_a2,a1,0 + st_a0,a1,0 la_br &pr_emit b :pr_no_other @@ -2125,20 +1791,14 @@ DEFINE OFF_labels 0048000009800000 # rel: value = t_label - (ip + width) la_a0 &ip ld_a1,a0,0 - la_a3 &pr_tmp la_a0 &pr_width ld_t0,a0,0 - st_t0,a3,0 - ld_a0,a3,0 # a0 = width - add_a1,a1,a0 # add_a1,a1,a0 — available - la_a3 &pr_tmp - st_a1,a3,0 # save (ip + width) + add_a1,a1,t0 la_a0 &pr_t_label - ld_a1,a0,0 # a1 = t_label - ld_a0,a3,0 # a0 = ip+width - sub_a2,a1,a0 + ld_a0,a0,0 + sub_a0,a0,a1 la_a1 &pr_value - st_a2,a1,0 + st_a0,a1,0 la_br &pr_emit b :pr_abs @@ -2151,8 +1811,6 @@ DEFINE OFF_labels 0048000009800000 la_a3 &pr_value st_a1,a3,0 :pr_emit - la_a0 &pr_value - ld_a0,a0,0 la_a1 &pr_width ld_a1,a1,0 la_a2 &pr_lo @@ -2161,7 +1819,6 @@ DEFINE OFF_labels 0048000009800000 ld_a3,a3,0 la_a0 &pr_range_check ld_t0,a0,0 - # Reload value into a0 since we just clobbered it. la_a0 &pr_value ld_a0,a0,0 la_br &emit_value @@ -2170,14 +1827,6 @@ DEFINE OFF_labels 0048000009800000 ## set_sigil_info(): reads cur_sigil; populates pr_width / pr_is_rel / ## pr_lo / pr_hi / pr_range_check. -## -## Sigil table: -## '!' (0x21): width=1, rel, lo=-128, hi=127, check -## '@' (0x40): width=2, rel, lo=-32768, hi=32767, check -## '$' (0x24): width=2, abs, lo=0, hi=65535, check -## '~' (0x7E): width=3, rel, lo=-(1<<23), hi=(1<<23)-1, check -## '%' (0x25): width=4, rel, no range check -## '&' (0x26): width=4, abs, no range check :set_sigil_info enter_0 la_a0 &cur_sigil @@ -2210,15 +1859,11 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 la_a1 &pr_range_check st_t0,a1,0 - # lo = -128 = 0 - 128 li_t0 %128 %0 - la_a3 &ssi_tmp - st_t0,a3,0 - ld_a3,a3,0 # a3 = 128 - li_t0 %0 %0 - sub_a3,t0,a3 # available: a3 = t0 - a3 = -128 + li_t1 %0 %0 + sub_t0,t1,t0 la_a1 &pr_lo - st_a3,a1,0 + st_t0,a1,0 li_t0 %127 %0 la_a1 &pr_hi st_t0,a1,0 @@ -2232,28 +1877,17 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 la_a1 &pr_range_check st_t0,a1,0 - # 32768 = 256 * 128. The seed has no immediate >= 256 in li_t* (it - # does, since li_t0 takes a 64-bit value, but we use the available - # %256 word literal). Stage values through ssi_tmp before each ld. + # 32768 = 256 * 128 li_t0 %256 %0 - la_a1 &ssi_tmp - st_t0,a1,0 - ld_a3,a1,0 # a3 = 256 - li_t0 %128 %0 - st_t0,a1,0 - ld_a2,a1,0 # a2 = 128 - mul_a3,a3,a2 # a3 = 32768 - la_a1 &ssi_tmp2 - st_a3,a1,0 - li_t0 %0 %0 - sub_a3,t0,a3 # a3 = -32768 + li_t1 %128 %0 + mul_t0,t0,t1 + li_t1 %0 %0 + sub_t1,t1,t0 la_a1 &pr_lo - st_a3,a1,0 - la_a1 &ssi_tmp2 - ld_t1,a1,0 - addi_t1,t1,neg1 # 32767 - la_a1 &pr_hi st_t1,a1,0 + addi_t0,t0,neg1 + la_a1 &pr_hi + st_t0,a1,0 eret :ssi_dollar li_t0 %2 %0 @@ -2270,17 +1904,11 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 # 65536 = 256 * 256 li_t0 %256 %0 - la_a1 &ssi_tmp - st_t0,a1,0 - ld_a3,a1,0 - ld_a2,a1,0 - mul_a3,a3,a2 # a3 = 65536 - la_a1 &ssi_tmp2 - st_a3,a1,0 - ld_t1,a1,0 - addi_t1,t1,neg1 # 65535 + mov_t1,t0 + mul_t0,t0,t1 + addi_t0,t0,neg1 la_a1 &pr_hi - st_t1,a1,0 + st_t0,a1,0 eret :ssi_tilde li_t0 %3 %0 @@ -2289,30 +1917,21 @@ DEFINE OFF_labels 0048000009800000 li_t0 %1 %0 la_a1 &pr_is_rel st_t0,a1,0 - la_a1 &pr_range_check - st_t0,a1,0 - # 8388608 = 256 * 256 * 128 - li_t0 %256 %0 - la_a1 &ssi_tmp - st_t0,a1,0 - ld_a3,a1,0 - ld_a2,a1,0 - mul_a3,a3,a2 # 65536 - li_t0 %128 %0 - st_t0,a1,0 - ld_a2,a1,0 - mul_a3,a3,a2 # 8388608 - la_a1 &ssi_tmp2 - st_a3,a1,0 - li_t0 %0 %0 - sub_a3,t0,a3 # -8388608 + la_a1 &pr_range_check + st_t0,a1,0 + # 8388608 = 256 * 256 * 128 + li_t0 %256 %0 + mov_t1,t0 + mul_t0,t0,t1 + li_t1 %128 %0 + mul_t0,t0,t1 + li_t1 %0 %0 + sub_t1,t1,t0 la_a1 &pr_lo - st_a3,a1,0 - la_a1 &ssi_tmp2 - ld_t1,a1,0 - addi_t1,t1,neg1 # 8388607 - la_a1 &pr_hi st_t1,a1,0 + addi_t0,t0,neg1 + la_a1 &pr_hi + st_t0,a1,0 eret :ssi_pct la_a0 &ptrsize @@ -2322,7 +1941,6 @@ DEFINE OFF_labels 0048000009800000 li_t0 %1 %0 la_a1 &pr_is_rel st_t0,a1,0 - li_t0 %1 %0 la_a1 &ptrsize_used st_t0,a1,0 li_t0 %0 %0 @@ -2352,10 +1970,9 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 eret -## --- Directives ------------------------------------------------------------- +## --- Directives ------------------------------------------------------------ -## do_align(): .align N [PATTERN]. N is a positive power of two; optional -## byte-mode pattern. Pads with zeros if no pattern. +## do_align(): .align N [PATTERN]. N positive power of two; optional pattern. :do_align enter_0 la_br &skip_inline_ws @@ -2368,26 +1985,22 @@ DEFINE OFF_labels 0048000009800000 beqz_a0 la_br &err_align_n bltz_a0 - # Power-of-two check: N & (N-1) == 0 + # power-of-two: N & (N-1) == 0 la_a0 &da_n ld_a3,a0,0 + addi_a3,a3,neg1 la_a0 &da_n ld_a2,a0,0 - addi_a2,a2,neg1 and_a3,a3,a2 la_br &err_align_n - mov_a0,a3 - bnez_a0 - + bnez_a3 li_t0 %0 %0 la_a0 &da_has_pat st_t0,a0,0 la_a0 &da_patlen st_t0,a0,0 - la_br &skip_inline_ws call - la_a0 &scan_pos ld_t0,a0,0 la_a1 &scan_end @@ -2440,17 +2053,13 @@ DEFINE OFF_labels 0048000009800000 ld_a0,a0,0 la_a1 &da_n ld_a1,a1,0 - rem_a2,a0,a1 # a2 = ip mod N + rem_a2,a0,a1 li_t0 %0 %0 la_a3 &da_pad st_t0,a3,0 la_br &da_emit beqz_a2 - # pad = N - r - la_a3 &da_pad - st_a1,a3,0 # store N - ld_a3,a3,0 # a3 = N - sub_a3,a3,a2 # a3 = N - r + sub_a3,a1,a2 la_a1 &da_pad st_a3,a1,0 :da_emit @@ -2496,7 +2105,7 @@ DEFINE OFF_labels 0048000009800000 :da_emit_done eret -## do_fill(): .fill N B. N >= 0 decimal; B is one byte literal. +## do_fill(): .fill N B. :do_fill enter_0 la_br &skip_inline_ws @@ -2554,16 +2163,25 @@ DEFINE OFF_labels 0048000009800000 la_a1 &scope_stack_ptr ld_a1,a1,0 shli_t2,t0,3 - add_a1,t2,a1 # available + add_a1,a1,t2 st_t1,a1,0 addi_t0,t0,1 la_a0 &scope_depth st_t0,a0,0 eret -## do_ptrsize(): .ptrsize N -- N must be 4 or 8. Whole-invocation: the -## first directive (or first '&'/'%' use) binds the width; later ones -## must match the bound value. +## do_scope_close(): scope_depth--. +:do_scope_close + enter_0 + la_a0 &scope_depth + ld_t0,a0,0 + la_br &err_scope_underflow + beqz_t0 + addi_t0,t0,neg1 + st_t0,a0,0 + eret + +## do_ptrsize(): .ptrsize N -- N must be 4 or 8. :do_ptrsize enter_0 la_br &skip_inline_ws @@ -2572,17 +2190,15 @@ DEFINE OFF_labels 0048000009800000 call la_a1 &dp_n st_a0,a1,0 - # Validate N in {4, 8} li_t0 %4 %0 - la_br &dp_ok_value + la_br &dp_ok beq_a0,t0 li_t0 %8 %0 - la_br &dp_ok_value + la_br &dp_ok beq_a0,t0 la_br &err_ptrsize_bad b -:dp_ok_value - # If a '&'/'%' has already used ptrsize, N must equal current ptrsize. +:dp_ok la_a0 &ptrsize_used ld_t0,a0,0 la_br &dp_set @@ -2601,26 +2217,14 @@ DEFINE OFF_labels 0048000009800000 st_t0,a1,0 eret -## do_scope_close(): scope_depth--; fatal if not in scope. -:do_scope_close - enter_0 - la_a0 &scope_depth - ld_t0,a0,0 - la_br &err_scope_underflow - beqz_t0 - addi_t0,t0,neg1 - st_t0,a0,0 - eret - -## --- Emit ------------------------------------------------------------------- +## --- Emit ------------------------------------------------------------------ ## emit_byte(a0=byte): pass 1 only bumps ip; pass 2 also writes to output_buf. -## Leaf. :emit_byte la_a1 &pass ld_t0,a1,0 li_t1 %2 %0 - la_br &eb_pass1 + la_br &eb_after_write bne_t0,t1 la_a1 &output_used ld_t0,a1,0 @@ -2635,30 +2239,25 @@ DEFINE OFF_labels 0048000009800000 sb_a0,a2,0 addi_t0,t0,1 st_t0,a1,0 -:eb_pass1 +:eb_after_write la_a0 &ip ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 ret -## emit_value(a0=value, a1=width, a2=lo, a3=hi, t0=range_check). Range-checks -## (if requested), packs little-endian into ev_bytes[0..width-1], then emits -## (in reverse order if big_endian). +## emit_value(a0=value, a1=width, a2=lo, a3=hi, t0=range_check). Range-checks, +## packs little-endian into ev_bytes[0..width-1], emits in LE/BE order. :emit_value enter_0 la_t1 &ev_value - mov_t2,t1 - st_a0,t2,0 + st_a0,t1,0 la_t1 &ev_width st_a1,t1,0 la_t1 &ev_lo st_a2,t1,0 la_t1 &ev_hi - la_a0 &aux_tmp - st_t1,a0,0 - ld_a0,a0,0 - st_a3,a0,0 + st_a3,t1,0 la_t1 &ev_range_check st_t0,t1,0 @@ -2671,8 +2270,7 @@ DEFINE OFF_labels 0048000009800000 la_a1 &ev_lo ld_a1,a1,0 la_br &err_ref_out_of_range - mov_a2,a1 - blt_a0,a2 + blt_a0,a1 la_a0 &ev_value ld_a0,a0,0 la_a1 &ev_hi @@ -2695,8 +2293,8 @@ DEFINE OFF_labels 0048000009800000 la_br &ev_emit_dispatch beq_t0,t1 la_a1 &ev_pack_v - ld_t2,a1,0 - andi_a3,t2,255 + ld_a3,a1,0 + andi_a3,a3,255 la_a2 &ev_bytes_ptr ld_a2,a2,0 add_a2,a2,t0 @@ -2728,10 +2326,7 @@ DEFINE OFF_labels 0048000009800000 la_a2 &ev_bytes_ptr ld_a2,a2,0 add_a2,a2,t0 - la_a3 &aux_tmp - st_a2,a3,0 - ld_a0,a3,0 - lb_a0,a0,0 + lb_a0,a2,0 la_br &emit_byte call la_a0 &ev_i @@ -2754,10 +2349,7 @@ DEFINE OFF_labels 0048000009800000 la_a2 &ev_bytes_ptr ld_a2,a2,0 add_a2,a2,t0 - la_a3 &aux_tmp - st_a2,a3,0 - ld_a0,a3,0 - lb_a0,a0,0 + lb_a0,a2,0 la_br &emit_byte call la_a0 &ev_i @@ -2769,10 +2361,63 @@ DEFINE OFF_labels 0048000009800000 :ev_done eret -## --- Misc helpers ----------------------------------------------------------- +## --- Output writer --------------------------------------------------------- +:write_output + enter_0 + la_a0 &output_path + ld_a2,a0,0 + li_a0 sys_openat + li_a1 H2_AT_FDCWD + li_a3 H2_O_WRONLY_CREAT_TRUNC + la_t1 &non_executable + ld_t1,t1,0 + la_br &wo_mode_nonexec + bnez_t1 + li_t0 H2_MODE_0750 + la_br &wo_after_mode + b +:wo_mode_nonexec + li_t0 H2_MODE_0640 +:wo_after_mode + syscall + la_br &err_open_output + bltz_a0 + la_a1 &output_fd + st_a0,a1,0 + li_t0 %0 %0 + la_a1 &output_written + st_t0,a1,0 +:wo_loop + la_a0 &output_written + ld_t0,a0,0 + la_a1 &output_used + ld_t1,a1,0 + la_br &wo_done + beq_t0,t1 + la_a0 &output_fd + ld_a1,a0,0 + la_a2 &output_buf_ptr + ld_a2,a2,0 + add_a2,a2,t0 + sub_a3,t1,t0 + li_a0 sys_write + syscall + la_br &err_write + bltz_a0 + la_br &err_write + beqz_a0 + la_a1 &output_written + ld_t0,a1,0 + add_t0,t0,a0 + st_t0,a1,0 + la_br &wo_loop + b +:wo_done + eret + +## --- Misc helpers ---------------------------------------------------------- -## str_eq(a0=p, a1=q, a2=len) -> a0=0/1. Returns 1 iff p[0..len-1] == q[..] -## AND p[len] == '\0'. Used for argv string compares. +## str_eq(a0=p, a1=q, a2=len) -> a0=0/1. len bytes equal AND p[len]==NUL. :str_eq enter_0 la_t0 &se_p @@ -2790,18 +2435,13 @@ DEFINE OFF_labels 0048000009800000 la_a0 &se_p ld_a0,a0,0 add_a0,a0,t1 - lb_a0,a0,0 + lb_t0,a0,0 la_a2 &se_q ld_a2,a2,0 add_a2,a2,t1 - lb_a2,a2,0 + lb_t2,a2,0 la_br &se_no - la_a3 &aux_tmp - st_a2,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - bne_a0,t0 + bne_t0,t2 addi_t1,t1,1 la_br &se_loop b @@ -2809,16 +2449,16 @@ DEFINE OFF_labels 0048000009800000 la_a0 &se_p ld_a0,a0,0 add_a0,a0,t1 - lb_a0,a0,0 + lb_t0,a0,0 la_br &se_no - bnez_a0 + bnez_t0 li_a0 %1 %0 eret :se_no li_a0 %0 %0 eret -## mem_eq(a0=p, a1=q, a2=len) -> a0=0/1. Plain byte compare, no NUL check. +## mem_eq(a0=p, a1=q, a2=len) -> a0=0/1. :mem_eq enter_0 la_t0 &me_p @@ -2836,18 +2476,13 @@ DEFINE OFF_labels 0048000009800000 la_a0 &me_p ld_a0,a0,0 add_a0,a0,t1 - lb_a0,a0,0 + lb_t0,a0,0 la_a2 &me_q ld_a2,a2,0 add_a2,a2,t1 - lb_a2,a2,0 + lb_t2,a2,0 la_br &me_no - la_a3 &aux_tmp - st_a2,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - bne_a0,t0 + bne_t0,t2 addi_t1,t1,1 la_br &me_loop b @@ -2858,104 +2493,104 @@ DEFINE OFF_labels 0048000009800000 li_a0 %0 %0 eret -## parse_long_arg(a0=str): parse decimal or 0x-prefixed hex i64. Fatal on -## malformed. -:parse_long_arg +## parse_long(a0=cstr) -> a0=value. Decimal or 0x-prefixed hex i64. +:parse_long enter_0 - la_t0 &pla_p + la_t0 &pl_p st_a0,t0,0 li_t0 %0 %0 - la_a1 &pla_val + la_a1 &pl_val st_t0,a1,0 - la_a1 &pla_neg + la_a1 &pl_neg st_t0,a1,0 - # detect 0x / 0X - la_a0 &pla_p + # 0x / 0X prefix? + la_a0 &pl_p ld_a0,a0,0 - la_a3 &aux_tmp - st_a0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - lb_t0,t0,0 + lb_t0,a0,0 li_t1 %48 %0 - la_br &pla_dec_init + la_br &pl_dec_init bne_t0,t1 - la_a3 &aux_tmp - st_a0,a3,0 - ld_a3,a3,0 - lb_t0,a3,1 + lb_t0,a0,1 li_t1 %120 %0 - la_br &pla_hex_init + la_br &pl_hex_init beq_t0,t1 li_t1 %88 %0 - la_br &pla_hex_init + la_br &pl_hex_init beq_t0,t1 - la_br &pla_dec_init + la_br &pl_dec_init b -:pla_hex_init - la_a0 &pla_p +:pl_hex_init + la_a0 &pl_p ld_t0,a0,0 - addi_t0,t0,2 # skip "0x" / "0X" + addi_t0,t0,2 st_t0,a0,0 -:pla_hex_loop - la_a0 &pla_p - ld_a0,a0,0 - la_a3 &aux_tmp - st_a0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 +:pl_hex_loop + la_a0 &pl_p ld_t0,a0,0 lb_t0,t0,0 - la_br &pla_finish + la_br &pl_finish beqz_t0 - la_a3 &pla_tmp - st_t0,a3,0 - ld_a0,a3,0 # a0 = c + # accept '0'..'9' / 'A'..'F' / 'a'..'f'; reject anything else + li_t1 %48 %0 + la_br &err_bad_long + blt_t0,t1 + li_t1 %57 %0 + la_br &pl_hex_acc + blt_t0,t1 + la_br &pl_hex_acc + beq_t0,t1 + li_t1 %65 %0 + la_br &err_bad_long + blt_t0,t1 + li_t1 %70 %0 + la_br &pl_hex_acc + blt_t0,t1 + la_br &pl_hex_acc + beq_t0,t1 + li_t1 %97 %0 + la_br &err_bad_long + blt_t0,t1 + li_t1 %102 %0 + la_br &pl_hex_acc + blt_t0,t1 + la_br &pl_hex_acc + beq_t0,t1 + la_br &err_bad_long + b +:pl_hex_acc + mov_a0,t0 la_br &byte_digit_value call - la_a1 &pla_val + la_a1 &pl_val ld_t0,a1,0 - shli_a3,t0,4 # a3 = val << 4 - mov_t0,a0 - add_a3,a3,t0 - st_a3,a1,0 - la_a0 &pla_p + shli_t0,t0,4 + add_t0,t0,a0 + st_t0,a1,0 + la_a0 &pl_p ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 - la_br &pla_hex_loop + la_br &pl_hex_loop b -:pla_dec_init - # Optional minus - la_a0 &pla_p +:pl_dec_init + la_a0 &pl_p ld_a0,a0,0 - la_a3 &aux_tmp - st_a0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 - ld_t0,a0,0 - lb_t0,t0,0 + lb_t0,a0,0 li_t1 %45 %0 - la_br &pla_dec_loop + la_br &pl_dec_loop bne_t0,t1 li_t0 %1 %0 - la_a1 &pla_neg + la_a1 &pl_neg st_t0,a1,0 - la_a0 &pla_p + la_a0 &pl_p ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 -:pla_dec_loop - la_a0 &pla_p - ld_a0,a0,0 - la_a3 &aux_tmp - st_a0,a3,0 - la_a0 &aux_tmp - st_a3,a0,0 +:pl_dec_loop + la_a0 &pl_p ld_t0,a0,0 lb_t0,t0,0 - la_br &pla_finish + la_br &pl_finish beqz_t0 li_t1 %48 %0 la_br &err_bad_long @@ -2963,107 +2598,41 @@ DEFINE OFF_labels 0048000009800000 li_t1 %57 %0 la_br &err_bad_long blt_t1,t0 - la_a3 &pla_tmp - li_t1 %10 %0 - st_t1,a3,0 - la_a1 &aux_tmp - st_a3,a1,0 - ld_a1,a1,0 - la_a2 &pla_val - ld_t0,a2,0 - mul_t0,t0,a1 # t0 = val * 10 - la_a0 &pla_p - ld_a0,a0,0 - lb_a0,a0,0 li_t1 %48 %0 - sub_a0,a0,t1 - add_t0,t0,a0 - la_a2 &pla_val - st_t0,a2,0 - la_a0 &pla_p + sub_t0,t0,t1 + la_a1 &pl_val + ld_a2,a1,0 + li_t1 %10 %0 + mul_a2,a2,t1 + add_a2,a2,t0 + st_a2,a1,0 + la_a0 &pl_p ld_t0,a0,0 addi_t0,t0,1 st_t0,a0,0 - la_br &pla_dec_loop + la_br &pl_dec_loop b -:pla_finish - la_a1 &pla_neg +:pl_finish + la_a1 &pl_neg ld_t0,a1,0 - la_br &pla_done + la_br &pl_done beqz_t0 - la_a2 &pla_val - ld_a3,a2,0 + la_a1 &pl_val + ld_a3,a1,0 li_t0 %0 %0 - sub_a3,t0,a3 # a3 = -val - st_a3,a2,0 -:pla_done - la_a1 &pla_val + sub_a3,t0,a3 + st_a3,a1,0 +:pl_done + la_a1 &pl_val ld_a0,a1,0 eret -## --- Output writer ---------------------------------------------------------- - -## write_output(): openat(output_path, O_WRONLY|O_CREAT|O_TRUNC, MODE). -## MODE = 0750 unless --non-executable, then 0640. Then write loop. -:write_output - enter_0 - la_a0 &output_path - ld_a2,a0,0 - li_a0 sys_openat - li_a1 AT_FDCWD - li_a3 O_WRONLY_CREAT_TRUNC - la_t1 &non_executable - ld_t1,t1,0 - la_br &wo_mode_nonexec - bnez_t1 - li_t0 MODE_0750 - la_br &wo_after_mode - b -:wo_mode_nonexec - li_t0 MODE_0640 -:wo_after_mode - syscall - la_br &err_open_output - bltz_a0 - la_a1 &output_fd - st_a0,a1,0 - li_t0 %0 %0 - la_a1 &output_written - st_t0,a1,0 -:wo_loop - la_a0 &output_written - ld_t0,a0,0 - la_a1 &output_used - ld_t1,a1,0 - la_br &wo_done - beq_t0,t1 - la_a0 &output_fd - ld_a1,a0,0 - la_a2 &output_buf_ptr - ld_a2,a2,0 - add_a2,a2,t0 - sub_a3,t1,t0 # available - li_a0 sys_write - syscall - la_br &err_write - bltz_a0 - la_br &err_write - beqz_a0 - la_a1 &output_written - ld_t0,a1,0 - add_t0,t0,a0 - st_t0,a1,0 - la_br &wo_loop - b -:wo_done - eret - -## --- Errors ----------------------------------------------------------------- +## --- Errors ---------------------------------------------------------------- -## fatal_msg(a0=msg_ptr): write either "hex2pp: <msg>\n" or -## "<path>:<line>: hex2pp: <msg>\n" to stderr, then exit(1). -:fatal_msg - la_a1 &err_saved_msg +## fatal(a0=msg_ptr): writes "<path>:<line>: hex2pp: <msg>\n" to stderr if +## cur_path is set, else "hex2pp: <msg>\n", then exits 1. +:fatal + la_a1 &fm_msg st_a0,a1,0 la_a0 &cur_path ld_t0,a0,0 @@ -3071,32 +2640,32 @@ DEFINE OFF_labels 0048000009800000 beqz_t0 # write path mov_a0,t0 - la_br &strlen_cstr + la_br &cstrlen call - la_a2 &err_saved_len - st_a0,a2,0 + la_a3 &fm_tmp + st_a0,a3,0 la_a2 &cur_path ld_a2,a2,0 - la_a3 &err_saved_len + la_a3 &fm_tmp ld_a3,a3,0 li_a0 sys_write li_a1 %2 %0 syscall - # write ":" + # ":" li_a0 sys_write li_a1 %2 %0 la_a2 &str_colon li_a3 %1 %0 syscall - # write decimal(cur_line) + # decimal cur_line la_a0 &cur_line ld_a0,a0,0 la_br &write_decimal_stderr call - # write ": hex2pp: " + # ": hex2pp: " li_a0 sys_write li_a1 %2 %0 - la_a2 &str_colon_hex2pp + la_a2 &str_colon_prog li_a3 %10 %0 syscall la_br &fm_emit_msg @@ -3104,19 +2673,19 @@ DEFINE OFF_labels 0048000009800000 :fm_no_path li_a0 sys_write li_a1 %2 %0 - la_a2 &str_hex2pp + la_a2 &str_prog li_a3 %8 %0 syscall :fm_emit_msg - la_a0 &err_saved_msg + la_a0 &fm_msg ld_a0,a0,0 - la_br &strlen_cstr + la_br &cstrlen call - la_a2 &err_saved_len - st_a0,a2,0 - la_a2 &err_saved_msg + la_a3 &fm_tmp + st_a0,a3,0 + la_a2 &fm_msg ld_a2,a2,0 - la_a3 &err_saved_len + la_a3 &fm_tmp ld_a3,a3,0 li_a0 sys_write li_a1 %2 %0 @@ -3130,23 +2699,22 @@ DEFINE OFF_labels 0048000009800000 li_a1 %1 %0 syscall -## strlen_cstr(a0=p) -> a0=length. Walks until NUL. -:strlen_cstr +## cstrlen(a0=p) -> a0=length. Walks until NUL. +:cstrlen li_t0 %0 %0 -:sl_loop - add_t1,a0,t0 # available +:cs_loop + add_t1,a0,t0 lb_t1,t1,0 - la_br &sl_done + la_br &cs_done beqz_t1 addi_t0,t0,1 - la_br &sl_loop + la_br &cs_loop b -:sl_done +:cs_done mov_a0,t0 ret ## write_decimal_stderr(a0=value): write decimal of unsigned i64 to stderr. -## Special-cases zero. Uses line_scratch (64 B) as a reverse-fill buffer. :write_decimal_stderr enter_0 la_a1 &wd_v @@ -3160,7 +2728,6 @@ DEFINE OFF_labels 0048000009800000 syscall eret :wd_nonzero - # Render reversed into line_scratch[...], starting near the end. li_t0 %63 %0 la_a1 &wd_pos st_t0,a1,0 @@ -3169,18 +2736,13 @@ DEFINE OFF_labels 0048000009800000 ld_a0,a0,0 la_br &wd_emit beqz_a0 - la_a3 &wd_tmp li_t1 %10 %0 - st_t1,a3,0 - la_a1 &aux_tmp - st_a3,a1,0 - ld_a1,a1,0 - rem_a2,a0,a1 # a2 = v mod 10 - div_a0,a0,a1 # a0 = v / 10 + rem_a2,a0,t1 + div_a0,a0,t1 la_a3 &wd_v st_a0,a3,0 li_t1 %48 %0 - add_a3,t1,a2 # ascii = '0' + digit + add_a3,t1,a2 la_a0 &wd_pos ld_t0,a0,0 la_a1 &line_scratch_ptr @@ -3193,21 +2755,13 @@ DEFINE OFF_labels 0048000009800000 la_br &wd_loop b :wd_emit - # write(2, &line_scratch[wd_pos+1], 64 - (wd_pos+1)) — but wd_pos+1 - # is also our buffer offset, so length = 63 - wd_pos = 64 - (wd_pos+1). - # Route the buffer pointer (a1) through wd_tmp into a2 (no mov_a2,a1 - # in the seed table). la_a0 &wd_pos ld_t0,a0,0 addi_t0,t0,1 la_a1 &line_scratch_ptr ld_a1,a1,0 add_a1,a1,t0 - la_a3 &wd_tmp - st_a1,a3,0 - la_a2 &aux_tmp - st_a3,a2,0 - ld_a2,a2,0 + mov_a2,a1 li_t1 %64 %0 sub_a3,t1,t0 li_a0 sys_write @@ -3215,208 +2769,180 @@ DEFINE OFF_labels 0048000009800000 syscall eret -## print_usage(): write usage banner to stdout (fd=1). -:print_usage - enter_0 - la_a0 &msg_usage - la_br &strlen_cstr - call - la_a3 &pu_tmp - st_a0,a3,0 - la_a2 &msg_usage - ld_a3,a3,0 - li_a0 sys_write - li_a1 %1 %0 - syscall - eret - -## --- Error stubs ------------------------------------------------------------ +## --- Error stubs ----------------------------------------------------------- :err_unknown_arg la_a0 &msg_unknown_arg - la_br &fatal_msg + la_br &fatal b -:err_missing_arg_value - la_a0 &msg_missing_arg_value - la_br &fatal_msg +:err_extra_positional + la_a0 &msg_extra_positional + la_br &fatal b :err_missing_positional la_a0 &msg_missing_positional - la_br &fatal_msg - b -:err_no_inputs - la_a0 &msg_no_inputs - la_br &fatal_msg + la_br &fatal b -:err_too_many_files - la_a0 &msg_too_many_files - la_br &fatal_msg +:err_missing_value + la_a0 &msg_missing_value + la_br &fatal b :err_open_input la_a0 &msg_open_input - la_br &fatal_msg + la_br &fatal b :err_read la_a0 &msg_read - la_br &fatal_msg + la_br &fatal b :err_input_too_big la_a0 &msg_input_too_big - la_br &fatal_msg + la_br &fatal b :err_open_output la_a0 &msg_open_output - la_br &fatal_msg + la_br &fatal b :err_write la_a0 &msg_write - la_br &fatal_msg + la_br &fatal b :err_text_overflow la_a0 &msg_text_overflow - la_br &fatal_msg + la_br &fatal b :err_too_many_labels la_a0 &msg_too_many_labels - la_br &fatal_msg + la_br &fatal b :err_duplicate_label la_a0 &msg_duplicate_label - la_br &fatal_msg + la_br &fatal b :err_undefined_label la_a0 &msg_undefined_label - la_br &fatal_msg + la_br &fatal b :err_undefined_local la_a0 &msg_undefined_local - la_br &fatal_msg + la_br &fatal b :err_unexpected_char la_a0 &msg_unexpected_char - la_br &fatal_msg + la_br &fatal b :err_unknown_directive la_a0 &msg_unknown_directive - la_br &fatal_msg - b -:err_dotted_outside_scope - la_a0 &msg_dotted_outside_scope - la_br &fatal_msg + la_br &fatal b :err_scope_overflow la_a0 &msg_scope_overflow - la_br &fatal_msg + la_br &fatal b :err_scope_underflow la_a0 &msg_scope_underflow - la_br &fatal_msg + la_br &fatal b :err_scope_unclosed la_a0 &msg_scope_unclosed - la_br &fatal_msg + la_br &fatal b :err_align_n la_a0 &msg_align_n - la_br &fatal_msg + la_br &fatal b :err_fill_n la_a0 &msg_fill_n - la_br &fatal_msg + la_br &fatal b :err_pattern_too_large la_a0 &msg_pattern_too_large - la_br &fatal_msg + la_br &fatal b :err_byte_lit_bad la_a0 &msg_byte_lit_bad - la_br &fatal_msg + la_br &fatal b -:err_pbs_incomplete - la_a0 &msg_pbs_incomplete - la_br &fatal_msg +:err_byte_stream_short + la_a0 &msg_byte_stream_short + la_br &fatal b :err_sigil_no_label la_a0 &msg_sigil_no_label - la_br &fatal_msg + la_br &fatal b :err_minus_no_label la_a0 &msg_minus_no_label - la_br &fatal_msg + la_br &fatal b :err_bad_sigil la_a0 &msg_bad_sigil - la_br &fatal_msg + la_br &fatal b :err_ref_out_of_range la_a0 &msg_ref_out_of_range - la_br &fatal_msg + la_br &fatal b :err_name_too_long la_a0 &msg_name_too_long - la_br &fatal_msg + la_br &fatal b :err_empty_name la_a0 &msg_empty_name - la_br &fatal_msg + la_br &fatal b :err_empty_directive la_a0 &msg_empty_directive - la_br &fatal_msg + la_br &fatal b :err_expected_decimal la_a0 &msg_expected_decimal - la_br &fatal_msg + la_br &fatal b :err_output_overflow la_a0 &msg_output_overflow - la_br &fatal_msg + la_br &fatal b :err_bad_long la_a0 &msg_bad_long - la_br &fatal_msg + la_br &fatal b :err_ptrsize_bad la_a0 &msg_ptrsize_bad - la_br &fatal_msg + la_br &fatal b :err_ptrsize_conflict la_a0 &msg_ptrsize_conflict - la_br &fatal_msg + la_br &fatal b ## Sentinel: end of executable text. :_text_end -## --- Rodata ----------------------------------------------------------------- - -:const_a_out "a.out" '00' +## --- Rodata ---------------------------------------------------------------- -:opt_dash_B "-B" '00' -:opt_dash_E "-E" '00' -:opt_dash_e "-e" '00' -:opt_dash_b "-b" '00' -:opt_dash_N "-N" '00' +:opt_B "-B" '00' +:opt_E "-E" '00' +:opt_e "-e" '00' +:opt_b "-b" '00' +:opt_N "-N" '00' -:dir_align "align" -:dir_fill "fill" -:dir_scope "scope" -:dir_endscope "endscope" -:dir_ptrsize "ptrsize" +:kw_align "align" +:kw_fill "fill" +:kw_scope "scope" +:kw_endscope "endscope" +:kw_ptrsize "ptrsize" :str_colon ":" -:str_colon_hex2pp ": hex2pp: " -:str_hex2pp "hex2pp: " +:str_colon_prog ": hex2pp: " +:str_prog "hex2pp: " :str_newline " " :str_zero "0" -:msg_usage "usage: hex2pp [-B ADDR] [-E|-e] [-b] [-N] IN OUT -" '00' :msg_unknown_arg "unknown argument" '00' -:msg_missing_arg_value "missing value for option" '00' -:msg_no_inputs "no input files" '00' +:msg_extra_positional "extra positional argument" '00' :msg_missing_positional "missing IN or OUT positional argument" '00' -:msg_too_many_files "too many input files" '00' +:msg_missing_value "missing value for option" '00' :msg_open_input "failed to open input file" '00' :msg_read "failed to read input" '00' :msg_input_too_big "input too large" '00' @@ -3429,7 +2955,6 @@ DEFINE OFF_labels 0048000009800000 :msg_undefined_local "undefined local label" '00' :msg_unexpected_char "unexpected character" '00' :msg_unknown_directive "unknown directive" '00' -:msg_dotted_outside_scope "dot-prefixed label outside a .scope" '00' :msg_scope_overflow ".scope: depth overflow" '00' :msg_scope_underflow ".endscope: not in a scope" '00' :msg_scope_unclosed ".scope not closed at end of input" '00' @@ -3437,7 +2962,7 @@ DEFINE OFF_labels 0048000009800000 :msg_fill_n ".fill: N must be non-negative" '00' :msg_pattern_too_large "pattern too large" '00' :msg_byte_lit_bad "byte literal: bad digit count" '00' -:msg_pbs_incomplete "byte stream: incomplete digits at end of run" '00' +:msg_byte_stream_short "byte stream: incomplete digits at end of run" '00' :msg_sigil_no_label "sigil not followed by label name" '00' :msg_minus_no_label "'-' must be followed by label name" '00' :msg_bad_sigil "internal: bad sigil" '00' @@ -3451,26 +2976,23 @@ DEFINE OFF_labels 0048000009800000 :msg_ptrsize_bad ".ptrsize: N must be 4 or 8" '00' :msg_ptrsize_conflict ".ptrsize conflicts with already-used width" '00' -## --- BSS pointer-init table ------------------------------------------------ +## BSS pointer-slot init table. :bss_init_tbl -&input_paths_ptr ZERO4 OFF_input_paths -&input_starts_ptr ZERO4 OFF_input_starts -&input_lens_ptr ZERO4 OFF_input_lens -&scope_stack_ptr ZERO4 OFF_scope_stack -&line_scratch_ptr ZERO4 OFF_line_scratch -&name_buf_ptr ZERO4 OFF_name_buf -&label_buf_ptr ZERO4 OFF_label_buf -&other_buf_ptr ZERO4 OFF_other_buf -&pat_buf_ptr ZERO4 OFF_pat_buf -&ev_bytes_ptr ZERO4 OFF_ev_bytes -&df_byte_ptr ZERO4 OFF_df_byte -&input_buf_ptr ZERO4 OFF_input_buf -&output_buf_ptr ZERO4 OFF_output_buf -&text_buf_ptr ZERO4 OFF_text_buf -&labels_ptr ZERO4 OFF_labels +&scope_stack_ptr ZERO4 H2_OFF_scope_stack +&name_buf_ptr ZERO4 H2_OFF_name_buf +&label_buf_ptr ZERO4 H2_OFF_label_buf +&other_buf_ptr ZERO4 H2_OFF_other_buf +&pat_buf_ptr ZERO4 H2_OFF_pat_buf +&line_scratch_ptr ZERO4 H2_OFF_line_scratch +&ev_bytes_ptr ZERO4 H2_OFF_ev_bytes +&df_byte_ptr ZERO4 H2_OFF_df_byte +&input_buf_ptr ZERO4 H2_OFF_input_buf +&output_buf_ptr ZERO4 H2_OFF_output_buf +&text_buf_ptr ZERO4 H2_OFF_text_buf +&labels_ptr ZERO4 H2_OFF_labels :bss_init_tbl_end -## --- BSS scalars ------------------------------------------------------------ +## --- BSS scalars ---------------------------------------------------------- :saved_argc ZERO8 @@ -3480,15 +3002,11 @@ ZERO8 ZERO8 :arg_ptr ZERO8 -:input_count +:input_path ZERO8 -:input_total +:input_fd ZERO8 -:li_path -ZERO8 -:li_fd -ZERO8 -:li_tmp +:input_len ZERO8 :output_path ZERO8 @@ -3513,8 +3031,6 @@ ZERO8 :pass ZERO8 -:pass_idx -ZERO8 :ip ZERO8 :cur_path @@ -3534,7 +3050,7 @@ ZERO8 :scope_seq ZERO8 -## name read scratch +## name read :name_len ZERO8 :name_scope @@ -3547,16 +3063,12 @@ ZERO8 ZERO8 :rn_n ZERO8 -:sl_tmp -ZERO8 ## decimal read :rd_val ZERO8 :rd_saw ZERO8 -:rd_tmp -ZERO8 ## byte stream :pbs_acc @@ -3573,8 +3085,6 @@ ZERO8 ZERO8 :p1b_have ZERO8 -:p1b_done -ZERO8 :p1b_c ZERO8 @@ -3590,21 +3100,15 @@ ZERO8 :intern_i ZERO8 -## label_addr scratch -:la_const_32 -ZERO8 - -## name_eq scratch +## name_eq :ne_label ZERO8 :ne_src ZERO8 :ne_len ZERO8 -:ne_tmp -ZERO8 -## define_label scratch +## define_label :dl_src ZERO8 :dl_len @@ -3618,7 +3122,7 @@ ZERO8 :dl_name_off ZERO8 -## lookup_label scratch +## lookup_label :ll_src ZERO8 :ll_len @@ -3631,10 +3135,8 @@ ZERO8 ZERO8 :ll_label ZERO8 -:ll_tmp -ZERO8 -## process_reference / set_sigil_info scratch +## process_reference / set_sigil_info :cur_sigil ZERO8 :pr_width @@ -3655,18 +3157,10 @@ ZERO8 ZERO8 :pr_t_label ZERO8 -:pr_t_other -ZERO8 :pr_value ZERO8 -:pr_tmp -ZERO8 -:ssi_tmp -ZERO8 -:ssi_tmp2 -ZERO8 -## emit_value scratch +## emit_value :ev_value ZERO8 :ev_width @@ -3700,7 +3194,7 @@ ZERO8 :dp_n ZERO8 -## str/mem helpers +## str/mem :se_p ZERO8 :se_q @@ -3714,20 +3208,18 @@ ZERO8 :me_len ZERO8 -## parse_long_arg -:pla_p -ZERO8 -:pla_val +## parse_long +:pl_p ZERO8 -:pla_neg +:pl_val ZERO8 -:pla_tmp +:pl_neg ZERO8 -## error/fatal -:err_saved_msg +## fatal +:fm_msg ZERO8 -:err_saved_len +:fm_tmp ZERO8 ## write_decimal @@ -3735,29 +3227,10 @@ ZERO8 ZERO8 :wd_pos ZERO8 -:wd_tmp -ZERO8 - -## print_usage -:pu_tmp -ZERO8 - -## Generic auxiliary scratch used by sequences that route a value through -## BSS to satisfy the seed P1 mnemonic table. -:aux_tmp -ZERO8 -## --- BSS pointer slots ------------------------------------------------------ -:input_paths_ptr -ZERO8 -:input_starts_ptr -ZERO8 -:input_lens_ptr -ZERO8 +## --- BSS pointer slots ---------------------------------------------------- :scope_stack_ptr ZERO8 -:line_scratch_ptr -ZERO8 :name_buf_ptr ZERO8 :label_buf_ptr @@ -3766,6 +3239,8 @@ ZERO8 ZERO8 :pat_buf_ptr ZERO8 +:line_scratch_ptr +ZERO8 :ev_bytes_ptr ZERO8 :df_byte_ptr diff --git a/scripts/boot-run-tests.sh b/scripts/boot-run-tests.sh @@ -126,35 +126,22 @@ run_m1pp_suite() { run_p1_suite() { if [ -z "$NAMES" ]; then - raw=$(discover tests/P1 P1) - pp=$(discover tests/P1 P1pp) - NAMES=$(printf '%s\n%s\n' "$raw" "$pp" | sort -u | tr '\n' ' ') + NAMES=$(discover tests/P1 P1pp) fi for name in $NAMES; do - raw_src=tests/P1/$name.P1 pp_src=tests/P1/$name.P1pp expected=tests/P1/$name.expected if [ ! -e "$expected" ]; then echo " SKIP $name (no .expected)"; continue; fi + if [ ! -e "$pp_src" ]; then echo " SKIP $name (no .P1pp)"; continue; fi expected_content=$(cat "$expected") label="[$ARCH] $name" bin=build/$ARCH/tests/P1/$name log=build/$ARCH/.work/tests/P1/$name/build.log mkdir -p "$(dirname "$bin")" "$(dirname "$log")" - if [ -e "$pp_src" ]; then - if ! sh scripts/boot-build-p1pp.sh "$bin" "$pp_src" \ - >"$log" 2>&1; then - fail "$label" "" "$log" - continue - fi - elif [ -e "$raw_src" ]; then - if ! sh scripts/boot-build-p1.sh "$raw_src" "$bin" \ - >"$log" 2>&1; then - fail "$label" "" "$log" - continue - fi - else - echo " SKIP $name (no .P1 or .P1pp)" + if ! sh scripts/boot-build-p1pp.sh "$bin" "$pp_src" \ + >"$log" 2>&1; then + fail "$label" "" "$log" continue fi actual=$("./$bin" 2>&1 || true) diff --git a/tests/P1/00-hello.P1 b/tests/P1/00-hello.P1 @@ -1,27 +0,0 @@ -## P1 hello-world smoke fixture. -## -## Exercises the build pipeline (lint -> prune -> catm -> M0 -> ELF link -> -## hex2-0) against build/p1/aarch64/p1_aarch64.M1. Standalone program — -## does not drive the m1pp expander. -## -## P1 syscall ABI: -## a0 = syscall number on entry, return value on exit -## a1, a2, a3, t0, s0, s1 = syscall arguments 0..5 - -:p1_main - ## write(fd=1, buf=&msg, count=14) - li_a0 sys_write - li_a1 %1 %0 - la_a2 &msg - li_a3 %14 %0 - syscall - - ## return 0 (backend :_start stub sys_exits with a0) - li_a0 %0 %0 - ret - -:msg -"Hello, World! -" - -:ELF_end diff --git a/tests/P1/00-hello.expected b/tests/P1/00-hello.expected @@ -1 +0,0 @@ -Hello, World!