summaryrefslogtreecommitdiff
path: root/programs/sub-suite/subasm.s
diff options
context:
space:
mode:
Diffstat (limited to 'programs/sub-suite/subasm.s')
-rw-r--r--programs/sub-suite/subasm.s388
1 files changed, 388 insertions, 0 deletions
diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s
new file mode 100644
index 0000000..9c6c3f0
--- /dev/null
+++ b/programs/sub-suite/subasm.s
@@ -0,0 +1,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: