summaryrefslogtreecommitdiff
path: root/programs/subasm.s
blob: 4cec21974cb9d5e651ac76680331bce81301e055 (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
; SuBAsm
; The Sux Bootstrapped Assembler.
;
; by mr b0nk 500 <b0nk@b0nk.xyz>

MAX_SYM = $800		; Max symbol size.

.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 utility subroutines.
util_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

; Lexeme string.
lexeme:

; Symbol tables.
.org lexeme+$100
sym_val:
.org sym_val+$4000
sym_id:
.org sym_id+$1000
sym_def:
.org sym_def+$100
sym_name:

; Fixup table.
; Fixups are unresolved symbols.
.org sym_name+$1000
fix_sym:
.org fix_sym+$1000
fix_ln:
.org fix_ln+$1000
fix_val:


; 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 parse_cmd	; Yes, so skip everything else.
	jmp @end	;
	jsr chk_cmd	; No, but did we get a full command?
	bne parse_cmd	; Yes, so skip everything else.
	jsr lexer	; No, so start lexing this line.
@end:
subasm_end:
	rts		; End of subasm.

parse_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 subasm_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.
	jmp subasm_end	; We are done.

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.
@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.


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.
utils: