summaryrefslogtreecommitdiff
path: root/frontends/calculator/CEdev/include/fasmg-ez80
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2019-04-10 15:14:00 -0400
committerAndrew Opalach <andrew@akon.city> 2019-04-10 15:14:00 -0400
commit60699af63f92f43cc4b4b9e3050fcdd2a8468281 (patch)
tree20a18af2774daa43ae7f4352dd032a24f7e06075 /frontends/calculator/CEdev/include/fasmg-ez80
parent4527bc20241068731c62101d0467d416119ec0c4 (diff)
downloadcetris-60699af63f92f43cc4b4b9e3050fcdd2a8468281.tar.gz
cetris-60699af63f92f43cc4b4b9e3050fcdd2a8468281.tar.bz2
cetris-60699af63f92f43cc4b4b9e3050fcdd2a8468281.zip
add opengl fronend, remove sdl frontend, refactor build system
Diffstat (limited to 'frontends/calculator/CEdev/include/fasmg-ez80')
-rw-r--r--frontends/calculator/CEdev/include/fasmg-ez80/ez80.inc862
-rw-r--r--frontends/calculator/CEdev/include/fasmg-ez80/ld.fasmg759
-rw-r--r--frontends/calculator/CEdev/include/fasmg-ez80/ti84pceg.inc61
-rw-r--r--frontends/calculator/CEdev/include/fasmg-ez80/tiformat.inc105
4 files changed, 1787 insertions, 0 deletions
diff --git a/frontends/calculator/CEdev/include/fasmg-ez80/ez80.inc b/frontends/calculator/CEdev/include/fasmg-ez80/ez80.inc
new file mode 100644
index 0000000..6e8e005
--- /dev/null
+++ b/frontends/calculator/CEdev/include/fasmg-ez80/ez80.inc
@@ -0,0 +1,862 @@
+define @ez80 @ez80
+macro @ez80.suffix @l, @il*
+ @ez80.l = @l
+ @ez80.il = @il
+ @ez80.lil = @ez80.l or @ez80.il shl 1
+ @ez80.pre = @ez80.lil or @ez80.lil shl 3 or 100o
+end macro
+macro @ez80.byte @values*&
+ db @values
+end macro
+macro @ez80.offset @value*
+ local value
+ value = @value
+ if elementsof value
+ err 'invalid offset'
+ else if value < -200o | 200o <= value
+ err 'offset is out of range'
+ end if
+ db value
+end macro
+macro @ez80.word @value*
+ local value
+ value = @value
+ if elementsof value
+ err 'invalid immediate'
+ end if
+ emit word + @ez80.il: @value
+end macro
+macro @ez80.idxpre @regs*&
+ local pre
+ iterate @reg, @regs
+ pre = @reg metadata 1 scale 1
+ if pre > 300o
+ @ez80.byte pre
+ break
+ end if
+ end iterate
+end macro
+macro @ez80.idxoff @reg*
+ local reg
+ reg = @reg
+ if reg metadata 1 scale 1 > 300o
+ @ez80.offset @reg scale 0
+ else if reg scale 0
+ err 'invalid arguments'
+ end if
+end macro
+macro @ez80.emit @values*&
+ if defined @ez80.pre
+ db @ez80.pre
+ end if
+ iterate @value, @values
+ @ez80.@value
+ end iterate
+end macro
+macro @ez80.nest @inst*&
+ if defined @ez80.pre
+ @ez80.pre =: @ez80.pre
+ end if
+ @inst
+end macro
+macro @ez80.check @ind*, @expr&
+ match @left ) @right, <@expr>
+ match @ ( @mid, <@left>
+ @ez80.check @ind, @mid @right
+ else
+ @ind =: 0
+ end match
+ else
+ @ind =: 1
+ end match
+end macro
+macro @ez80.classify @val, @ind*, @arg&
+ match, @arg
+ @ind =: 0
+ else
+ @val =: @arg
+ match ( @ ), @arg
+ @ez80.check @ind, @
+ else
+ @ind =: 0
+ end match
+ end match
+end macro
+
+long? = 3
+; FIXME: dup relocations
+macro dw? @values*&
+ if @ez80.adl
+ emit word?: @values
+ else
+ match left =dup? right, @values
+ emit word?: @values
+ else
+ iterate @value, @values
+ @ez80.word @value
+ end iterate
+ end match
+ end if
+end macro
+macro dl? @values*&
+ if @ez80.adl
+ match left =dup? right, @values
+ emit long?: @values
+ else
+ iterate @value, @values
+ @ez80.word @value
+ end iterate
+ end match
+ else
+ emit long?: @values
+ end if
+end macro
+iterate @name, dw, rw, dl, rl
+ struc (name) @name? @values*&
+ label name: long?
+ @name? @values
+ end struc
+end iterate
+macro assume? @expr*
+ match =adl? == @adl, @expr
+ local adl
+ adl = @adl
+ if adl = adl and 1
+ @ez80.l = adl
+ @ez80.il = adl
+ @ez80.adl = adl
+ else
+ err 'adl assume should be 0 or 1'
+ end if
+ else
+ err 'invalid assume statement'
+ end match
+end macro
+assume? adl = 1
+
+element @ez80.breg
+element b?: @ez80.breg * 003o + 030o
+element nz?: @ez80.breg * 010o + 001o
+element z?: @ez80.breg * 010o + 011o
+element nc?: @ez80.breg * 010o + 021o
+element c?: @ez80.breg * 003o + 031o
+element po?: @ez80.breg * 010o + 041o
+element pe?: @ez80.breg * 010o + 051o
+nv? = po?
+v? = pe?
+element p?: @ez80.breg * 010o + 061o
+element m?: @ez80.breg * 010o + 071o
+element d?: @ez80.breg * 003o + 032o
+element e?: @ez80.breg * 003o + 033o
+element h?: @ez80.breg * 003o + 034o
+element ixh?: @ez80.breg * 335o + 034o
+element iyh?: @ez80.breg * 375o + 034o
+element l?: @ez80.breg * 003o + 035o
+element ixl?: @ez80.breg * 335o + 035o
+element iyl?: @ez80.breg * 375o + 035o
+element f?: @ez80.breg * 002o + 036o
+element a?: @ez80.breg * 003o + 037o
+
+element @ez80.irmb
+element i?: @ez80.irmb * 107o + 127o
+element r?: @ez80.irmb * 117o + 137o
+element mb?: @ez80.irmb * 155o + 156o
+
+element @ez80.wreg
+element bc?: @ez80.wreg * 007o + 000o
+element de?: @ez80.wreg * 007o + 020o
+element hl?: @ez80.wreg * 007o + 040o
+element ix?: @ez80.wreg * 335o + 040o
+element iy?: @ez80.wreg * 375o + 040o
+element sp?: @ez80.wreg * 006o + 060o
+element af?: @ez80.wreg * 001o + 060o
+element af'?
+
+@ez80.is_reg equ metadata 1 element 1 eq
+
+macro inst! @name*, @params&
+ restore @name?
+ define @name? @name?
+ @ez80.oplist equ @name?
+ namespace @name?
+ macro s? @args&
+ @ez80.suffix 0, @ez80.il
+ @name? @args
+ end macro
+ macro l? @args&
+ @ez80.suffix 1, @ez80.il
+ @name? @args
+ end macro
+ macro is? @args&
+ @ez80.suffix @ez80.l, 0
+ @name? @args
+ end macro
+ macro il? @args&
+ @ez80.suffix @ez80.l, 1
+ @name? @args
+ end macro
+ macro sis? @args&
+ @ez80.suffix 0, 0
+ @name? @args
+ end macro
+ macro lis? @args&
+ @ez80.suffix 1, 0
+ @name? @args
+ end macro
+ macro sil? @args&
+ @ez80.suffix 0, 1
+ @name? @args
+ end macro
+ macro lil? @args&
+ @ez80.suffix 1, 1
+ @name? @args
+ end macro
+ end namespace
+ local @temp
+ virtual
+ iterate @param, @params
+ match @arg @, @param*
+ @temp = string `@arg shr 8
+ db 'local ', @temp, ', ', @temp, 'ind', 10
+ match @arg &, @param
+ db 'iterate @, ', `@arg, 10, 9, 'indx %%-%+1', 10, 9
+ end match
+ db '@ez80.classify ', @temp, ', ', @temp, 'ind, '
+ match @@ &, @param
+ db '@', 10, 'end iterate', 10
+ else
+ db `@arg, 10
+ end match
+ end match
+ end iterate
+ load @temp: $ - $$ from $$
+ end virtual
+ esc macro @name?: @params
+ local before, after, noerr
+ label before
+ eval @temp
+end macro
+macro end?.inst!
+ label after
+ if ~defined noerr & before = after
+ err 'invalid arguments'
+ end if
+ restore @ez80.pre
+ assume? adl = @ez80.adl
+ esc end macro
+end macro
+
+iterate <@name, @opc*>, \
+ nop, 000o, \
+ rlca, 007o, \
+ rrca, 017o, \
+ rla, 027o, \
+ rra, 037o, \
+ daa, 047o, \
+ cpl, 057o, \
+ scf, 067o, \
+ ccf, 077o, \
+ halt, 166o, \
+ exx, 331o, \
+ di, 363o, \
+ ei, 373o, \
+ neg, <355o, 104o>, \
+ retn, <355o, 105o>, \
+ reti, <355o, 115o>, \
+ rrd, <355o, 147o>, \
+ rld, <355o, 157o>, \
+ slp, <355o, 166o>, \
+ stmix, <355o, 175o>, \
+ rsmix, <355o, 176o>, \
+ inim, <355o, 202o>, \
+ otim, <355o, 203o>, \
+ ini2, <355o, 204o>, \
+ indm, <355o, 212o>, \
+ otdm, <355o, 213o>, \
+ ind2, <355o, 214o>, \
+ inimr, <355o, 222o>, \
+ otimr, <355o, 223o>, \
+ ini2r, <355o, 224o>, \
+ indmr, <355o, 232o>, \
+ otdmr, <355o, 233o>, \
+ ind2r, <355o, 234o>, \
+ ldi, <355o, 240o>, \
+ cpi, <355o, 241o>, \
+ ini, <355o, 242o>, \
+ outi, <355o, 243o>, \
+ outi2, <355o, 244o>, \
+ ldd, <355o, 250o>, \
+ cpd, <355o, 251o>, \
+ ind, <355o, 252o>, \
+ outd, <355o, 253o>, \
+ outd2, <355o, 254o>, \
+ ldir, <355o, 260o>, \
+ cpir, <355o, 261o>, \
+ inir, <355o, 262o>, \
+ otir, <355o, 263o>, \
+ oti2r, <355o, 264o>, \
+ lddr, <355o, 270o>, \
+ cpdr, <355o, 271o>, \
+ indr, <355o, 272o>, \
+ otdr, <355o, 273o>, \
+ otd2r, <355o, 274o>, \
+ inirx, <355o, 302o>, \
+ otirx, <355o, 303o>, \
+ indrx, <355o, 312o>, \
+ otdrx, <355o, 313o>
+ inst @name
+ @ez80.emit <byte @opc>
+ end inst
+end iterate
+
+iterate @name, inc, dec
+ inst @name, @reg*
+ if regind
+ if reg relativeto reg element 1 & reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 0 = 040o
+ @ez80.emit idxpre reg, byte 063o + %, idxoff reg
+ end if
+ else if reg eq reg element 1
+ if reg @ez80.is_reg @ez80.wreg & reg metadata 1 scale 1 and 004o
+ @ez80.emit idxpre reg, byte reg metadata 1 scale 0 - 005o \
+ + % shl 3
+ else if reg @ez80.is_reg @ez80.breg \
+ & reg metadata 1 scale 1 and 001o
+ @ez80.emit idxpre reg, byte reg metadata 1 scale 0 shl 3 \
+ and 070o or % + 3
+ end if
+ end if
+ end inst
+end iterate
+
+inst ex, @arg1, @arg2*
+ if arg1ind
+ if arg2ind
+ err 'invalid indirection'
+ else if arg1 eq sp? & arg2 eq arg2 element 1 \
+ & arg2 @ez80.is_reg @ez80.wreg & arg2 metadata 1 scale 0 = 040o
+ @ez80.emit idxpre arg2, byte 343o
+ end if
+ else if arg2ind
+ @ez80.nest ex? @arg2, @arg1
+ else if (arg1 eq af? & arg2 eq af'?) | (arg1 eq af'? & arg2 eq af?)
+ @ez80.emit byte 010o
+ else if (arg1 eq de? & arg2 eq hl?) | (arg1 eq hl? & arg2 eq de?)
+ @ez80.emit byte 353o
+ end if
+end inst
+
+inst djnz, @addr*
+ if addrind
+ err 'invalid indirection'
+ else
+ @ez80.emit byte 020o, offset addr - after
+ end if
+end inst
+inst jr, @arg1*, @arg2
+ if arg1ind | arg2ind
+ err 'invalid indirection'
+ else if ~defined arg2
+ @ez80.emit byte 030o, offset arg1 - after
+ else
+ if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 0 and 047o = 001o
+ @ez80.emit byte arg1 metadata 1 scale 0 and 030o or 040o, \
+ offset arg2 - after
+ end if
+ end if
+end inst
+inst jq, @arg1*, @arg2
+ local off, keep
+ if arg1ind | arg2ind
+ err 'invalid indirection'
+ else if ~defined arg2
+ off = arg1 - before - 2
+ if defined @ez80.pre
+ off = off - 1
+ end if
+ if defined noerr & ~arg1 eq after | defined keep
+ define keep
+ end if
+ if defined after & arg1 eq after & ~defined keep
+ define noerr
+ else if ~elementsof off & -200o <= off & off < 200o
+ @ez80.emit byte 030o, offset off
+ else
+ @ez80.emit byte 303o, word arg1
+ end if
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 0 and 007o = 001o
+ off = arg2 - before - 2
+ if defined @ez80.pre
+ off = off - 1
+ end if
+ if defined noerr & ~arg2 eq after | defined keep
+ define keep
+ end if
+ if defined after & arg2 eq after & ~defined keep
+ define noerr
+ else if arg1 metadata 1 scale 0 < 040o & ~elementsof off & -200o <= off & off < 200o
+ @ez80.emit byte arg1 metadata 1 scale 0 and 030o or 040o, \
+ offset off
+ else
+ @ez80.emit byte arg1 metadata 1 scale 0 and 070o or 302o, \
+ word arg2
+ end if
+ end if
+end inst
+
+inst ld, @dst, @src*
+ local opc
+ if dstind & srcind
+ err 'invalid indirection'
+ else if dstind
+ if dst relativeto dst element 1 & dst @ez80.is_reg @ez80.wreg
+ if dst metadata 1 scale 0 = 040o
+ if src eq src element 1 & src @ez80.is_reg @ez80.breg \
+ & src metadata 1 scale 1 = 003o
+ @ez80.emit idxpre dst, byte src metadata 1 scale 0 \
+ and 007o or 160o, idxoff dst
+ else if src eq src element 1 & src @ez80.is_reg @ez80.wreg \
+ & src metadata 1 scale 1 and 005o = 005o
+ opc = src metadata 1 scale 0 or 017o
+ if src metadata 1 scale 1 > 300o
+ if dst metadata 1 scale 1 xor src metadata 1 scale 1 \
+ and 040o
+ opc = opc + 017o
+ else
+ opc = opc + 020o
+ end if
+ end if
+ if dst metadata 1 scale 1 > 300o
+ @ez80.emit idxpre dst, byte opc, idxoff dst
+ else
+ @ez80.emit <byte 355o, opc>
+ end if
+ else
+ @ez80.emit idxpre dst, byte 066o, idxoff dst, byte src
+ end if
+ else if src eq a? & dst metadata 1 scale 0 < 040o
+ @ez80.emit byte dst metadata 1 scale 0 or 002o
+ end if
+ else if src eq a?
+ @ez80.emit byte 062o, word dst
+ else if src eq src element 1 & src @ez80.is_reg @ez80.wreg \
+ & src metadata 1 scale 1 and 004o
+ if src metadata 1 scale 0 = 040o
+ @ez80.emit idxpre src, byte 042o, word dst
+ else
+ @ez80.emit <byte 355o, src metadata 1 scale 0 or 103o>, word dst
+ end if
+ end if
+ else if srcind
+ if ~dst eq dst element 1
+ else if src relativeto src element 1 & src @ez80.is_reg @ez80.wreg
+ if src metadata 1 scale 0 = 040o
+ if dst @ez80.is_reg @ez80.breg & dst metadata 1 scale 1 = 003o
+ @ez80.emit idxpre src, byte dst metadata 1 scale 0 \
+ shl 3 and 070o or 106o, idxoff src
+ else if dst @ez80.is_reg @ez80.wreg \
+ & dst metadata 1 scale 1 and 005o = 005o
+ opc = dst metadata 1 scale 0 or 007o
+ if dst metadata 1 scale 1 > 300o
+ if dst metadata 1 scale 1 xor src metadata 1 scale 1 \
+ and 040o
+ opc = opc + 012o
+ else
+ opc = opc + 020o
+ end if
+ end if
+ if src metadata 1 scale 1 > 300o
+ @ez80.emit idxpre src, byte opc, idxoff src
+ else
+ @ez80.emit <byte 355o, opc>
+ end if
+ end if
+ else if dst eq a? & src metadata 1 scale 0 < 040o
+ @ez80.emit byte src metadata 1 scale 0 or 012o
+ end if
+ else if dst eq a?
+ @ez80.emit byte 072o, word src
+ else if dst @ez80.is_reg @ez80.wreg & dst metadata 1 scale 1 and 004o
+ if dst metadata 1 scale 0 = 040o
+ @ez80.emit idxpre dst, byte 052o, word src
+ else
+ @ez80.emit <byte 355o, dst metadata 1 scale 0 or 113o>, word src
+ end if
+ end if
+ else if dst eq dst element 1
+ if dst @ez80.is_reg @ez80.breg
+ if src eq src element 1 & src @ez80.is_reg @ez80.breg \
+ & dst metadata 1 scale 1 and src metadata 1 scale 1 and 001o \
+ & (dst metadata 1 scale 0 xor src metadata 1 scale 0 and 006o \
+ | dst metadata 1 scale 1 = src metadata 1 scale 1) \
+ & (~dst eq src | dst metadata 1 scale 0 > 033o)
+ @ez80.emit <idxpre dst, src>, \
+ byte dst metadata 1 scale 0 shl 3 and 070o \
+ + src metadata 1 scale 0 and 007o or 100o
+ else if src eq src element 1 & src @ez80.is_reg @ez80.irmb \
+ & dst eq a?
+ @ez80.emit <byte 355o, src metadata 1 scale 0>
+ else if dst metadata 1 scale 1 and 001o
+ @ez80.emit idxpre dst, \
+ byte dst metadata 1 scale 0 shl 3 and 070o or 006o, \
+ byte src
+ end if
+ else if dst @ez80.is_reg @ez80.wreg & dst metadata 1 scale 1 and 004o
+ if dst eq sp? & src eq src element 1 & src @ez80.is_reg @ez80.wreg \
+ & src metadata 1 scale 0 = 040o
+ @ez80.emit idxpre src, byte 371o
+ else if dst eq hl? & src eq i?
+ @ez80.emit <byte 355o, 327o>
+ else
+ @ez80.emit idxpre dst, byte dst metadata 1 scale 0 or 001o, \
+ word src
+ end if
+ else if dst @ez80.is_reg @ez80.irmb & src eq a?
+ @ez80.emit <byte 355o, dst metadata 1 scale 1>
+ else if dst eq i? & src eq hl?
+ @ez80.emit <byte 355o, 307o>
+ end if
+ end if
+end inst
+
+inst add, @arg1*, @arg2
+ if ~defined arg2
+ @ez80.nest a?, @arg1
+ else if arg1ind
+ err 'invalid indirection'
+ else if arg1 eq a?
+ if arg2ind
+ if arg2 relativeto arg2 element 1 & arg2 @ez80.is_reg @ez80.wreg \
+ & arg2 metadata 1 scale 0 = 040o
+ @ez80.emit idxpre arg2, byte 206o, idxoff arg2
+ end if
+ else if arg2 eq arg2 element 1 & arg2 @ez80.is_reg @ez80.breg \
+ & arg2 metadata 1 scale 1 and 001o
+ @ez80.emit idxpre arg2, byte arg2 metadata 1 scale 0 and 007o \
+ or 200o
+ else
+ @ez80.emit <byte 306o, arg2>
+ end if
+ else if arg2ind
+ err 'invalid indirection'
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.wreg \
+ & arg2 eq arg2 element 1 & arg1 @ez80.is_reg @ez80.wreg \
+ & arg1 metadata 1 scale 0 = 040o & arg2 metadata 1 scale 1 and 004o \
+ & (arg1 metadata 1 scale 0 <> arg2 metadata 1 scale 0 \
+ | arg1 metadata 1 scale 1 = arg2 metadata 1 scale 1)
+ @ez80.emit idxpre arg1, byte arg2 metadata 1 scale 0 or 011o
+ end if
+end inst
+iterate @name, adc, sbc
+ inst @name, @arg1*, @arg2
+ if ~defined arg2
+ if arg1 @ez80.is_reg @ez80.wreg
+ @ez80.nest hl?, @arg1
+ else
+ @ez80.nest a?, @arg1
+ end if
+ else if arg1ind
+ err 'invalid indirection'
+ else if arg1 eq a?
+ if arg2ind
+ if arg2 relativeto arg2 element 1 \
+ & arg2 @ez80.is_reg @ez80.wreg \
+ & arg2 metadata 1 scale 0 = 040o
+ @ez80.emit idxpre arg2, byte 176o + % shl 4, idxoff arg2
+ end if
+ else if arg2 eq arg2 element 1 & arg2 @ez80.is_reg @ez80.breg \
+ & arg2 metadata 1 scale 1 and 001o
+ @ez80.emit idxpre arg2, byte arg2 metadata 1 scale 0 and 007o \
+ or 170o + % shl 4
+ else
+ @ez80.emit <byte 276o + % shl 4, arg2>
+ end if
+ else if arg2ind
+ err 'invalid indirection'
+ else if arg1 eq hl? & arg2 eq arg2 element 1 \
+ & arg2 @ez80.is_reg @ez80.wreg \
+ & arg2 metadata 1 scale 1 and 002o
+ @ez80.emit <byte 355o, arg2 metadata 1 scale 0 + 122o - % shl 3>
+ end if
+ end inst
+end iterate
+iterate <@name, @opc*>, \
+ sub, 220o, \
+ and, 240o, \
+ xor, 250o, \
+ or, 260o, \
+ cp, 270o
+ inst @name, @arg1*, @arg2
+ if ~defined arg2
+ if arg1ind
+ if arg1 relativeto arg1 element 1 \
+ & arg1 @ez80.is_reg @ez80.wreg \
+ & arg1 metadata 1 scale 0 = 040o
+ @ez80.emit idxpre arg1, byte @opc or 006o, idxoff arg1
+ end if
+ else if arg1 relativeto arg1 element 1 \
+ & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 1 and 001o
+ @ez80.emit idxpre arg1, byte arg1 metadata 1 scale 0 and 007o \
+ or @opc
+ else
+ @ez80.emit <byte @opc or 106o, arg1>
+ end if
+ else if arg1ind
+ err 'invalid indirection'
+ else if arg1 eq a?
+ @ez80.nest @name? @arg2
+ end if
+ end inst
+end iterate
+inst tst, @arg1*, @arg2
+ if ~defined arg2
+ if arg1ind
+ if arg1 eq hl?
+ @ez80.emit <byte 355o, 064o>
+ end if
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 1 = 003o
+ @ez80.emit <byte 355o, \
+ arg1 metadata 1 scale 0 shl 3 and 070o or 004o>
+ else
+ @ez80.emit <byte 355o, 144o, arg1>
+ end if
+ else if arg1ind
+ err 'invalid indirection'
+ else if arg1 eq a?
+ @ez80.nest tst? @arg2
+ end if
+end inst
+
+inst ret, @cond
+ if ~defined cond
+ @ez80.emit byte 311o
+ else if condind
+ err 'invalid indirection'
+ else if cond eq cond element 1 & cond @ez80.is_reg @ez80.breg \
+ & cond metadata 1 scale 0 and 007o = 001o
+ @ez80.emit byte cond metadata 1 scale 0 and 070o or 300o
+ end if
+end inst
+iterate @name, pop, push
+ inst @name, @reg*&
+ while defined reg + regind
+ if regind
+ err 'invalid indirection'
+ else if reg eq reg element 1 & reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 1 and 001o
+ @ez80.emit idxpre reg, \
+ byte reg metadata 1 scale 0 + 275o + % shl 2
+ else if `@name = 'push'
+ @ez80.nest pea? reg
+ else
+ err 'invalid argument'
+ end if
+ restore reg, regind
+ end while
+ end inst
+end iterate
+
+inst jp, @arg1*, @arg2
+ if ~defined arg2
+ if ~arg1ind
+ @ez80.emit byte 303o, word arg1
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.wreg \
+ & arg1 metadata 1 scale 0 = 040o
+ @ez80.emit idxpre arg1, byte 351o
+ end if
+ else if arg1ind | arg2ind
+ err 'invalid indirection'
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 0 and 007o = 001o
+ @ez80.emit byte arg1 metadata 1 scale 0 and 070o or 302o, word arg2
+ end if
+end inst
+inst call, @arg1*, @arg2
+ if arg1ind | arg2ind
+ err 'invalid indirection'
+ else if ~defined arg2
+ @ez80.emit byte 315o, word arg1
+ else if arg1 eq arg1 element 1 & arg1 @ez80.is_reg @ez80.breg \
+ & arg1 metadata 1 scale 0 and 007o = 001o
+ @ez80.emit byte arg1 metadata 1 scale 0 and 070o or 304o, word arg2
+ end if
+end inst
+inst rst, @addr*
+ if addrind
+ err 'invalid indirection'
+ else if addr = addr and 070o
+ @ez80.emit byte addr or 307o
+ else
+ err 'invalid rst target'
+ end if
+end inst
+
+iterate <@name, @opc*>, \
+ rlc, 000o, \
+ rrc, 010o, \
+ rl, 020o, \
+ rr, 030o, \
+ sla, 040o, \
+ sra, 050o, \
+ srl, 070o
+ inst @name, @reg*
+ if `@name = 'rl' & ~defined @ez80.pre & ~elementsof reg
+ rb long? * reg
+ define noerr
+ else if regind
+ if reg relativeto reg element 1 & reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 0 = 040o
+ @ez80.emit idxpre reg, byte 313o, idxoff reg, byte @opc or 006o
+ end if
+ else if reg eq reg element 1 & reg @ez80.is_reg @ez80.breg \
+ & reg metadata 1 scale 1 = 003o
+ @ez80.emit <byte 313o, reg metadata 1 scale 0 and 007o or @opc>
+ end if
+ end inst
+end iterate
+iterate @name, bit, res, set
+ inst @name, @bit, @reg*
+ if bitind
+ err 'invalid indirection'
+ else if regind
+ if reg relativeto reg element 1 & reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 0 = 040o
+ @ez80.emit idxpre reg, byte 313o, idxoff bit shr 3 + reg, \
+ byte bit shl 3 and 070o or % shl 6 or 006o
+ end if
+ else if reg eq reg element 1
+ if reg @ez80.is_reg @ez80.breg & reg metadata 1 scale 1 = 003o \
+ & bit = bit and 007o
+ @ez80.emit <byte 313o, reg metadata 1 scale 0 and 007o \
+ or % shl 6 or bit shl 3>
+ else if reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 1 = 007o & bit = bit and 017o
+ @ez80.emit <byte 313o, bit shl 3 and 070o or % shl 6 \
+ or reg metadata 1 scale 0 shr 3 \
+ or 001o and not bit shr 3>
+ end if
+ end if
+ end inst
+end iterate
+
+inst out, @port, @reg*
+ if ~portind
+ err 'missing indirection'
+ else if regind
+ err 'invalid indirection'
+ else if port eq bc? | port eq c?
+ if reg eq reg element 1 & reg @ez80.is_reg @ez80.breg \
+ & reg metadata 1 scale 1 = 003o
+ @ez80.emit <byte 355o, reg metadata 1 scale 0 shl 3 and 070o \
+ or 101o>
+ else if ~reg
+ @ez80.emit <byte 355o, 161o>
+ end if
+ else if reg eq a?
+ @ez80.emit <byte 323o, port>
+ end if
+end inst
+inst in, @reg*, @port
+ if ~defined port
+ @ez80.nest in? f?, @reg
+ else if regind
+ err 'invalid indirection'
+ else if ~portind
+ err 'missing indirection'
+ else if port eq bc? | port eq c? & reg eq reg element 1 \
+ & reg @ez80.is_reg @ez80.breg & reg metadata 1 scale 1 and 002o
+ @ez80.emit <byte 355o, reg metadata 1 scale 0 shl 3 and 070o \
+ or 100o>
+ else if reg eq a?
+ @ez80.emit <byte 333o, port>
+ end if
+end inst
+inst in0, @reg*, @port
+ if ~defined port
+ @ez80.nest in0? f?, @reg
+ else if regind
+ err 'invalid indirection'
+ else if ~portind
+ err 'missing indirection'
+ else if reg eq reg element 1 & reg @ez80.is_reg @ez80.breg \
+ & reg metadata 1 scale 1 and 002o
+ @ez80.emit <byte 355o, reg metadata 1 scale 0 shl 3 and 070o \
+ or 000o, port>
+ end if
+end inst
+inst out0, @port, @reg*
+ if ~portind
+ err 'missing indirection'
+ else if regind
+ err 'invalid indirection'
+ else if reg eq reg element 1 & reg @ez80.is_reg @ez80.breg \
+ & reg metadata 1 scale 1 = 003o
+ @ez80.emit <byte 355o, reg metadata 1 scale 0 shl 3 and 070o \
+ or 001o, port>
+ end if
+end inst
+inst tstio, @src*
+ if srcind
+ err 'invalid indirection'
+ else
+ @ez80.emit <byte 355o, 164o, src>
+ end if
+end inst
+
+inst lea, @dst, @src*
+ if dstind | srcind
+ err 'invalid indirection'
+ else if dst eq dst element 1 & src relativeto src element 1 \
+ & dst @ez80.is_reg @ez80.wreg & src @ez80.is_reg @ez80.wreg \
+ & dst metadata 1 scale 0 <> 060o & src metadata 1 scale 1 > 300o
+ local opc
+ if dst metadata 1 scale 1 and 002o
+ opc = src metadata 1 scale 1 shr 5 and 001o \
+ or dst metadata 1 scale 0 or 002o
+ else if dst relativeto src
+ opc = dst metadata 1 scale 1 shr 5 and 001o or 062o
+ else
+ opc = dst metadata 1 scale 1 shr 5 and 001o or 124o
+ end if
+ @ez80.emit <byte 355o, opc>, offset src scale 0
+ end if
+end inst
+inst pea, @src*
+ if srcind
+ err 'invalid indirection'
+ else if src relativeto src element 1 & src @ez80.is_reg @ez80.wreg \
+ & src metadata 1 scale 1 > 300o
+ @ez80.emit <byte 355o, src metadata 1 scale 1 shr 5 and 001o + 145o>, \
+ offset src scale 0
+ end if
+end inst
+
+inst im, @mode*
+ if modeind
+ err 'invalid indirection'
+ else if mode = 0
+ @ez80.emit <byte 355o, 106o>
+ else if mode = 1
+ @ez80.emit <byte 355o, 126o>
+ else if mode = 2
+ @ez80.emit <byte 355o, 136o>
+ else
+ err 'invalid mode'
+ end if
+end inst
+
+inst mlt, @reg*
+ if regind
+ err 'invalid indirection'
+ else if reg eq reg element 1 & reg @ez80.is_reg @ez80.wreg \
+ & reg metadata 1 scale 1 and 002o
+ @ez80.emit <byte 355o, reg metadata 1 scale 0 or 114o>
+ end if
+end inst
+
+purge inst
+purge end?.inst
diff --git a/frontends/calculator/CEdev/include/fasmg-ez80/ld.fasmg b/frontends/calculator/CEdev/include/fasmg-ez80/ld.fasmg
new file mode 100644
index 0000000..e7bdbf8
--- /dev/null
+++ b/frontends/calculator/CEdev/include/fasmg-ez80/ld.fasmg
@@ -0,0 +1,759 @@
+assert "\"" = '"' ; check for patched fasmg
+include 'tiformat.inc'
+define ez80 ez80
+namespace ez80
+ include 'ez80.inc'
+end namespace
+macro ?! $ : $ , \
+ $@ : $@ , \
+ $$ : $$ , \
+ and : and , \
+ assert : assert , \
+ at : at , \
+ break : break , \
+ define : define , \
+ defined : defined , \
+ dup : dup , \
+ else : else , \
+ emit : emit , \
+ end : end , \
+ equ : equ , \
+ err : err , \
+ esc : esc , \
+ ez80 : ez80 , \
+ from : from , \
+ if : if , \
+ include : include , \
+ irpv : irpv , \
+ iterate : iterate , \
+ label : label , \
+ lengthof : lengthof , \
+ load : load , \
+ local : local , \
+ macro : macro , \
+ match : match , \
+ mod : mod , \
+ namespace: namespace, \
+ not : not , \
+ or : or , \
+ purge : purge , \
+ rb : rb , \
+ repeat : repeat , \
+ restore : restore , \
+ restruc : restruc , \
+ rawmatch : rawmatch , \
+ segment : segment , \
+ shl : shl , \
+ shr : shr , \
+ store : store , \
+ struc : struc , \
+ used : used , \
+ virtual : virtual , \
+ while : while , \
+ xor : xor
+ local global, debug, files, segments, hex, output
+ global equ
+ segments equ
+ restore global, segments
+
+ macro files.libs.parse file, offset, isused, anyused*
+ local private
+ namespace private
+ macro library?! name, version*
+ end if
+ if anyused
+ emit 1: $C0, name, 0, version
+ end if
+ if 0
+ end macro
+ iterate each, export, export_pointer
+ macro each?! function*
+ end if
+ namespace ez80
+ if used global._#function
+ isused = 1
+ global._#function := $ + %-1
+ jp offset
+ virtual
+ local name
+ emit 1: '_', `function
+ load name: $ - $$ from $$
+ global equ name = global._#function
+ end virtual
+ end if
+ offset = offset + word + @ez80.il
+ end namespace
+ if 0
+ end macro
+ end iterate
+ if 0
+ esc include! file
+ end if
+ end namespace
+ end macro
+ macro files.libs.handle file, isused*
+ local offset, anyused
+ offset = 0
+ files.libs.parse file, offset, isused, anyused
+ anyused := isused
+ end macro
+
+ macro files.srcs.check file, isused*
+ local private
+ namespace private
+ iterate name, DEF, GLOBAL, PUBLIC, XDEF
+ iterate style, name, .name
+ macro style?! symbols*&
+ end if
+ iterate symbol, symbols
+ if used global.symbol
+ isused = 1
+ end if
+ end iterate
+ if 0
+ end macro
+ end iterate
+ end iterate
+ if 0
+ esc include! file
+ end if
+ end namespace
+ end macro
+ macro files.srcs.parse file*
+ local private
+ namespace private
+ virtual segments.code.area
+ ?$ equ $
+ ?XOR? equ xor
+ ?AND? equ and
+ ?OR? equ or
+ ?SHL? equ shl
+ ?SHR? equ shr
+ ?NOT? equ not
+ iterate name, LIST, NEWPAGE, NOLIST, PAGE
+ macro name?
+ end macro
+ end iterate
+ iterate name, CPU, TITLE
+ macro name? arg*
+ end macro
+ end iterate
+ iterate name, COPY, INCLUDE
+ macro name?! path*
+ include path
+ end macro
+ end iterate
+ iterate name, EXTERN, EXTERNAL, REF, XREF
+ macro name? symbols*&
+ match list : space, symbols
+ iterate symbol, list
+ symbol := global.symbol
+ end iterate
+ else
+ iterate symbol, symbols
+ symbol := global.symbol
+ end iterate
+ end match
+ end macro
+ end iterate
+ iterate name, DEF, GLOBAL, PUBLIC, XDEF
+ macro name? symbols*&
+ iterate symbol, symbols
+ global.symbol := symbol
+ virtual
+ local name
+ emit 1: `symbol
+ load name: $ - $$ from $$
+ global equ name = global.symbol
+ end virtual
+ end iterate
+ end macro
+ end iterate
+ struc (symbol) EQU? expr*
+ local error
+ if ~defined error & defined symbol | error
+ err 'Symbol "', `symbol, '" already defined'
+ error = 1
+ else
+ error = 0
+ end if
+ ?symbol = expr
+ end struc
+ iterate name, VAR, SET
+ struc (symbol) name? expr*
+ ?symbol = expr
+ end struc
+ end iterate
+ macro DS? count
+ local c
+ c = count
+ rb c
+ end macro
+ struc DS? count
+ .: DS? count
+ end struc
+ iterate <def,blk,size*>, B,B,1, W,W,2, W24,P,3, L,L,4
+ macro D#def? vals*&
+ local v
+ iterate val, vals
+ v = val
+ emit size: v
+ end iterate
+ end macro
+ macro BLK#blk? count*, init
+ local c, i
+ c = count
+ match, init
+ emit size: c dup ?
+ else
+ i = init
+ emit size: c dup i
+ end match
+ end macro
+ iterate name, D#def, BLK#blk
+ struc name? args&
+ .: name? args
+ end struc
+ end iterate
+ end iterate
+ iterate <name,alias*>, TRIO,DW24, DF,DL
+ macro name? vals*&
+ alias? vals
+ end macro
+ struc name? args&
+ .: name? args
+ end struc
+ end iterate
+ macro ALIGN? val*
+ local v
+ v = val
+ rb v-1 - ($ + v-1) mod v
+ end macro
+ macro SEGMENT? name*
+ segment name
+ end macro
+ macro ASSUME? expr*
+ namespace ez80
+ assume? expr
+ end namespace
+ end macro
+ iterate register, B, NZ, Z, NC, C, PO, PE, P, M, D, E, \
+ H, IXH, IYH, L, IXL, IYL, F, A, I, R, \
+ MB, BC, DE, HL, IX, IY, SP, AF, AF'
+ register? := ez80.register?
+ end iterate
+ iterate suffix, , .s?, .l?, .is?, .il?, .sis?, .sil?, .lis?, .lil?
+ irpv name, ez80.@ez80.oplist
+ rawmatch rawname, name
+ define rawname rawname
+ macro rawname#suffix args&
+ namespace ez80
+ name#suffix args
+ end namespace
+ end macro
+ end rawmatch
+ end irpv
+ macro LD? d, s*
+ namespace ez80
+ @ez80.classify dst, dstind, d
+ @ez80.classify src, srcind, s
+ if ~dstind & dst eq dst element 1 & dst @ez80.is_reg @ez80.wreg \
+ & dst metadata 1 scale 1 and 001o & ~srcind \
+ & src relativeto src element 1 & src @ez80.is_reg @ez80.wreg
+ if src metadata 1 scale 1 = 007o
+ PUSH? s
+ POP? d
+ else
+ LEA? d, s
+ end if
+ else
+ LD? d, s
+ end if
+ end namespace
+ end macro
+ macro JR?#suffix args&
+ namespace ez80
+ jq?#suffix args
+ end namespace
+ end macro
+ end iterate
+ iterate <name,carry>, UEXT,<OR? A?,A>, SEXT,RLA
+ macro name? reg*
+ carry?
+ SBC? reg, reg
+ end macro
+ end iterate
+ macro COMMENT?! delim*&
+ end match
+ local inside
+ inside = 0
+ macro ?! line&
+ local length, text
+ length = 0
+ if inside
+ length = lengthof `line
+ text = `line
+ else if `line = 'end match'
+ inside = 1
+ length = lengthof `delim - 1
+ text = `delim shr 8
+ end if
+ repeat length
+ if ~text xor `delim and $FF
+ purge ?
+ break
+ end if
+ text = text shr 8
+ end repeat
+ end macro
+ end macro
+
+ if defined debug
+ debug.enabled = 0
+ debug.startAddr = $
+ iterate name, ALIAS, BASE, DEFINE, ENDREC, SPACE, TAG
+ macro name? str1*
+ if debug.enabled
+ virtual debug
+ debug.uleb128 debug.name
+ debug.string str1
+ end virtual
+ end if
+ end macro
+ end iterate
+ iterate name, BEGFUNC, ENDFUNC
+ macro name? str1, num1, str2*
+ if debug.enabled
+ local line, addr
+ line = num1
+ addr = $
+ virtual debug
+ debug.uleb128 debug.name
+ debug.string str1, str2
+ debug.uleb128 line - debug.line, addr - debug.addr
+ end virtual
+ debug.line = line
+ debug.addr = addr
+ end if
+ end macro
+ end iterate
+ macro BEGREC? str1, num1*
+ if debug.enabled
+ virtual debug
+ debug.uleb128 debug.BEGREC
+ debug.string str1
+ debug.uleb128 num1
+ end virtual
+ end if
+ end macro
+ iterate <name,signed>, CLASS,u, DIM,u, LENGTH,u, REG,u, SIZE,u, TYPE,s, VALUE,s
+ macro name? num1*
+ if debug.enabled
+ virtual debug
+ debug.uleb128 debug.name
+ debug.signed#leb128 num1
+ end virtual
+ end if
+ end macro
+ end iterate
+ macro DEBUG? str1*
+ virtual debug
+ debug.uleb128 debug.FILE, lengthof debug.source
+ emit 1: debug.source
+ debug.uleb128 debug.startAddr - debug.addr, debug.DEBUG
+ debug.string str1
+ end virtual
+ debug.enabled = 1
+ debug.line = 0
+ debug.addr = debug.startAddr
+ end macro
+ macro END?!
+ end if
+ if debug.enabled
+ local addr
+ segment code
+ addr = $
+ virtual debug
+ debug.uleb128 debug.END, addr - debug.addr
+ end virtual
+ debug.addr = addr
+ end if
+ if 0
+ end macro
+ macro ENDEF?
+ if debug.enabled
+ virtual debug
+ debug.uleb128 debug.ENDEF
+ end virtual
+ end if
+ end macro
+ macro FILE? str1*
+ debug.source = str1
+ end macro
+ macro LINE? num1*
+ local line, addr
+ line = num1
+ addr = $
+ if line <> debug.line | addr <> debug.addr & debug.enabled
+ virtual debug
+ debug.uleb128 debug.LINE, line - debug.line, addr - debug.addr
+ end virtual
+ debug.line = line
+ debug.addr = addr
+ end if
+ end macro
+ else
+ iterate name, ALIAS, BASE, BEGFUNC, BEGREC, CLASS, DEBUG, \
+ DEFINE, DIM, ENDEF, ENDFUNC, ENDREC, FILE, \
+ LENGTH, LINE, REG, SIZE, SPACE, TAG, TYPE, VALUE
+ macro name? args&
+ end macro
+ end iterate
+ macro END?!
+ end if
+ if 0
+ end macro
+ end if
+
+ struc ? def::&
+ . def
+ end struc
+ macro ? line&
+ match .rest, line
+ rest
+ else match first= .rest, line
+ first rest
+ else
+ line
+ end match
+ end macro
+ if 1
+ include file
+ end if
+ purge ?
+ restruc ?
+ end virtual
+ end namespace
+ end macro
+ macro files.srcs.handle file, isused*
+ if ~isused
+ files.srcs.check file, isused
+ end if
+ if isused
+ files.srcs.parse file
+ end if
+ end macro
+
+ macro symbol? args*&
+ iterate arg, args
+ rawmatch symbol == value, arg
+ namespace segments
+ global.symbol := value
+ virtual
+ local name
+ emit 1: `symbol
+ load name: $ - $$ from $$
+ global equ = name global.symbol
+ end virtual
+ end namespace
+ else
+ 'Syntax error in symbol arguments'
+ end rawmatch
+ end iterate
+ end macro
+
+ iterate name, srcs, libs
+ macro files.name.add file, used*
+ local isused
+ rawmatch rawused, used
+ namespace segments
+ isused = rawused
+ end namespace
+ end rawmatch
+ if `file and $FF = "'"
+ files.name equ file, isused
+ else
+ files.name equ `file, isused
+ end if
+ end macro
+ macro name? args*&
+ local require
+ iterate arg, args
+ match file= =used? =if?= used, arg
+ files.name.add file, used
+ else match file= =used?, arg
+ files.name.add file, 1
+ else
+ files.name.add arg, 0
+ end match
+ end iterate
+ end macro
+ end iterate
+
+ macro locate? args*&
+ iterate arg, args
+ rawmatch name =at? location, arg
+ segments equ segments.name?
+ namespace segments
+ name? := `name
+ name.base? := location
+ end namespace
+ else
+ err 'Syntax error in locate argument'
+ end rawmatch
+ end iterate
+ end macro
+ macro range? args*&
+ iterate arg, args
+ rawmatch name lower : upper, arg
+ locate name at lower
+ namespace segments
+ name.high? := upper
+ end namespace
+ else
+ err 'Syntax error in range arguments'
+ end rawmatch
+ end iterate
+ end macro
+ macro order?: args*&
+ match first =, second =, rest, args
+ order first, second
+ order second, rest
+ else match first =, second, args
+ locate second at first.base + first.length
+ else
+ err 'Not enough order arguments'
+ end match
+ end macro
+ macro merge? args*&
+ match name == list, args
+ order list
+ iterate segment, list
+ locate name at segment.base
+ indx %%
+ namespace segments
+ name.top? := segment.base + segment.length
+ if defined segment.high
+ name.high? := segment.high
+ end if
+ end namespace
+ break
+ end iterate
+ else
+ err 'Syntax error in merge arguments'
+ end match
+ end macro
+
+ macro hex value*, leading: '0', digits: 6
+ local val, zero, digit, char
+ emit 1: ' '
+ val = value
+ zero = leading
+ repeat digits
+ digit = (val shr ((%% - %) shl 2)) and 0Fh
+ if digit < 10
+ char = '0' + digit
+ else
+ char = 'A' + digit - 10
+ end if
+ if digit
+ zero = '0'
+ else if % <> %%
+ char = zero
+ end if
+ emit 1: char
+ end repeat
+ end macro
+
+ macro map?
+ local longest, name
+ postpone ?
+ virtual as 'map'
+ longest = lengthof "Segment"
+ irpv segment, segments
+ if longest < lengthof segment
+ longest = lengthof segment
+ end if
+ end irpv
+ emit 1: "Segment", longest - lengthof "Segment" + 1 dup ' ', "Base Top High Length", 10, longest dup '-', 4 dup " ------", '-', 10
+ irpv segment, segments
+ namespace segment
+ if longest < lengthof segment
+ longest = lengthof segment
+ end if
+ emit 1: segment, longest - lengthof segment dup ' '
+ hex base
+ hex top
+ if defined high
+ hex high
+ else
+ emit 1: 7 dup ' '
+ end if
+ hex length, ' '
+ emit 1: 'h', 10
+ end namespace
+ end irpv
+ match any, global
+ longest = lengthof "Label"
+ irpv symbol, global
+ match name == value, symbol
+ if longest < lengthof name
+ longest = lengthof name
+ end if
+ end match
+ end irpv
+ emit 1: 10, "Label", longest - lengthof "Label" + 3 dup ' ', "Value", 10, longest dup '-', 3 dup ' ', 6 dup '-', 10
+ irpv symbol, global
+ match name == value, symbol
+ emit 1: name, longest - lengthof name + 1 dup ' ', '='
+ hex value
+ emit 1: 10
+ end match
+ end irpv
+ end match
+ end virtual
+ end postpone
+ end macro
+ macro dbg?
+ virtual as 'dbg'
+ debug::
+ end virtual
+ namespace debug
+ virtual at 0
+ iterate name, EOF, ALIAS, BASE, BEGFUNC, BEGREC, CLASS, DEBUG, DEFINE, \
+ DIM, END, ENDEF, ENDFUNC, ENDREC, FILE, LENGTH, LINE, \
+ REG, SIZE, SPACE, STRINGS, TAG, TYPE, VALUE
+ name rb 1
+ end iterate
+ end virtual
+ line = 0
+ addr = 0
+ macro uleb128 values*&
+ iterate value, values
+ local val
+ val = value
+ assert val >= 0
+ while val shr 7 > 0
+ emit 1: val and 07Fh or 080h
+ val = val shr 7
+ end while
+ emit 1: val
+ end iterate
+ end macro
+ macro sleb128 values*&
+ iterate value, values
+ local val
+ val = value
+ while val shr 6 <> 0 & val shr 6 <> -1
+ emit 1: val and 07Fh or 080h
+ val = val shr 7
+ end while
+ emit 1: val and 07Fh
+ end iterate
+ end macro
+ restore strings
+ macro string values*&
+ iterate value, values
+ local count, unfound
+ count = 0
+ unfound = 1
+ irpv each, debug.strings
+ if each = value
+ unfound = 0
+ debug.uleb128 %
+ break
+ end if
+ count = %%
+ end irpv
+ if unfound
+ debug.uleb128 count + 1
+ debug.strings =: value
+ end if
+ end iterate
+ end macro
+ end namespace
+ end macro
+
+ macro segment name*
+ end virtual
+ virtual segments.name.area
+ end macro
+
+ if ~defined segments
+ err 'No segments defined'
+ else
+ restore output.base, output.top ; forbid forward reference
+ irpv segment, segments
+ namespace segment
+ virtual at base
+ area?::
+ end virtual
+ if ~defined output.base | output.base > base & ~defined high
+ output.base = base
+ end if
+ end namespace
+ end irpv
+ irpv file, files.srcs
+ files = 0
+ files.srcs.handle file
+ end irpv
+ if ~defined files
+ err 'Please pass the input files with -i\'srcs "file1" [if require1], "file2" [if require2], ...\''
+ end if
+ irpv file, files.libs
+ virtual segments.libs.area
+ files.libs.handle file
+ end virtual
+ end irpv
+
+ if defined debug
+ virtual debug
+ if defined debug.strings
+ debug.uleb128 debug.STRINGS
+ irpv string, debug.strings
+ if % = 1
+ debug.uleb128 %%
+ end if
+ debug.uleb128 lengthof string
+ emit 1: string
+ end irpv
+ end if
+ debug.uleb128 debug.EOF
+ end virtual
+ end if
+
+ irpv segment, segments
+ namespace segment
+ virtual area
+ top? := $
+ length? := $ - $$
+ initlen? := $@ - $$
+ end virtual
+ if ~defined high
+ if ~defined output.top | output.top < top
+ output.top = top
+ end if
+ else if top > high
+ repeat 1, len: length, over: top - high, max: high - base
+ err 'Segment ', segment, ' is ', `len, ' bytes, ', \
+ `over, ' bytes larger than the maximum of ', \
+ `max, ' bytes'
+ end repeat
+ end if
+ end namespace
+ end irpv
+ org output.base
+ rb output.top - $
+ postpone ?
+ irpv segment, segments
+ namespace segment
+ if ~defined high
+ load output: initlen from area: base
+ store output: initlen at base
+ end if
+ end namespace
+ end irpv
+ end postpone
+ end if
+ purge ?
+end macro
diff --git a/frontends/calculator/CEdev/include/fasmg-ez80/ti84pceg.inc b/frontends/calculator/CEdev/include/fasmg-ez80/ti84pceg.inc
new file mode 100644
index 0000000..73b7fc1
--- /dev/null
+++ b/frontends/calculator/CEdev/include/fasmg-ez80/ti84pceg.inc
@@ -0,0 +1,61 @@
+macro ?!
+ ; assign needs to be local so that it is only
+ ; defined once (no purge!) so that it can be
+ ; forward referenced so that it can recurse
+ local assign
+ macro assign: name*, expr&
+ match left =% right, expr
+ assign name, left mod right
+ else match left =| right, expr
+ assign name, left or right
+ else match left =& right, expr
+ assign name, left and right
+ else match left =^ right, expr
+ assign name, left xor right
+ else match left =<=< right, expr
+ assign name, left shl right
+ else match left =>=> right, expr
+ assign name, left shr right
+ else match left =~ right, expr
+ assign name, left not right
+ else match =~ right, expr
+ assign name, not right
+ else
+ name? := expr
+ end match
+ end macro
+ struc (name) equ? expr&
+ assign name, expr
+ end struc
+ macro Ld args&
+ match =equ? expr, args
+ assign name, expr
+ end match
+ end macro
+ purge ?
+end macro
+
+macro .list?
+end macro
+macro .nolist?
+end macro
+macro #define? name
+end macro
+macro #ifdef? name
+end macro
+macro #ifndef? name
+end macro
+macro #endif?
+end macro
+
+element anovaf_vars?
+include 'ti84pce.inc'
+
+restruc equ?
+purge Ld
+purge .list?
+purge .nolist?
+purge #define?
+purge #ifdef?
+purge #ifndef?
+purge #endif?
diff --git a/frontends/calculator/CEdev/include/fasmg-ez80/tiformat.inc b/frontends/calculator/CEdev/include/fasmg-ez80/tiformat.inc
new file mode 100644
index 0000000..23ec697
--- /dev/null
+++ b/frontends/calculator/CEdev/include/fasmg-ez80/tiformat.inc
@@ -0,0 +1,105 @@
+macro format?.ti? clause&
+ local all, checkloc, checksum, cplx, data, exec, flag, head, name, process, prot, temp, type, ext, var
+ macro process: setting
+ match first rest, setting
+ process first
+ process rest
+ else match =ARCHIVED?, setting
+ flag = flag or 1 shl 7
+ else match =EXECUTABLE?, setting
+ define exec
+ else match =PROTECTED?, setting
+ type = 6
+ define prot
+ else match =REAL?, setting
+ type = 0
+ ext = '8xn'
+ else match =LIST?, setting
+ if defined cplx
+ type = 13
+ else
+ type = 2
+ end if
+ ext = '8xl'
+ else match =MATRIX?, setting
+ type = 2
+ ext = '8xm'
+ else match =EQUATION?, setting
+ type = 3
+ ext = '8xy'
+ else match =STRING?, setting
+ type = 4
+ ext = '8xs'
+ else match =PROGRAM?, setting
+ if defined prot
+ type = 6
+ else
+ type = 5
+ end if
+ ext = '8xp'
+ else match =PICTURE?, setting
+ type = 7
+ ext = '8ci'
+ else match =GDB?, setting
+ type = 1
+ ext = '8xd'
+ else match =COMPLEX?, setting
+ type = 12
+ define cplx
+ ext = '8xc'
+ else match =APPVAR?, setting
+ type = 21
+ ext = '8xv'
+ else match =GROUP?, setting
+ type = 23
+ ext = '8xg'
+ else match =IMAGE?, setting
+ type = 26
+ ext = '8ca'
+ else if setting eqtype 'name'
+ name = setting
+ else if setting eqtype 0
+ type = setting
+ ext = '8x'
+ end if
+ end macro
+ name = 'A'
+ type = 6
+ ext = '8xp'
+ flag = 0
+ process clause
+ format binary as ext
+ assert ~$% & 'Unexpected data before format directive'
+ dq '**TI83F*'
+ db 26, 10, 0
+ rb 42
+ dw sizeof all
+ label all: checkloc - $%
+ dw sizeof head, sizeof data
+ label head: data - $
+ db type
+ dq name
+ db 0, flag
+ dw sizeof data
+ label data: checkloc - $%
+ dw sizeof var
+ label var: checkloc - $%
+ if defined exec
+ dw 07BEFh
+ org 0D1A881h
+ else
+ org 0
+ end if
+ postpone
+ label checkloc at $%
+ end postpone
+ postpone ?
+ assert checkloc = $% & 'Unexpected postpone before format directive'
+ checksum = 0
+ repeat sizeof all
+ load temp: byte from: all + %-1
+ checksum = (checksum + temp) and 0FFFFh
+ end repeat
+ dw checksum
+ end postpone
+end macro