uxn/projects/library/asma.tal

903 lines
22 KiB
Tal
Raw Normal View History

(
Asma - an in-Uxn assembler
This assembler aims to be binary compatible with the output from
src/uxnasm.c, but unlike that assembler this one can be run inside Uxn
itself!
Asma is designed to be able to be copy-pasted inside another project, so
all its routines are prefixed with "asma-" to prevent clashes with labels
used in the incorporating project. The reset vector contains a couple of
examples of asma's usage and can be discarded.
)
2021-05-15 13:08:08 -04:00
(
Common macros for use later on.
)
2021-05-03 14:15:06 -04:00
%asma-IF-ERROR { ;asma/error LDA2 ORA }
2021-05-15 14:58:50 -04:00
(
Asma's public interface.
These routines are what are expected to be called from programs that bundle
Asma into bigger projects.
)
@asma-assemble-file ( src-filename* dest-filename* -- )
2021-11-05 18:48:04 -04:00
#01 .File/append DEO
DUP2 .File/name DEO2
#01 .File/delete DEO
2021-05-15 14:58:50 -04:00
;asma/dest-filename STA2 ;asma/src-filename STA2
;asma-init-first-pass JSR2
2021-05-15 16:02:33 -04:00
;asma-flush-ignore ;asma/flush-fn STA2
2021-05-15 14:58:50 -04:00
;asma/src-filename LDA2 ;asma-assemble-file-pass JSR2
asma-IF-ERROR ,&error JCN
;asma-init-next-pass JSR2
2021-05-15 16:02:33 -04:00
;asma-flush-to-file ;asma/flush-fn STA2
;asma/dest-filename LDA2 ORA ,&filename-present JCN
;asma-flush-to-console ;asma/flush-fn STA2
&filename-present
2021-05-15 14:58:50 -04:00
;asma/src-filename LDA2 ;asma-assemble-file-pass JSR2
asma-IF-ERROR ,&error JCN
2021-10-06 01:14:18 -04:00
( flush output buffer )
;asma-output/ptr LDA2 ;asma-write-buffer SUB2 ;asma/flush-fn LDA2 JSR2
2021-05-15 14:58:50 -04:00
;asma-trees/labels ;asma-print-labels JSR2 ( DEBUG )
2021-05-16 04:27:06 -04:00
;asma-print-line-count JSR2 ( DEBUG )
;asma-print-heap-usage JSR2 ( DEBUG )
2021-05-15 14:58:50 -04:00
JMP2r
&error
;asma-print-error JSR2 ( DEBUG )
JMP2r
2021-05-15 13:08:08 -04:00
(
Debugging routines. These all output extra information to the Console.
These can be stripped out to save space, once the references to them are
2021-05-15 14:58:50 -04:00
removed. Look for the word DEBUG above to find these references: the lines
that contain that word can be deleted to strip out the functionality
2021-05-15 13:08:08 -04:00
cleanly.
)
2021-05-15 14:58:50 -04:00
@asma-print-error ( -- )
.File/name DEI2 ;asma-print-string JSR2
;&line ;asma-print-string JSR2
;asma/line LDA2 ;asma-print-short JSR2
#3a .Console/error DEO
#20 .Console/error DEO
;asma/error LDA2 ;asma-print-string JSR2
2021-10-07 16:57:54 -04:00
#3a .Console/error DEO
#20 .Console/error DEO
;asma/orig-token LDA2 ;asma-print-string JSR2
2021-10-07 16:57:54 -04:00
#2e .Console/error DEO
#0a .Console/error DEO
2021-05-16 05:20:04 -04:00
JMP2r
2021-05-15 14:58:50 -04:00
&line 20 "line 20 00
2021-05-15 14:58:50 -04:00
2021-05-16 04:27:06 -04:00
@asma-print-line-count ( -- )
;asma/log-level LDA #01 AND #00 EQU ,&skip JCN
2021-10-07 16:58:54 -04:00
;asma/lines LDA2 ;asma-print-short JSR2
;&lines ;asma-print-string JSR2
&skip
2021-05-15 14:58:50 -04:00
JMP2r
2021-05-16 04:27:06 -04:00
&lines [ 20 "lines 20 "of 20 "source 20 "code. 0a 00 ]
@asma-print-heap-usage ( -- )
;asma/log-level LDA #08 AND #00 EQU ,&skip JCN
2021-10-06 01:42:19 -04:00
;heap LDA2 ;asma-heap SUB2 ;asma-print-short JSR2
;&str1 ;asma-print-string JSR2
2021-10-06 01:42:19 -04:00
;asma-heap/end ;heap LDA2 SUB2 ;asma-print-short JSR2
;&str2 ;asma-print-string JSR2
&skip
2021-05-16 04:27:06 -04:00
JMP2r
&str1 [ 20 "bytes 20 "of 20 "heap 20 "used, 20 00 ]
&str2 [ 20 "bytes 20 "free. 0a 00 ]
2021-05-15 14:58:50 -04:00
@asma-print-sublabels ( incoming-ptr* -- )
2021-05-14 03:09:55 -04:00
LDA2
ORAk ,&valid-incoming-ptr JCN
POP2 JMP2r
&valid-incoming-ptr
( left node )
2021-05-15 14:58:50 -04:00
DUP2 ,asma-print-sublabels JSR
2021-05-14 03:09:55 -04:00
( here )
2021-10-07 16:57:54 -04:00
#09 .Console/error DEO
2021-05-14 03:09:55 -04:00
DUP2 #0004 ADD2
&loop
2021-08-26 18:27:18 -04:00
DUP2 INC2 SWP2 LDA
2021-05-14 03:09:55 -04:00
DUP #00 EQU ,&end JCN
2021-10-07 16:57:54 -04:00
.Console/error DEO
2021-05-14 03:09:55 -04:00
,&loop JMP
&end
POP
2021-10-07 16:57:54 -04:00
#09 .Console/error DEO
LDA2 ;asma-print-short JSR2
2021-10-07 16:57:54 -04:00
#0a .Console/error DEO
2021-05-14 03:09:55 -04:00
( right node )
2021-05-15 14:58:50 -04:00
#0002 ADD2 ,asma-print-sublabels JSR
2021-05-14 03:09:55 -04:00
JMP2r
2021-05-15 14:58:50 -04:00
@asma-print-labels ( incoming-ptr* -- )
;asma/log-level LDA #04 AND #00 EQU ,&skip JCN
2021-05-14 03:09:55 -04:00
LDA2
ORAk ,&valid-incoming-ptr JCN
&skip
2021-05-14 03:09:55 -04:00
POP2 JMP2r
&valid-incoming-ptr
( left node )
2021-05-15 14:58:50 -04:00
DUP2 ,asma-print-labels JSR
2021-05-14 03:09:55 -04:00
( here )
DUP2 #0004 ADD2
LDAk LIT 'A LTH ,&loop JCN
LDAk LIT 'Z GTH ,&loop JCN
POP2
,&skip-device-label JMP
2021-05-14 03:09:55 -04:00
&loop
2021-08-26 18:27:18 -04:00
DUP2 INC2 SWP2 LDA
2021-05-14 03:09:55 -04:00
DUP #00 EQU ,&end JCN
2021-10-07 16:57:54 -04:00
.Console/error DEO
2021-05-14 03:09:55 -04:00
,&loop JMP
&end
POP
2021-10-07 16:57:54 -04:00
#09 .Console/error DEO
LDA2k ;asma-print-short JSR2
2021-10-07 16:57:54 -04:00
#0a .Console/error DEO
2021-05-14 03:09:55 -04:00
( subtree )
2021-05-15 14:58:50 -04:00
#0002 ADD2 ;asma-print-sublabels JSR2
2021-05-14 03:09:55 -04:00
&skip-device-label
2021-05-14 03:09:55 -04:00
( right node )
2021-05-15 14:58:50 -04:00
#0002 ADD2 ,asma-print-labels JSR
2021-05-14 03:09:55 -04:00
JMP2r
@asma-print-string ( ptr* -- )
LDAk DUP ,&keep-going JCN
POP POP2 JMP2r
&keep-going
2021-10-07 16:57:54 -04:00
.Console/error DEO
2021-08-26 18:27:18 -04:00
INC2
,asma-print-string JMP
@asma-print-short ( short* -- )
2021-10-07 16:57:54 -04:00
LIT '0 .Console/error DEO
LIT 'x .Console/error DEO
OVR #04 SFT ,&hex JSR
SWP #0f AND ,&hex JSR
DUP #04 SFT ,&hex JSR
#0f AND ,&hex JMP
&hex
#30 ADD DUP #3a LTH ,&not-alpha JCN
#27 ADD
&not-alpha
2021-10-07 16:57:54 -04:00
.Console/error DEO
JMP2r
2021-05-15 14:58:50 -04:00
(
Initialise the assembler state before loading a file or chunk.
)
2021-05-03 14:15:06 -04:00
2021-05-15 14:58:50 -04:00
@asma-init-first-pass ( -- )
#ff ;asma/pass STA
2021-05-15 16:02:33 -04:00
#0000 DUP2k
;asma/error STA2
;asma-trees/labels STA2
;asma-trees/macros STA2
2021-05-15 14:58:50 -04:00
;asma-opcodes/_entry ;asma-trees/opcodes STA2
( fall through )
2021-05-14 03:09:55 -04:00
2021-05-15 14:58:50 -04:00
@asma-init-next-pass ( -- )
2021-08-26 18:27:18 -04:00
;asma/pass LDA INC ;asma/pass STA
2021-05-15 16:02:33 -04:00
;asma-write-buffer ;asma-output/ptr STA2
#0000 DUP2
2021-05-15 16:02:33 -04:00
;asma/addr STA2
;asma/state STA
2021-10-04 17:28:13 -04:00
#01 SWP ( 0100 ) ;asma/written-addr STA2
;&preamble-end ;&preamble SUB2k ;asma-assemble-chunk JSR2 POP2 POP2
2021-05-15 14:58:50 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
2021-08-18 02:33:53 -04:00
&preamble
"%BRK 20 '{ 20 "00 20 '} 20
&preamble-end
2021-05-15 14:58:50 -04:00
(
Divide a file up into chunks, and pass each chunk to asma-assemble-chunk.
)
2021-05-03 14:15:06 -04:00
@asma-assemble-file-pass ( filename-ptr* -- )
;asma-assemble-chunk #0000 ROT2 ( func* line^ filename* )
2021-10-04 17:28:13 -04:00
;asma-read-buffer DUP2 ;asma-read-buffer/end ROT2 SUB2 ( func* line^ filename* buf* size^ )
ROT2 ( func* line^ buf* size^ filename* )
,file-read-chunks JSR
2021-04-18 07:48:49 -04:00
2021-10-04 17:28:13 -04:00
asma-IF-ERROR ,&error JCN
2021-05-15 16:02:33 -04:00
&error
2021-10-04 17:28:13 -04:00
POP2 POP2 POP2 POP2 POP2
JMP2r
2021-10-04 17:28:13 -04:00
include projects/library/file-read-chunks.tal
2021-05-15 14:58:50 -04:00
(
Assemble a chunk of source code, which begins with whitespace or the start
of a token and is divided up into tokens separated by whitespace. If the
chunk ends with whitespace, assembled-up-to-ptr* will equal ptr* + len* and
every token in the chunk will have been assembled. If the chunk ends with a
non-whitespace character, assembled-up-to-ptr* will point to the beginning
of the last token in the chunk.
)
2021-04-12 16:01:36 -04:00
2021-10-06 01:14:18 -04:00
@asma-assemble-chunk ( line^ chunk* len^ -- line^ assembled-up-to-chunk* )
ROT2 STH2 ( chunk* len^ / line^ )
OVR2 ADD2 ( chunk* end-chunk* / line^ )
OVR2 ;asma-read-buffer EQU2 STH
DUP2 ;asma-read-buffer/end NEQ2
STHr AND ;asma/eof STA
SWP2 STH2k ( end-chunk* chunk* / line^ start-of-token* )
&loop ( end-chunk* char* / line^ start-of-token* )
LDAk #21 LTH ,&whitespace JCN
INC2 ,&loop JMP
&whitespace ( end-chunk* ws-char* / line^ start-of-token* )
GTH2k ,&within-chunk JCN
;asma/eof LDA ,&eof JCN
( reached the end of the chunk, start-of-token* is where we assembled up to )
POP2 POP2 STH2r STH2r SWP2 JMP2r
&within-chunk ( end-chunk* ws-char* / line^ start-of-token* )
LDAk #0a NEQ ( end-chunk* ws-char* not-newline / line^ start-of-token* )
#00 OVR2 STA
STH2r ,asma-assemble-token JSR ( end-chunk* ws-char* not-newline / line^ )
2021-10-04 17:28:13 -04:00
asma-IF-ERROR ,&error JCN
2021-10-07 16:58:54 -04:00
,&not-newline JCN
,asma/lines LDR2 INC2 ,asma/lines STR2
&not-newline ( end-chunk* ws-char* / line^ )
2021-10-06 01:14:18 -04:00
;asma/break LDA ,&break JCN
INC2 STH2k ( end-chunk* start-of-token* / line^ start-of-token* )
2021-10-04 17:28:13 -04:00
,&loop JMP
2021-04-12 16:01:36 -04:00
2021-10-06 01:14:18 -04:00
&break ( end-chunk* ws-char* / line^ )
( the read buffer has been invalidated, ws-char* plus one is where we assembled up to )
;asma/break LDA #01 SUB ;asma/break STA
INC2 NIP2 ( assembled-up-to-ptr* / line^ )
STH2r SWP2 JMP2r
2021-03-31 18:55:02 -04:00
&error ( end-chunk* ws-char* not-newline / line^ )
2021-10-06 01:14:18 -04:00
( return no progress with assembly to make file-read-chunks exit )
POP POP2 POP2
STH2kr ;asma/line STA2
STH2r ;asma-read-buffer
2021-03-31 18:55:02 -04:00
JMP2r
2021-10-06 01:14:18 -04:00
&eof ( end-chunk* ws-char* / line^ start-of-token* )
( reached the end of file, end-chunk* is safe to write since the buffer is bigger )
( return no progress with assembly to make file-read-chunks exit )
POP2 ( end-chunk* / line^ start-of-token* )
#00 ROT ROT STA ( / line^ start-of-token* )
STH2r ,asma-assemble-token JSR ( / line^ )
STH2r ;asma-read-buffer JMP2r
@asma [
2021-10-07 16:58:54 -04:00
&pass $1 &state $1 &line $2 &lines $2 &break $1 &eof $1
&token $2 &orig-token $2
2021-10-06 01:42:19 -04:00
&addr $2 &written-addr $2 &flush-fn $2
&src-filename $2 &dest-filename $2
&error $2 &log-level $1
]
2021-05-03 14:15:06 -04:00
@asma-trees [ &labels $2 &macros $2 &opcodes $2 &scope $2 ]
2021-03-31 18:55:02 -04:00
2021-05-15 13:08:08 -04:00
(
The main routine to assemble a single token.
asma/state contains several meaningful bits:
0x02 we are in a comment,
2021-10-06 01:14:18 -04:00
0x04 we are in a macro body,
0x08 we are expecting an include filename, and
0x10 we are in a macro body that we are ignoring
2021-05-15 13:08:08 -04:00
(because the macro was already defined in a previous pass).
2021-10-06 01:14:18 -04:00
Since 0x10 never appears without 0x04, the lowest bit set in asma/state is
2021-05-15 13:08:08 -04:00
always 0x00, 0x02, or 0x04, which is very handy for use with jump tables.
The lowest bit set can be found easily by #00 (n) SUBk AND.
)
2021-05-03 14:15:06 -04:00
@asma-assemble-token ( string-ptr* -- )
DUP2 ;asma/token STA2
DUP2 ;asma/orig-token STA2
2021-05-13 17:51:36 -04:00
LDAk ,&not-empty JCN
2021-05-03 14:15:06 -04:00
POP2
2021-03-31 18:55:02 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
&not-empty ( token* / )
( truncate to one char long )
2021-08-26 18:27:18 -04:00
INC2 ( end* / )
2021-05-13 17:51:36 -04:00
STH2k LDAkr ( end* / end* char )
STH2k ( end* / end* char end* )
2021-05-03 14:15:06 -04:00
LITr 00 STH2 ( / end* char end* 00 end* )
STAr ( / end* char end* )
2021-03-31 18:55:02 -04:00
2021-05-13 17:51:36 -04:00
#00 ;asma/state LDA SUBk AND ( tree-offset* / end* )
2021-05-03 14:15:06 -04:00
DUP2 ;&first-char-trees ADD2 ( tree-offset* incoming-ptr* / end* )
;asma-traverse-tree JSR2
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
( restore truncated char )
STAr
2021-03-31 18:55:02 -04:00
2021-05-11 14:12:07 -04:00
,&not-found JCN
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
( tree-offset* token-routine-ptr* / end* )
STH2r ;asma/token STA2
2021-08-15 16:25:58 -04:00
NIP2 LDA2
2021-05-03 14:15:06 -04:00
JMP2 ( tail call )
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&not-found ( tree-offset* dummy* / end* )
POP2 POP2r
2021-05-15 13:08:08 -04:00
;&body-routines ADD2 LDA2
2021-05-03 14:15:06 -04:00
JMP2 ( tail call )
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&first-char-trees
:asma-first-char-normal/_entry
:asma-first-char-comment/_entry
:asma-first-char-macro/_entry
2021-10-06 01:14:18 -04:00
$2 ( invalid position )
$2 ( empty tree for include )
2021-03-31 18:55:02 -04:00
2021-05-15 13:08:08 -04:00
&body-routines
2021-05-03 14:15:06 -04:00
:asma-normal-body
:asma-ignore
:asma-macro-body
2021-10-06 01:14:18 -04:00
$2 ( invalid position )
:asma-include-filename
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
@asma-parse-hex-digit ( charcode -- 00-0f if valid hex
OR 10-ff otherwise )
2021-05-11 14:12:07 -04:00
DUP #3a LTH ,&digit JCN
DUP #60 GTH ,&letter JCN
2021-05-03 14:15:06 -04:00
JMP2r
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&digit
#30 SUB
JMP2r
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&letter
#57 SUB
2021-03-31 18:55:02 -04:00
JMP2r
@asma-parse-hex-string ( strict -- value* 06 if valid hex and (length == 4 or (length == 3 and not strict))
OR value* 03 if valid hex and (length == 2 or (length == 1 and not strict))
OR 00 otherwise )
STH
;asma/token LDA2 DUP2 ,strlen JSR ( token* length^ )
DUP STHr AND ,&fail2 JCN
DUP2 #0004 GTH2 ,&fail2 JCN
ORAk #00 EQU ,&fail2 JCN
#0002 GTH2 ROT ROT
2021-05-03 14:15:06 -04:00
LIT2r 0000
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&loop
2021-05-13 17:51:36 -04:00
LDAk
2021-05-11 14:12:07 -04:00
DUP ,&not-end JCN
2021-05-03 14:15:06 -04:00
POP POP2
2021-08-26 18:27:18 -04:00
STH2r ROT INC DUPk ADD ADD
2021-03-31 18:55:02 -04:00
JMP2r
2021-04-24 05:50:21 -04:00
&not-end
2021-05-03 14:15:06 -04:00
,asma-parse-hex-digit JSR
2021-05-11 14:12:07 -04:00
DUP #f0 AND ,&fail JCN
2021-05-24 17:52:11 -04:00
LITr 40 SFT2r
2021-05-03 14:15:06 -04:00
#00 STH STH ADD2r
2021-08-26 18:27:18 -04:00
INC2
2021-04-24 05:50:21 -04:00
,&loop JMP
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&fail
POP2r
&fail2
POP2 POP2
#00
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
%asma-SHORT-FLAG { #20 }
%asma-RETURN-FLAG { #40 }
2021-05-12 18:51:34 -04:00
%asma-KEEP-FLAG { #80 }
2021-03-31 18:55:02 -04:00
include projects/library/string.tal
2021-10-06 01:54:03 -04:00
@asma-traverse-tree ( incoming-ptr* -- binary-ptr* 00 if key found
OR node-incoming-ptr* 01 if key not found )
;asma/token LDA2
( fall through to traverse-tree )
include projects/library/binary-tree.tal
2021-05-03 14:15:06 -04:00
@asma-parse-opcode ( -- byte 00 if valid opcode
OR 01 otherwise )
;asma/token LDA2
2021-10-06 01:54:03 -04:00
DUP2 ,strlen JSR #0003 LTH2 ,&too-short JCN
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
( truncate to three chars long )
#0003 ADD2 ( end* / )
2021-05-13 17:51:36 -04:00
STH2k LDAkr ( end* / end* char )
STH2k ( end* / end* char end* )
2021-05-03 14:15:06 -04:00
LITr 00 STH2 ( / end* char end* 00 end* )
STAr ( / end* char end* )
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
;asma-trees/opcodes ;asma-traverse-tree JSR2
STAr
2021-05-11 14:12:07 -04:00
,&not-found JCN
2021-04-14 17:00:10 -04:00
;asma-opcodes/_disasm SUB2 #03 SFT2 ( 00 byte / end* )
2021-10-29 19:28:33 -04:00
DUP #00 EQU ,&set-keep JCN ( force keep flag for LIT )
2021-05-03 14:15:06 -04:00
&loop
2021-05-13 17:51:36 -04:00
LDAkr STHr LIT2r 0001 ADD2r ( 00 byte char / end* )
2021-05-11 14:12:07 -04:00
DUP ,&not-end JCN
2021-05-03 14:15:06 -04:00
POP POP2r
SWP
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
&not-end
2021-05-11 14:12:07 -04:00
DUP LIT '2 NEQ ,&not-two JCN
2021-05-03 14:15:06 -04:00
POP asma-SHORT-FLAG ORA ,&loop JMP
2021-04-11 18:45:31 -04:00
2021-05-03 14:15:06 -04:00
&not-two
2021-05-12 18:51:34 -04:00
DUP LIT 'r NEQ ,&not-return JCN
POP asma-RETURN-FLAG ORA ,&loop JMP
2021-04-24 05:50:21 -04:00
2021-05-12 18:51:34 -04:00
&not-return
LIT 'k NEQ ,&not-keep JCN
2021-10-29 19:28:33 -04:00
&set-keep asma-KEEP-FLAG ORA ,&loop JMP
2021-05-12 18:51:34 -04:00
&not-keep ( 00 byte / end* )
2021-05-03 14:15:06 -04:00
&not-found ( incoming-ptr* / end* )
POP2r
&too-short ( token* / )
POP2 #01
2021-04-11 18:45:31 -04:00
JMP2r
2021-05-15 16:02:33 -04:00
@asma-write-short ( short -- )
SWP
,asma-write-byte JSR
,asma-write-byte JMP ( tail call )
2021-05-03 14:15:06 -04:00
@asma-write-byte ( byte -- )
;asma/addr LDA2 ;asma/written-addr LDA2
LTH2k ,&rewound JCN
&loop
EQU2k ,&ready JCN
#00 ,&write JSR
2021-08-26 18:27:18 -04:00
INC2
,&loop JMP
2021-05-15 16:02:33 -04:00
&rewound
;asma-msg-rewound ;asma/error STA2
POP2 POP2 POP JMP2r
&ready
2021-08-26 18:27:18 -04:00
POP2 INC2
DUP2 ;asma/addr STA2
;asma/written-addr STA2
&write
2021-05-15 16:02:33 -04:00
,asma-output/ptr LDR2
DUP2 ;asma-write-buffer/end EQU2 ,&flush JCN
&after-flush
STH2k STA
2021-08-26 18:27:18 -04:00
STH2r INC2 ,asma-output/ptr STR2
2021-04-11 18:45:31 -04:00
JMP2r
2021-05-15 16:02:33 -04:00
&flush ( ptr* -- start-of-buffer* )
;asma-write-buffer SUB2k ( ptr* start* len* )
;asma/flush-fn LDA2 JSR2
2021-08-15 16:25:58 -04:00
NIP2 ( start* )
2021-05-15 16:02:33 -04:00
,&after-flush JMP
@asma-output [ &ptr $2 ]
2021-05-15 16:02:33 -04:00
@asma-flush-ignore ( len* -- )
POP2
JMP2r
@asma-flush-to-file ( len* -- )
.File/length DEO2
2021-05-15 16:02:33 -04:00
;asma/dest-filename LDA2 .File/name DEO2
2021-11-07 14:10:30 -05:00
;asma-write-buffer .File/write DEO2
2021-05-15 16:02:33 -04:00
JMP2r
2021-04-11 18:45:31 -04:00
@asma-flush-to-console ( len* -- )
ORAk ,&not-empty JCN
POP2 JMP2r
&not-empty
;asma-write-buffer DUP2 ROT2 ADD2 SWP2 ( end* ptr* )
&loop ( end* ptr* )
LDAk .Console/write DEO
INC2
GTH2k ,&loop JCN
POP2 POP2
JMP2r
2021-10-06 01:42:19 -04:00
include projects/library/heap.tal
2021-05-03 14:15:06 -04:00
2021-05-15 13:08:08 -04:00
(
First character routines.
The following routines (that don't have a FORTH-like signature) are called
to deal with tokens that begin with particular first letters, or (for
-body routines) tokens that fail to match any first letter in their tree.
)
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
%asma-STATE-SET { ;asma/state LDA ORA ;asma/state STA }
%asma-STATE-CLEAR { #ff EOR ;asma/state LDA AND ;asma/state STA }
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-comment-start
#02 asma-STATE-SET
@asma-ignore
JMP2r
2021-04-24 05:50:21 -04:00
2021-05-03 14:15:06 -04:00
@asma-comment-end
#02 asma-STATE-CLEAR
JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-macro-define
2021-05-11 14:12:07 -04:00
;asma/pass LDA ,&ignore-macro JCN
2021-04-11 04:40:26 -04:00
2021-05-11 14:12:07 -04:00
;asma-trees/macros ;asma-traverse-tree JSR2 ,&not-exist JCN
2021-05-03 14:15:06 -04:00
POP2
;asma-msg-macro ;asma/error STA2
JMP2r
2021-04-24 05:50:21 -04:00
2021-10-06 01:42:19 -04:00
&not-exist ( incoming-ptr* )
2021-05-03 14:15:06 -04:00
( define macro by creating new node )
2021-10-06 01:42:19 -04:00
;heap LDA2 SWP2 STA2
#0000 ;append-heap-short JSR2 ( less-than pointer )
#0000 ;append-heap-short JSR2 ( greater-than pointer )
;asma/token LDA2 ;append-heap-string JSR2 ( key )
2021-05-03 14:15:06 -04:00
#04 asma-STATE-SET
JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
&ignore-macro
2021-10-06 01:14:18 -04:00
#14 asma-STATE-SET
2021-05-03 14:15:06 -04:00
JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-macro-body
2021-10-06 01:14:18 -04:00
;asma/state LDA #10 AND ,&skip JCN
2021-10-06 01:42:19 -04:00
;asma/token LDA2 ;append-heap-string JSR2
2021-05-15 13:08:08 -04:00
&skip
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
@asma-macro-end
2021-10-06 01:42:19 -04:00
#00 ;append-heap-byte JSR2
2021-10-06 01:14:18 -04:00
#14 asma-STATE-CLEAR
2021-05-03 14:15:06 -04:00
JMP2r
2021-04-24 05:50:21 -04:00
2021-05-03 14:15:06 -04:00
@asma-label-define
;asma-trees/labels ,asma-label-helper JSR
2021-05-11 14:12:07 -04:00
,&already-existed JCN
2021-04-11 04:40:26 -04:00
2021-10-06 01:42:19 -04:00
#0000 ;append-heap-short JSR2 ( data2: subtree incoming ptr )
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
&already-existed
#0002 ADD2 ;asma-trees/scope STA2
JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-sublabel-define
;asma-trees/scope LDA2 ,asma-label-helper JSR
POP POP2
JMP2r
2021-04-11 04:40:26 -04:00
2021-10-20 12:35:06 -04:00
@asma-label-helper ( incoming-ptr* -- binary-ptr* 01 if label existed already
OR binary-ptr* 00 if label was created )
2021-05-03 14:15:06 -04:00
;asma-traverse-tree JSR2
2021-05-11 14:12:07 -04:00
,&new-label JCN
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
( label already exists )
LDA2k ;asma/addr LDA2 EQU2 ,&address-match JCN
;asma-msg-redefined ;asma/error STA2
&address-match
2021-05-03 14:15:06 -04:00
#01 JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
&new-label ( incoming-ptr* )
( define label by creating new node )
2021-10-06 01:42:19 -04:00
;heap LDA2 SWP2 STA2
#0000 ;append-heap-short JSR2 ( less-than pointer )
#0000 ;append-heap-short JSR2 ( greater-than pointer )
;asma/token LDA2 ;append-heap-string JSR2 ( key )
2021-04-11 04:40:26 -04:00
2021-10-06 01:42:19 -04:00
;heap LDA2
2021-04-24 05:50:21 -04:00
2021-10-06 01:42:19 -04:00
;asma/addr LDA2 ;append-heap-short JSR2 ( data1: address )
2021-05-03 14:15:06 -04:00
#00 JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-pad-absolute
#0000 ,asma-pad-helper JMP
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-pad-relative
;asma/addr LDA2
( fall through )
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-pad-helper ( offset* -- )
#00 ;asma-parse-hex-string JSR2
2021-05-11 14:12:07 -04:00
,&valid JCN
2021-04-11 04:40:26 -04:00
2021-05-14 03:09:55 -04:00
;asma-msg-hex ;asma/error STA2
2021-10-06 01:14:18 -04:00
POP2
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
&valid
ADD2 ;asma/addr STA2
2021-04-11 18:45:31 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
@asma-raw-char
;asma/token LDA2 LDA
;asma-write-byte JMP2 ( tail call )
2021-04-11 18:45:31 -04:00
2021-05-03 14:15:06 -04:00
@asma-raw-word
;asma/token LDA2
2021-04-11 18:45:31 -04:00
2021-04-24 05:50:21 -04:00
&loop
2021-05-13 17:51:36 -04:00
LDAk
2021-05-11 14:12:07 -04:00
DUP ,&not-end JCN
2021-05-03 14:15:06 -04:00
POP POP2
2021-04-11 18:45:31 -04:00
JMP2r
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
&not-end
;asma-write-byte JSR2
2021-08-26 18:27:18 -04:00
INC2
2021-05-03 14:15:06 -04:00
,&loop JMP
@asma-literal-abs-addr
LIT LIT2 ;asma-write-byte JSR2
( fall through )
2021-04-24 05:50:21 -04:00
2021-05-03 14:15:06 -04:00
@asma-abs-addr
,asma-addr-helper JSR
;asma-write-short JMP2 ( tail call )
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
@asma-literal-zero-addr
LIT LIT ;asma-write-byte JSR2
,asma-addr-helper JSR
;asma-write-byte JSR2
2021-04-11 04:40:26 -04:00
2021-05-11 14:12:07 -04:00
,&not-zero-page JCN
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
&not-zero-page
;asma/pass LDA #00 EQU
;asma/error LDA2 ORA
ORA ,&ignore-error JCN
2021-05-03 14:15:06 -04:00
;asma-msg-zero-page ;asma/error STA2
&ignore-error
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
@asma-literal-rel-addr
LIT LIT ;asma-write-byte JSR2
,asma-addr-helper JSR ;asma/addr LDA2 SUB2 #0002 SUB2
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
DUP2 #0080 LTH2 STH
2021-05-11 14:12:07 -04:00
DUP2 #ff7f GTH2 STHr ORA ,&in-bounds JCN
2021-04-11 04:40:26 -04:00
POP2
2021-05-03 14:15:06 -04:00
;asma-msg-relative ;asma/error STA2
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
&in-bounds
;asma-write-byte JSR2
POP
2021-04-11 04:40:26 -04:00
JMP2r
2021-05-03 14:15:06 -04:00
@asma-addr-helper ( -- addr* )
2021-05-13 17:51:36 -04:00
;asma/token LDA2 LDAk #26 NEQ ,&not-local JCN
2021-08-26 18:27:18 -04:00
INC2 ;asma/token STA2
;asma-trees/scope LDA2
2021-05-03 14:15:06 -04:00
,&final-lookup JMP
&not-local ( token* )
2021-05-13 17:51:36 -04:00
LDAk
2021-05-11 14:12:07 -04:00
DUP ,&not-end JCN
2021-05-03 14:15:06 -04:00
POP POP2
;asma-trees/labels
2021-05-03 14:15:06 -04:00
,&final-lookup JMP
&not-end ( token* char )
2021-05-11 14:12:07 -04:00
#2f EQU ,&found-slash JCN
2021-08-26 18:27:18 -04:00
INC2
2021-05-03 14:15:06 -04:00
,&not-local JMP
&found-slash ( token* )
DUP2 #00 ROT ROT STA
;asma-trees/labels ;asma-traverse-tree JSR2 STH
SWP2 DUP2 #2f ROT ROT STA
STHr ,&not-found2 JCN
2021-05-03 14:15:06 -04:00
( token* binary-ptr* )
2021-08-26 18:27:18 -04:00
INC2 ;asma/token STA2
#0002 ADD2
2021-04-11 04:40:26 -04:00
2021-05-03 14:15:06 -04:00
&final-lookup ( addr-offset* incoming-ptr* )
;asma-traverse-tree JSR2
,&not-found JCN
LDA2
2021-04-11 04:40:26 -04:00
JMP2r
&not-found2 ( dummy* dummy* )
POP2
&not-found ( dummy* )
POP2
2021-05-03 14:15:06 -04:00
2021-05-11 14:12:07 -04:00
;asma/pass LDA #00 EQU ,&ignore-error JCN
2021-05-03 14:15:06 -04:00
;asma-msg-label ;asma/error STA2
&ignore-error
;asma/addr LDA2
2021-04-11 04:40:26 -04:00
JMP2r
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
@asma-literal-hex
#01 ;asma-parse-hex-string JSR2 JMP
2021-05-03 14:15:06 -04:00
( hex invalid ) ,&invalid JMP
( hex byte ) ,asma-byte-helper JMP
( hex short ) ,asma-short-helper JMP
2021-03-31 18:55:02 -04:00
2021-05-03 14:15:06 -04:00
&invalid
;asma-msg-hex ;asma/error STA2
JMP2r
@asma-byte-helper ( dummy value -- )
LIT LIT ;asma-write-byte JSR2
&raw
;asma-write-byte JSR2
2021-04-12 16:01:36 -04:00
POP
JMP2r
2021-05-03 14:15:06 -04:00
@asma-short-helper ( value* -- )
LIT LIT2 ;asma-write-byte JSR2
&raw
;asma-write-short JMP2 ( tail call )
@asma-normal-body
2021-05-11 14:12:07 -04:00
;asma-parse-opcode JSR2 ,&not-opcode JCN
2021-05-03 14:15:06 -04:00
;asma-write-byte JMP2 ( tail call )
2021-04-24 05:50:21 -04:00
&not-opcode
#01 ;asma-parse-hex-string JSR2 JMP
2021-05-03 14:15:06 -04:00
( hex invalid ) ,&not-hex JMP
( hex byte ) ,asma-byte-helper/raw JMP
( hex short ) ,asma-short-helper/raw JMP
&not-hex
.System/rst DEI #e0 GTH ,&too-deep JCN
;asma-trees/macros ;asma-traverse-tree JSR2 ,&not-macro JCN
2021-05-03 14:15:06 -04:00
&macro-loop
2021-05-13 17:51:36 -04:00
LDAk ,&keep-going JCN
2021-04-12 16:01:36 -04:00
POP2
2021-05-03 14:15:06 -04:00
JMP2r
&keep-going
2021-10-06 01:54:03 -04:00
DUP2k ;strlen JSR2 INC2 ADD2
SWP2 ;asma-assemble-token JSR2 asma-IF-ERROR ,&macro-error JCN
2021-05-03 14:15:06 -04:00
,&macro-loop JMP
2021-04-12 16:01:36 -04:00
&macro-error
POP2
JMP2r
2021-04-24 05:50:21 -04:00
&not-macro
2021-10-06 01:14:18 -04:00
POP2
;&include-string ;asma/token LDA2
;strcmp JSR2 NIP2 NIP2 NIP ,&not-include JCN
2021-10-06 01:14:18 -04:00
#08 asma-STATE-SET
JMP2r
&not-include
;asma-msg-token ;asma/error STA2
JMP2r
2021-03-31 18:55:02 -04:00
&too-deep
2021-10-06 01:14:18 -04:00
;asma-msg-too-deep ;asma/error STA2
JMP2r
&include-string "include 00
@asma-include-filename
#08 asma-STATE-CLEAR
2021-10-06 01:42:19 -04:00
;heap LDA2
;asma/token LDA2 ;append-heap-string JSR2
2021-10-06 01:14:18 -04:00
;asma-assemble-file-pass JSR2
;asma/break LDAk INC ROT ROT STA
2021-05-03 14:15:06 -04:00
JMP2r
2021-05-15 13:08:08 -04:00
( Error messages )
2021-05-03 14:15:06 -04:00
@asma-msg-hex "Invalid 20 "hexadecimal 00
@asma-msg-zero-page "Address 20 "not 20 "in 20 "zero 20 "page 00
@asma-msg-relative "Address 20 "outside 20 "range 00
@asma-msg-label "Label 20 "not 20 "found 00
@asma-msg-token "Unrecognised 20 "token 00
2021-05-03 14:15:06 -04:00
@asma-msg-macro "Macro 20 "already 20 "exists 00
@asma-msg-rewound "Memory 20 "overwrite 00
@asma-msg-too-deep "Recursion 20 "level 20 "too 20 "deep 00
@asma-msg-redefined "Label 20 "redefined 00
2021-05-03 14:15:06 -04:00
( trees )
( --- 8< ------- 8< --- cut here --- 8< ------- 8< --- )
( automatically generated code below )
( see etc/asma.moon for instructions )
2021-05-15 13:08:08 -04:00
( label less greater key binary
than than string data )
2021-05-03 14:15:06 -04:00
@asma-first-char-comment
&_entry $2 $2 ') 00 :asma-comment-end
@asma-first-char-macro
&28 $2 $2 '( 00 :asma-comment-start
&29 :&28 $2 ') 00 :asma-comment-end
&_entry :&29 :&7d '{ 00 :asma-ignore
&7d $2 $2 '} 00 :asma-macro-end
@asma-first-char-normal
&22 $2 $2 '" 00 :asma-raw-word
&23 :&22 $2 '# 00 :asma-literal-hex
&24 :&23 :&25 '$ 00 :asma-pad-relative
&25 $2 $2 '% 00 :asma-macro-define
&26 :&24 :&29 26 00 ( & ) :asma-sublabel-define
&27 $2 $2 '' 00 :asma-raw-char
&28 :&27 $2 '( 00 :asma-comment-start
&29 :&28 :&2c ') 00 :asma-comment-end
&2c $2 $2 ', 00 :asma-literal-rel-addr
&_entry :&26 :&5d '. 00 :asma-literal-zero-addr
&3a $2 $2 ': 00 :asma-abs-addr
&3b :&3a $2 '; 00 :asma-literal-abs-addr
&40 :&3b :&5b '@ 00 :asma-label-define
&5b $2 $2 '[ 00 :asma-ignore
&5d :&40 :&7c '] 00 :asma-ignore
&7b $2 $2 '{ 00 :asma-ignore
&7c :&7b :&7d '| 00 :asma-pad-absolute
&7d $2 $2 '} 00 :asma-ignore
@asma-opcodes
2021-08-18 02:33:53 -04:00
&_entry :&GTH :&ROT &_disasm "LIT 00
&INC $2 $2 "INC 00
2021-05-12 18:15:11 -04:00
&POP $2 $2 "POP 00
2021-08-18 02:33:53 -04:00
&DUP $2 $2 "DUP 00
2021-08-15 16:34:33 -04:00
&NIP :&MUL :&OVR "NIP 00
2021-05-03 14:15:06 -04:00
&SWP $2 $2 "SWP 00
2021-05-12 18:15:11 -04:00
&OVR :&ORA :&POP "OVR 00
2021-08-15 16:22:01 -04:00
&ROT :&NIP :&STR "ROT 00
2021-08-18 02:33:53 -04:00
&EQU $2 $2 "EQU 00
2021-05-12 18:15:11 -04:00
&NEQ $2 $2 "NEQ 00
2021-08-18 02:33:53 -04:00
&GTH :&DIV :&JSR "GTH 00
2021-05-12 18:15:11 -04:00
&LTH $2 $2 "LTH 00
&JMP $2 $2 "JMP 00
2021-08-18 02:33:53 -04:00
&JCN :&INC :&JMP "JCN 00
2021-05-12 18:15:11 -04:00
&JSR :&JCN :&LDR "JSR 00
&STH $2 $2 "STH 00
&LDZ $2 $2 "LDZ 00
2021-05-11 14:14:52 -04:00
&STZ $2 $2 "STZ 00
2021-05-12 18:15:11 -04:00
&LDR :&LDA :&LDZ "LDR 00
&STR :&STA :&SUB "STR 00
2021-05-03 14:15:06 -04:00
&LDA $2 $2 "LDA 00
2021-05-12 18:15:11 -04:00
&STA :&SFT :&STH "STA 00
2021-08-18 02:33:53 -04:00
&DEI :&AND :&DEO "DEI 00
&DEO $2 $2 "DEO 00
2021-05-03 14:15:06 -04:00
&ADD $2 $2 "ADD 00
2021-05-12 18:15:11 -04:00
&SUB :&STZ :&SWP "SUB 00
&MUL :&LTH :&NEQ "MUL 00
2021-08-18 02:33:53 -04:00
&DIV :&DEI :&EOR "DIV 00
2021-05-03 14:15:06 -04:00
&AND :&ADD $2 "AND 00
2021-05-12 18:15:11 -04:00
&ORA $2 $2 "ORA 00
2021-08-18 02:33:53 -04:00
&EOR :&DUP :&EQU "EOR 00
2021-05-12 18:15:11 -04:00
&SFT $2 $2 "SFT 00
2021-05-03 14:15:06 -04:00