summaryrefslogtreecommitdiff
path: root/programs/sub-suite/subasm.s
blob: 9c6c3f0f3d717dd71ca6849e321c0baad6d380c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
; SuBAsm
; The Sux Bootstrapped Assembler.
;
; by mr b0nk 500 <b0nk@b0nk.xyz>

MAX_SYM = $800		; Max symbol size.
OPNUM	= 88		; Instruction count.

.include "lexer.s"
.include "utils.s"

.org incl
; String Constants.
asm_name:
	.byte "SuBAsm"
asm_ver:
	.byte "0.1"

; Directives.
dir:
	.byte "org"
	.byte "byte"
	.byte "word"
	.byte "dword"
	.byte "qword"
	.byte "include"

; Short form Commands.
sh_cmds:
	.byte "vlahirs"

; Commands.
cmds:
	.byte "viewmem"
	.byte "list"
	.byte "asm"
	.byte "help"
	.byte "inst"
	.byte "run"
	.byte "set"

; Instruction mnemonics, and opcodes.

; Legend.
; mne = Mnemonic.
; imm = Immediate data.
; zm  = Zero Matrix.
; zmx = Zero Matrix, indexed with X.
; zmy = Zero Matrix, indexed with Y.
; ind = Indirect.
; idx = Indexed Indirect.
; idy = Indirect Indexed.
; abs = Absolute.
; imp = Implied.

mne:
;	       mne   imm,  zm, zmx, zmy, ind, idx, idy, abs, imp
	.byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00
	.byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF
	.byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02
	.byte "PHP", $08, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "CPB", $09, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF
	.byte "PHB", $0A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $E5
	.byte "JMP", $FF, $0E, $FF, $FF, $CE, $FF, $FF, $10, $FF
	.byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF
	.byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12
	.byte "ENT", $18, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "CPY", $19, $3D, $FF, $FF, $85, $FF, $FF, $4C, $FF
	.byte "PLB", $1A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $F5
	.byte "JSR", $FF, $1E, $FF, $FF, $BE, $FF, $FF, $20, $FF
	.byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF
	.byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22
	.byte "PLP", $28, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "CPX", $29, $4D, $FF, $FF, $B5, $FF, $FF, $3C, $FF
	.byte "PHY", $2A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "BPO", $FF, $2E, $FF, $FF, $FF, $FF, $FF, $30, $FF
	.byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF
	.byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32
	.byte "STT", $38, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "PLY", $3A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "BNG", $FF, $3E, $FF, $FF, $FF, $FF, $FF, $40, $FF
	.byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF
	.byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42
	.byte "PHA", $48, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "PHX", $4A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "BCS", $FF, $4E, $FF, $FF, $FF, $FF, $FF, $50, $FF
	.byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF
	.byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52
	.byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58
	.byte "PLX", $5A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "BCC", $FF, $5E, $FF, $FF, $FF, $FF, $FF, $60, $FF
	.byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF
	.byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62
	.byte "PLA", $68, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A
	.byte "BEQ", $FF, $6E, $FF, $FF, $FF, $FF, $FF, $70, $FF
	.byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF
	.byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72
	.byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $78
	.byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A
	.byte "BNE", $FF, $7E, $FF, $FF, $FF, $FF, $FF, $80, $FF
	.byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF
	.byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82
	.byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $88
	.byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A
	.byte "BVS", $FF, $8E, $FF, $FF, $FF, $FF, $FF, $90, $FF
	.byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF
	.byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92
	.byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $98
	.byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A
	.byte "BVC", $FF, $9E, $FF, $FF, $FF, $FF, $FF, $A0, $FF
	.byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF
	.byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2
	.byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A8
	.byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA
	.byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AE
	.byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF
	.byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2
	.byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B8
	.byte "LDX", $B9, $BD, $FF, $C9, $95, $FF, $FF, $BC, $FF
	.byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA
	.byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0
	.byte "LDA", $C1, $C6, $79, $39, $05, $5D, $5C, $C4, $FF
	.byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C5
	.byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C8
	.byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA
	.byte "STA", $FF, $CD, $89, $49, $15, $6D, $6C, $CC, $FF
	.byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0
	.byte "LDB", $D1, $D6, $99, $59, $35, $8D, $8C, $D4, $FF
	.byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D5
	.byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D8
	.byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA
	.byte "STB", $FF, $DD, $A9, $69, $45, $9D, $9C, $DC, $FF
	.byte "TXS", $E0, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
	.byte "LDY", $E1, $E6, $E9, $FF, $65, $FF, $FF, $E4, $FF
	.byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E8
	.byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA
	.byte "STY", $FF, $ED, $F9, $FF, $75, $FF, $FF, $EC, $FF
	.byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EE
	.byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF
	.byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2
	.byte "STX", $FF, $FD, $FF, $D9, $A5, $FF, $FF, $FC, $FF
	.byte "INB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FE

; Command subroutine table.
cmd_srt:
	.word viewmem
	.word list
	.word asm
	.word help
	.word inst
	.word run
	.word set

; Data entry point for the lexer.
lexer_data:


; Token table.
.org $20000
tokline:

.org cmd_buf+$400
; Program Counter.
prg_cnt:
	.qword 0
; Hex digit string buffer.
hex_str:
	.qword 0, 0
; String buffer.
strbuf:

.org strbuf+$80
; Subroutine pointer.
sub_ptr:
	.word 0

; Indecies.
idx0:
	.qword 0
idx1:
	.qword 0
idx2:
	.qword 0
idx3:
	.qword 0

; Current token line.
ctok:
	.word 0

; Last token line.
ltok:
	.word 0

; Lexeme type.
lex_type:
	.byte 0

; Lexeme string.
lexeme:

; Symbol table.
.org lexeme+$100
sym:

; Fixup table.
; Fixups are unresolved symbols.
.org sym+$8000
fix:


; Start of program code.
.org parser
subasm:
	ldb #0		; Set the first pointer
	lda.d #cmd_buf	; to the command buffer.
	jsr set_ptr	;
	tba		; Reset A.
	tax		; Reset X.
	jsr chk_shcmd	; Did we get a shortend command?
	bne @cmd	; Yes, so skip everything else.
	jsr chk_cmd	; No, but did we get a full command?
	bne @cmd	; Yes, so skip everything else.
	jsr lex		; No, so start lexing this line.
	jmp @end	; We are done.
@cmd:
	ldb #1		; Set the second pointer
	lda.d #cmd_srt	; to the command subroutine table.
	jsr set_ptr	;
	deb		; Reset B.
	tba		; Reset A.
	lda f		; Get the command ID.
	cmp #8		; Is the command ID greater than the command count?
	bcs @end	; Yes, so we're done.
	lsl #1		; No, so multiply the command ID by two.
	phy #2		; Preserve the screen buffer position.
	tay		; Set the index to the offset that we just calculated.
	lda.w (ptr2), y	; Get the command subroutine, from the command subroutine table.
	ply #2		; Get back the screen buffer position.
	ldb #2		; Save it in the third pointer.
	jsr set_ptr	;
	ldb #0		; Reset B.
	jsr (ptr3)	; Run the command's subroutine.
@end:
	rts		; End of subasm.

chk_shcmd:
	tba		; Reset A.
	inb		; Set the second pointer
	lda.w #sh_cmds	; to the shortend command table.
	jsr set_ptr	;
	deb		; Reset B.
	tba		; Reset A.
	phy #2		; Preserve the screen buffer position.
	txy		; Set our index to zero.
	lda (ptr), y	; Is there nothing in the command buffer?
	beq @false	; Yes, so return that we failed.
	cmp #' '	; No, but is this character, a space?
	beq @false	; Yes, so return that we failed.
	jsr tolower	; No, so convert it to lowercase.
@loop:
	ldb (ptr2), y	; Are we at the end of the table?
	beq @false	; Yes, so return that we failed.
	cab		; No, so did the character match?
	beq @found	; Yes, so check if there are any arguments.
	iny		; No, so check the next command.
	jmp @loop	; Keep looping.
@found:
	sty f		; Save the command ID.
	ldy #1		; Check the next character in the command buffer.
	lda (ptr), y	; Is this the end of the buffer?
	beq @true	; Yes, so return that we succeded.
	cmp #' '	; No, but is this a space?
	beq @true	; Yes, so return that we succeded.
	jmp @false	; No, so return that we failed.
@true:
	lda #1		; Return true.
	jmp @end	; We are done.
@false:
	ldb #0		; Reset B.
	tba		; Return false.
	tax		; Reset X.
@end:
	ply #2		; Get back the screen buffer position.
	rts		; End of chk_shcmd.


chk_cmd:
	tba		; Reset A.
	tax		; Reset X.
	sta.q idx0	; Reset the first index.
	sta.q idx1	; Reset the second index.
@loop:
	lda.w #cmds	; Get pointer to the start of the command table.
	clc		; Prepare for a non carrying add.
	adc.w idx0	; Offset the pointer, by the length of the previous string.
	pha #8		; Preserve the command string pointer.
	jsr strcasecmp	; Is the command buffer, the same as the command string?
	pla #8		; Get the command string pointer back.
	beq @true	; Yes, so return true.
	ldb idx1	; No, so Get the command ID.
	cpb #7		; Have we reached the end of the command table?
	beq @false	; Yes, so return false.
	inc idx1	; No, so increment the command ID.
@getlen:
	jsr strlen	; Get the string's length.
	inx		; Add one to the length.
	txa		; Place it in the accumulator.
	clc		; Prepare for a non carrying add.
	adc.w idx0	; Add the string offset to the current length
	sta.w idx0	; Save the offset in the first index.
	jmp @loop	; Keep looping.
@true:
	ldb idx1	; Get the command ID.
	stb f		; Return the command ID.
	ldb #1		; Return true.
	jmp @end	; We are done.
@false:
	ldb #0		; Return false.
@end:
	rts		; End of chk_cmd.

viewmem:
	lda.q prg_cnt	; Get the program counter.
	sta.q idx0	; Save the address in the first index.
	and #$F0	; Clear the first four bits of the address.
	sta idx0	; Overwrite the first byte, with the masked byte.
	lda #19		; Move the cursor to the right, by 19 columns.
	sta scr_col	;
	jsr update_pos	;
	jsr print_lo	; Print the low nibble offsets.
	ldx #0		; Reset X.
	ldb #0		; Reset B.
	stb idx1	; Reset the byte count.
@loop:
	lda #'\n'	; Print a newline.
	jsr print_char	;
	jsr print_hi	; Place the address in the string buffer.
	jsr print_chunk	; Place the next 16 bytes in the string buffer.
	lda.d #strbuf	; Print the string buffer.
	jsr print_str	;
	inc idx1	; Increment the chunk count.
	ldb idx1	; Get the chunk count.
	cpb #$10	; Did we print 16 chunks?
	beq @end	; Yes, so we're done.
	lda.q idx0	; No, so get the address index.
	clc		; Prepare for a non carrying add.
	adc #$10	; Add 16 to the address.
	sta.q idx0	; Put it back into the address.
	and #0		; Reset A.
	jmp @loop	; Keep looping.
@end:
	lda #'\n'	; Print a newline.
	jsr print_char	;
	and #0		; Reset A.
	rts		; End of viewmem.


list:
	nop		;
@end:
	rts		; End of list.
asm:
	nop		;
@end:
	rts		; End of asm.
help:
	nop		;
@end:
	rts		; End of help.
inst:
	nop		;
@end:
	rts		; End of inst.
run:
	nop		;
@end:
	rts		; End of run.
set:
	nop		;
@end:
	rts		; End of set.

; Entry point for utility subroutines.
lexer: