+local generated = {}
+
+definerule("generate",
+ {
+ body = { type="string" },
+ offset = { type="object" },
+ },
+ function(e)
+ return normalrule {
+ name = e.name,
+ ins = { "./generate.sh", "./"..e.body },
+ outleaves = { e.name..".s" },
+ commands = {
+ "%{ins[1]} "..e.body.." "..e.offset.." > %{outs}"
+ }
+ }
+ end
+)
+
+for i = 1, 128 do
+ generated[#generated+1] = generate {
+ name = "fload"..i,
+ body = "fload.h",
+ offset = i
+ }
+
+ generated[#generated+1] = generate {
+ name = "floadn"..i,
+ body = "floadn.h",
+ offset = i
+ }
+
+ generated[#generated+1] = generate {
+ name = "fstore"..i,
+ body = "fstore.h",
+ offset = i
+ }
+
+ generated[#generated+1] = generate {
+ name = "fstoren"..i,
+ body = "fstoren.h",
+ offset = i
+ }
+
+ generated[#generated+1] = generate {
+ name = "faddr"..i,
+ body = "faddr.h",
+ offset = i
+ }
+
+ generated[#generated+1] = generate {
+ name = "faddrn"..i,
+ body = "faddrn.h",
+ offset = i
+ }
+end
+
for _, plat in ipairs(vars.plats) do
acklibrary {
name = "lib_"..plat,
- srcs = { "./*.s" },
- vars = { plat = plat },
+ srcs = concat("./*.s", generated),
+ vars = {
+ plat = plat,
+ ["+ackcflags"] = {"-Imach/i80/libem"}
+ },
}
end
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Fetches the word at positive stack offset OFFSET into de.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.faddr, OFFSET)
+LABEL(.faddr, OFFSET):
+ #if OFFSET == 0
+ mov l, c
+ mov h, b
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ inx h
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ inx h
+ inx h
+ #else
+ lxi h, OFFSET
+ dad b
+ #endif
+ ret
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Fetches the word at negative stack offset OFFSET into de.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.faddrn, OFFSET)
+LABEL(.faddrn, OFFSET):
+ #if OFFSET == 0
+ mov l, c
+ mov h, b
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ dcx h
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ dcx h
+ dcx h
+ #else
+ lxi h, -OFFSET
+ dad b
+ #endif
+ ret
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Fetches the word at positive stack offset OFFSET into de.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.fload, OFFSET)
+LABEL(.fload, OFFSET):
+ #if OFFSET == 0
+ #error "0 shouldn't happen"
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ inx h
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ inx h
+ inx h
+ #else
+ lxi h, OFFSET
+ dad b
+ #endif
+ mov e, m
+ inx h
+ mov d, m
+ ret
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Fetches the word at negative stack offset OFFSET into de.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.floadn, OFFSET)
+LABEL(.floadn, OFFSET):
+ #if OFFSET == 0
+ #error "0 shouldn't happen"
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ mov d, m
+ dcx h
+ mov e, m
+ ret
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ dcx h
+ mov d, m
+ dcx h
+ mov e, m
+ ret
+ #else
+ lxi h, -OFFSET
+ dad b
+ mov e, m
+ inx h
+ mov d, m
+ ret
+ #endif
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Stores the word in de to positive stack offset OFFSET.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.fstore, OFFSET)
+LABEL(.fstore, OFFSET):
+ #if OFFSET == 0
+ #error "0 shouldn't happen"
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ inx h
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ inx h
+ inx h
+ #else
+ lxi h, OFFSET
+ dad b
+ #endif
+ mov m, e
+ inx h
+ mov m, d
+ ret
--- /dev/null
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+! Stores the word in de to negative stack offset OFFSET.
+
+#define PASTE(a, b) a ## b
+#define LABEL(prefix, offset) PASTE(prefix, offset)
+
+.define LABEL(.fstoren, OFFSET)
+LABEL(.fstoren, OFFSET):
+ #if OFFSET == 0
+ #error "0 shouldn't happen"
+ #elif OFFSET == 1
+ mov l, c
+ mov h, b
+ mov m, d
+ dcx h
+ mov m, e
+ ret
+ #elif OFFSET == 2
+ mov l, c
+ mov h, b
+ dcx h
+ mov m, d
+ dcx h
+ mov m, e
+ ret
+ #else
+ lxi h, -OFFSET
+ dad b
+ mov m, e
+ inx h
+ mov m, d
+ ret
+ #endif
+
--- /dev/null
+#!/bin/sh
+echo "#"
+echo "#define OFFSET $2"
+echo "#include \"$1\""
.sect .bss
.sect .text
+! Which resets we install are determined by statistical analysis of Star
+! Trek. When changing these, make sure to update the i80 table to match.
+! 97 call .floadn2
+! 41 call .floadn4
+! 34 call .fload4
+! 28 call .fstoren2
+
.define .rst_init
.rst_init:
- mvi a, 0xc3 ! jmp <a16>
- sta 0x08
- sta 0x10
- sta 0x18
- lxi h, rst1
- shld 0x09
- lxi h, rst2
- shld 0x11
- lxi h, rst3
- shld 0x19
- ret
-
- ! de = [bc+const1] (remember bc is the frame pointer)
-rst1:
- pop h
+ lxi h, .floadn2
+ lxi d, 0x0008
+ call copy
+ lxi h, .floadn4
+ lxi d, 0x0010
+ call copy
+ lxi h, .fload4
+ lxi d, 0x0018
+ call copy
+ lxi h, .fstoren2
+ lxi d, 0x0020
+ jmp copy
+
+! Copies eight bytes from HL to DE.
+copy:
+ mvi c, 8
+.1:
mov a, m
+ stax d
inx h
- push h
-
- mov l, a
- ral
- sbb a
- mov h, a
-
- dad b
- mov e, m
- inx h
- mov d, m
- ret
-
- ! [bc+const1] = de (remember bc is the frame pointer)
-rst2:
- pop h
- mov a, m
- inx h
- push h
-
- mov l, a
- ral
- sbb a
- mov h, a
-
- dad b
- mov m, e
- inx h
- mov m, d
- ret
-
- ! hl = bc+const1
-rst3:
- pop h
- mov a, m
- inx h
- push h
-
- mov l, a
- ral
- sbb a
- mov h, a
-
- dad b
- ret
-
+ inx d
+ dcr c
+ jnz .1
+ ret
\ No newline at end of file
SL=4
+STACKHELPERS=128
+
PROPERTIES
areg /* the a-register */
const2 = { INT num; } 2 num.
smallconst2 = { INT num; } 2 num.
label = { ADDR off; } 2 off.
+plabel = { ADDR off; INT param; } 2 off param.
m = { } 2 cost(0,3) "m".
SETS
ana reg1:ro kills a:cc cost(1, 4).
ani const1:ro kills a:cc cost(2, 7).
Call "call" label:ro cost(3,17).
+ Call "call" plabel:ro cost(3,17).
/* 'call' is a reserved word */
/* cc label:ro cost(3,14). */
/* cm label:ro cost(3,14). */
yields {const2, highw($1)} {const2, loww($1)}
#ifdef USE_I80_RSTS
- pat lol sfit($1, 8)
- uses hlreg, areg, dereg
+ pat lol $1==0-2
+ uses dereg, hlreg
gen
rst {const1, 1}
- data1 {const1, $1}
+ yields de
+
+ pat lol $1==0-4
+ uses dereg, hlreg
+ gen
+ rst {const1, 2}
+ yields de
+
+ pat lol $1==4
+ uses dereg, hlreg
+ gen
+ rst {const1, 3}
yields de
#endif
+pat lol ($1>0) && ($1<=STACKHELPERS)
+ uses dereg, hlreg
+ gen
+ Call {plabel, ".fload", $1}
+ yields de
+
+pat lol ($1<0) && ($1>=0-STACKHELPERS)
+ uses dereg, hlreg
+ gen
+ Call {plabel, ".floadn", 0-$1}
+ yields de
+
pat lol
- uses hlreg={const2, $1}, dereg
- gen
- dad lb
- mov e,{m}
- inx hl
- mov d,{m}
- yields de
+ uses dereg
+ gen
+ dad lb
+ mov e, {m}
+ inx hl
+ mov d, {m}
pat loe
uses hlreg
adp $1
loi 2
-#ifdef USE_I80_RSTS
- pat lal sfit($1, 8)
- uses dereg, hlreg, areg
- gen
- rst {const1, 3}
- data1 {const1, $1}
- yields hl
-#endif
+pat lal ($1>0) && ($1<=STACKHELPERS)
+ uses hlreg
+ gen
+ Call {plabel, ".faddr", $1}
+ yields hl
+
+pat lal ($1<0) && ($1>=0-STACKHELPERS)
+ uses hlreg
+ gen
+ Call {plabel, ".faddrn", 0-$1}
+ yields hl
pat lal
uses hlreg={const2,$1}
with dereg yields de de leaving stl $1
#ifdef USE_I80_RSTS
- pat stl sfit($1, 8)
- with dereg
- uses hlreg, areg
- gen
- rst {const1, 2}
- data1 {const1, $1}
+ pat stl $1==0-2
+ with dereg
+ uses hlreg
+ gen
+ rst {const1, 4}
#endif
+pat stl ($1>0) && ($1<=STACKHELPERS)
+ with dereg
+ uses hlreg
+ gen
+ Call {plabel, ".fstore", $1}
+
+pat stl ($1<0) && ($1>=0-STACKHELPERS)
+ with dereg
+ uses hlreg
+ gen
+ Call {plabel, ".fstoren", 0-$1}
+
pat stl
with dereg
- uses hlreg={const2, $1}
- gen
- dad lb
- mov {m}, e
- inx hl
- mov {m}, d
+ uses hlreg={const2, $1}
+ gen
+ dad lb
+ mov {m}, e
+ inx hl
+ mov {m}, d
pat ste loe $1==$2
with hlreg yields hl hl leaving ste $1
inx %1
yields %1
-#ifdef USE_I80_RSTS
- pat inl sfit($1, 8)
- uses hlreg, areg
+pat inl ($1>0) && ($1<STACKHELPERS)
+ uses hlreg
gen
- rst {const1, 3}
- data1 {const1, $1}
+ Call {plabel, ".faddr", $1}
inr {m}
- jnz {label, 1f}
+ jnz {label,1f}
+ inx hl
+ inr {m}
+ 1:
+
+pat inl ($1<0) && ($1<0-STACKHELPERS)
+ uses hlreg
+ gen
+ Call {plabel, ".faddrn", $1}
+ inr {m}
+ jnz {label,1f}
inx hl
inr {m}
1:
-#endif
pat inl
uses hlreg={const2,$1}
with hl_or_de
gen dcx %1 yields %1
-#ifdef USE_I80_RSTS
- pat del sfit($1, 8)
- uses hlreg, areg, dereg
+pat del
+ uses hlreg={const2,$1}
gen
- rst {const1, 3}
- data1 {const1, $1}
+ dad lb
mov e, {m}
inx hl
mov d, {m}
mov {m}, d
dcx hl
mov {m}, e
-#endif
-
-pat del
- uses hlreg={const2,$1}, dereg
- gen dad lb
- mov e,{m}
- inx hl
- mov d,{m}
- dcx de
- mov {m},d
- dcx hl
- mov {m},e
pat dee
uses hlreg
dcx hl
shld {label,$1}
-#ifdef USE_I80_RSTS
- pat zrl sfit($1, 8)
- uses hlreg, areg
- gen
- rst {const1, 3}
- data1 {const1, $1}
- xra a
- mov {m}, a
- inx hl
- mov {m}, a
-#endif
-
pat zrl
uses hlreg={const2,$1}, areg
gen
jnz {label,$1}
1:
-#ifdef USE_I80_RSTS
- pat lol zeq sfit($1, 8)
- with STACK
- uses hlreg, areg
- gen
- rst {const1, 3}
- data1 {const1, $1}
- mov a, {m}
- inx hl
- ora {m}
- jz {label, $2}
-#endif
-
pat lol zeq
with STACK
uses hlreg={const2,$1}, areg
ora {m}
jz {label,$2}
-#ifdef USE_I80_RSTS
- pat lol zne sfit($1, 8)
- with STACK
- uses hlreg, areg
- gen
- rst {const1, 3}
- data1 {const1, $1}
- mov a, {m}
- inx hl
- ora {m}
- jnz {label, $2}
-#endif
-
pat lol zne
with STACK
uses hlreg={const2,$1}, areg
{FLOATS?} \
(.e:{TAIL}={PLATFORMDIR}/libem.a \
{PLATFORMDIR}/libsys.a \
+ {PLATFORMDIR}/libem.a \
{PLATFORMDIR}/libend.a)
linker
end