boot2

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

commit 916cf97b8f41509b44ffed37e1ca56534882f07a
parent 6802247719c4e9f7c114105d756009926ef8c68b
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 30 Apr 2026 11:01:32 -0700

p1pp: extend cmpset macro set

Diffstat:
MP1/P1pp.P1pp | 23++++++++++++++++++++++-
Mcc/cc.scm | 8++------
Mtests/P1/cmpset.P1pp | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mtests/P1/cmpset.expected | 2+-
4 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/P1/P1pp.P1pp b/P1/P1pp.P1pp @@ -298,9 +298,14 @@ # # %cmpset_<cc>(rd, ra[, rb]) rd = (ra <cc> rb) ? 1 : 0 # -# Two-operand: eq, ne, lt, ltu (signed/unsigned). +# Two-operand: eq, ne, lt, ltu, le, leu, ge, geu (signed/unsigned). # Zero-operand (compare against zero): eqz, nez, ltz. # +# le/ge/leu/geu lower through the same ifelse machinery with operands +# swapped or condition flipped: a >= b iff !(a < b) iff (b <= a-1), and +# we reach it as (b < a) ? 0 : 1 via ifelse_lt with swapped arms (and +# the unsigned/signed pairing follows ltu/lt). +# # Lower to %ifelse_<cc>(...) which itself works across all P1 backends. # A backend that supports a native conditional-set instruction can later # specialize these to a single op without touching callers. @@ -321,6 +326,22 @@ %ifelse_ltu(ra, rb, { %li(rd, 1) }, { %li(rd, 0) }) %endm +%macro cmpset_le(rd, ra, rb) + %ifelse_lt(rb, ra, { %li(rd, 0) }, { %li(rd, 1) }) +%endm + +%macro cmpset_leu(rd, ra, rb) + %ifelse_ltu(rb, ra, { %li(rd, 0) }, { %li(rd, 1) }) +%endm + +%macro cmpset_ge(rd, ra, rb) + %ifelse_lt(ra, rb, { %li(rd, 0) }, { %li(rd, 1) }) +%endm + +%macro cmpset_geu(rd, ra, rb) + %ifelse_ltu(ra, rb, { %li(rd, 0) }, { %li(rd, 1) }) +%endm + %macro cmpset_eqz(rd, ra) %ifelse_eqz(ra, { %li(rd, 1) }, { %li(rd, 0) }) %endm diff --git a/cc/cc.scm b/cc/cc.scm @@ -3562,12 +3562,8 @@ ((eq? op 'ne) (%cg-emit-cmp cg "ne" 'a0 'a1 't0)) ((eq? op 'lt) (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a0 'a1 't0)) ((eq? op 'gt) (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a1 'a0 't0)) - ((eq? op 'le) - (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a1 'a0 't0) - (%cg-emit-many cg (list "%li(t1, 1)\n%xor(t0, t0, t1)\n"))) - ((eq? op 'ge) - (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a0 'a1 't0) - (%cg-emit-many cg (list "%li(t1, 1)\n%xor(t0, t0, t1)\n"))) + ((eq? op 'le) (%cg-emit-cmp cg (if unsigned? "leu" "le") 'a0 'a1 't0)) + ((eq? op 'ge) (%cg-emit-cmp cg (if unsigned? "geu" "ge") 'a0 'a1 't0)) (else (die #f "cg-binop: unknown op" op))) (%cg-spill-reg cg 't0 result-ty))))) diff --git a/tests/P1/cmpset.P1pp b/tests/P1/cmpset.P1pp @@ -4,12 +4,17 @@ # %cmpset_ne rd = (ra != rb) ? 1 : 0 # %cmpset_lt signed less-than # %cmpset_ltu unsigned less-than +# %cmpset_le signed less-or-equal +# %cmpset_leu unsigned less-or-equal +# %cmpset_ge signed greater-or-equal +# %cmpset_geu unsigned greater-or-equal # %cmpset_eqz(rd, ra) rd = (ra == 0) ? 1 : 0 # %cmpset_nez rd = (ra != 0) ? 1 : 0 # %cmpset_ltz rd = (ra < 0) ? 1 : 0 # -# Each subtest checks both the true and false case for a comparator. -# Output: "EQ NE LT LTU EZ NZ LZ\n" on full pass. +# Each subtest checks both the true and false case for a comparator +# (and for le/ge, also the equality boundary). +# Output: "EQ NE LT LTU LE LEU GE GEU EZ NZ LZ\n" on full pass. %fn(p1_main, 0, { # ---- eq ------------------------------------------------------------- @@ -46,6 +51,55 @@ %li(t1, 0) %bne(t0, t1, &::fail) %la(a0, &c_ltu) %li(a1, 4) %call(&print) + # ---- le (signed) ---------------------------------------------------- + # true cases: a < b, and a == b + %li(s0, -3) %li(s1, 2) + %cmpset_le(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %li(s0, 5) %li(s1, 5) + %cmpset_le(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + # false: a > b + %li(s0, 6) %li(s1, 5) + %cmpset_le(t0, s0, s1) + %li(t1, 0) %bne(t0, t1, &::fail) + %la(a0, &c_le) %li(a1, 3) %call(&print) + + # ---- leu (unsigned) ------------------------------------------------- + # -1 unsigned is huge; 5 <= -1 (true), -1 <= 5 (false), 5 <= 5 (true) + %li(s0, 5) %li(s1, -1) + %cmpset_leu(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %cmpset_leu(t0, s1, s0) + %li(t1, 0) %bne(t0, t1, &::fail) + %li(s0, 5) %li(s1, 5) + %cmpset_leu(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %la(a0, &c_leu) %li(a1, 4) %call(&print) + + # ---- ge (signed) ---------------------------------------------------- + %li(s0, 2) %li(s1, -3) + %cmpset_ge(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %li(s0, 5) %li(s1, 5) + %cmpset_ge(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %li(s0, -3) %li(s1, 2) + %cmpset_ge(t0, s0, s1) + %li(t1, 0) %bne(t0, t1, &::fail) + %la(a0, &c_ge) %li(a1, 3) %call(&print) + + # ---- geu (unsigned) ------------------------------------------------- + %li(s0, -1) %li(s1, 5) + %cmpset_geu(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %cmpset_geu(t0, s1, s0) + %li(t1, 0) %bne(t0, t1, &::fail) + %li(s0, 5) %li(s1, 5) + %cmpset_geu(t0, s0, s1) + %li(t1, 1) %bne(t0, t1, &::fail) + %la(a0, &c_geu) %li(a1, 4) %call(&print) + # ---- eqz ------------------------------------------------------------ %li(s0, 0) %cmpset_eqz(t0, s0) @@ -88,6 +142,10 @@ :c_ne "NE " :c_lt "LT " :c_ltu "LTU " +:c_le "LE " +:c_leu "LEU " +:c_ge "GE " +:c_geu "GEU " :c_ez "EZ " :c_nz "NZ " :c_lz "LZ" diff --git a/tests/P1/cmpset.expected b/tests/P1/cmpset.expected @@ -1 +1 @@ -EQ NE LT LTU EZ NZ LZ +EQ NE LT LTU LE LEU GE GEU EZ NZ LZ