From 887802efcdb3b56263069cc6778a8f53ed89d599 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Mon, 22 Jun 2020 17:56:52 -0400 Subject: Did some more stuff. - Fixed some bugs in the emulator's assembler. - Worked on SuBAsm's lexer some more. - Created a new directory for the SuB suite, and moved all of the SuB suite's files in there. --- programs/sub-suite/subasm.s | 388 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 programs/sub-suite/subasm.s (limited to 'programs/sub-suite/subasm.s') 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 + +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: -- cgit v1.2.3-13-gbd6f