diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-17 20:37:44 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-17 20:37:44 -0400 |
commit | d31aed21b27fbda68abe088d657ba18455607cc4 (patch) | |
tree | 484f16e64f1fa4bcbdad7eb3242ec95e3ca9f5be | |
parent | 7e57608dff1e768d2ee5d6b6a28a319865530ed0 (diff) |
- Fixed some bugs in the emulator's assembler.
- Simplified the effective address functions.
- Made SuBEditor a bit faster.
- JSR, and RTS now support using the RS prefix, which
is used to specify the return address size, with an
RS prefix of 0 being a return address size of 64
bits, rather than 8 bits.
-rw-r--r-- | asmmon.h | 2 | ||||
-rw-r--r-- | assemble.c | 28 | ||||
-rw-r--r-- | disasm.c | 24 | ||||
-rw-r--r-- | lexer.c | 16 | ||||
-rw-r--r-- | opcode.h | 1 | ||||
-rw-r--r-- | programs/sub-suite/declare.s | 238 | ||||
-rw-r--r-- | programs/sub-suite/lexer.s | 24 | ||||
-rw-r--r-- | programs/sub-suite/subeditor.s | 26 | ||||
-rw-r--r-- | sux.c | 15 | ||||
-rw-r--r-- | sux.h | 129 | ||||
-rw-r--r-- | test/bit-or.s | 317 | ||||
-rw-r--r-- | test/fib2.s | 2 | ||||
-rw-r--r-- | test/popcnt2.s | 4 | ||||
-rw-r--r-- | test/reg-transfer.s | 3 | ||||
-rw-r--r-- | test/subroutine.s | 13 |
15 files changed, 638 insertions, 204 deletions
@@ -543,6 +543,8 @@ extern uint8_t isfixup; extern line *find_line(uint32_t ln, uint8_t dbg); extern uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg); +extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg); +extern token *skip_expr(token *t, uint8_t dbg); extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg); extern token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t value, char *str, symbol *s); extern void assemble(line *ln, bytecount *bc, uint8_t dbg); @@ -103,10 +103,32 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { case EXPR_NONE : value = tmp_val; break; } isstart = 0; + if (dbg) { + printf("get_val(): Value: $%"PRIX64", Expression type: $%X, Expression Value: $%"PRIX64".\n", value, type, tmp_val); + } } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); return value; } +token *skip_expr(token *t, uint8_t dbg) { + /*if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) { + }*/ + do { + t = (t->id == TOK_EXPR) ? t->next : t; + switch (t->id) { + case TOK_HEX : + case TOK_DEC : + case TOK_BIN : + case TOK_CHAR : + case TOK_SYM : + case TOK_LABEL: t = t->next; break; + } + } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); + return t; +} + + + uint8_t get_directivesize(uint8_t type, uint8_t dbg) { switch (type) { case DIR_QWORD: return 3; @@ -163,6 +185,9 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre bc->datasize += tmp; break; } + if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) { + t = skip_expr(t, dbg); + } break; case TOK_STRING: if (type == DIR_BYTE) { @@ -196,6 +221,9 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre } break; } + if (t == NULL) { + break; + } } return tmpaddr; } @@ -3,7 +3,7 @@ #include <string.h> void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread) { - union reg value; + uint64_t value; uint64_t address = get_addr(cpu, opcode, prefix, 0, 0, thread); uint8_t rs = (prefix >> 4) & 3; char *postfix; @@ -58,29 +58,29 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint value = read_value(cpu, cpu->pc, addrsize, 0, 0); if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || optype[opcode] == REL) { switch (addrsize) { - case 0 : sign = ((int8_t )value.u8 [0] < 0) ? "-" : "+"; break; - case 1 : sign = ((int16_t)value.u16[0] < 0) ? "-" : "+"; break; + case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break; + case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break; case 2 : - case 3 : sign = ((int32_t)value.u32[0] < 0) ? "-" : "+"; break; + case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break; case 4 : case 5 : case 6 : - case 7 : sign = ((int64_t)value.u64 < 0) ? "-" : "+"; break; + case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break; } - value.u64 &= mask.u64; + value &= mask.u64; } switch (optype[opcode]) { case BREG: case IMPL: wprintw(scr, "%s%s" , opname[opcode], postfix); break; - case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value.u64); break; + case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break; case IND : case INDX: case INDY: ind = "("; /* Falls through. */ case ZMX : case ZMY : case ZM : - case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value.u64, idx); break; - case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value.u64); break; + case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value, idx); break; + case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value); break; } if (address == TX_ADDR || address == RX_ADDR) { @@ -100,18 +100,18 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint uint32_t adr; if (address == CTRL_ADDR || addr[STEP_ADDR]) { adr = 0x30000; - wprintw(scr, ", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u", addr[0], addr[1], addr[0x22], addr[0x23]); + wprintw(scr, ", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u", addr[0], addr[1], addr[2], addr[3]); wmove(scr, 32, 0); wprintw(scr, "bitabl: "); for (uint8_t i = 0; i < 16; i++) { - wprintw(scr, "%02X", addr[adr+i]); + wprintw(scr, "%s", showbits(addr[adr+i], 7, 0)); } mvwprintw(scr, ln++, 0, "buffer: "); wmove(scr, ln++, 0); uint8_t maxrow = 10; int line_offset = (addr[0]-(maxrow-1) >= 0) ? addr[0]-(maxrow-1) : 0; for (uint8_t i = 0; i < maxrow; i++) { - line_idx = (i+addr[0x22]+line_offset << 6) + (i+addr[0x22]+line_offset << 4); + line_idx = (i+addr[2]+line_offset << 6) + (i+addr[2]+line_offset << 4); for (uint8_t j = 0; j < 0x50; j++) { wprintw(scr, "%02X", addr[tmpad+j+line_idx]); if ((addr[0] == i+line_offset) && addr[1] == j) { @@ -653,6 +653,22 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { } if (i) { l->tok = tokens; + token *tok = tokens; + if (tok->id == TOK_SYM && tok->next) { + symbol *s = tok->sym; + for (; tok; tok = tok->next) { + switch (tok->id) { + case TOK_HEX : + case TOK_BIN : + case TOK_DEC : + case TOK_CHAR: + case TOK_EXPR: + s->val = get_val(tok, address, 3, dbg); + tok = skip_expr(tok, dbg); + break; + } + } + } tokens = NULL; last_tok = NULL; bytecount dummy; @@ -18,6 +18,7 @@ #define N (1 << 7) /* Negative flag. */ extern uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode); +extern char *showbits(uint64_t value, uint8_t bitnum, uint8_t dbg); /* reg_expr, and val_expr are the arithmetic expressions * that will be used for either the value, or register, such as '+', or '-'. diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s index 8054956..55ccc2b 100644 --- a/programs/sub-suite/declare.s +++ b/programs/sub-suite/declare.s @@ -113,9 +113,9 @@ scr_row: .res 1 scr_col: .res 1 -scr_trow: +scr_str: .res 1 -scr_tcol: +scr_end: .res 1 scr_ptr: .res 2 @@ -148,9 +148,9 @@ end: .res 8 bitmask: .res 1 -scr_str: +scr_trow: .res 1 -scr_end: +scr_tcol: .res 1 wrapped: .res 1 @@ -287,311 +287,387 @@ bits: .byte $80, $40, $20, $10, $08, $04, $02, $01 -; Instruction mnemonics, and opcodes. +; Instruction table. ; Format. ; -; String : Mnemonic. ; 2 bytes: Addressing mode bits. ; 1 byte : Base value, used to generate the actual opcode. -mne: - .byte "ADC" +inst: + ; ADC .word IMM|ZM|ABS|BREG .byte $01 - .byte "AND" + ; AND .word IMM|ZM|ABS|BREG .byte $41 - .byte "ASR" + ; ASR .word IMM|ZM|ABS|BREG .byte $62 - .byte "BCC" + ; BCC .word REL .byte $A0 - .byte "BCS" + ; BCS .word REL .byte $90 - .byte "BEQ" + ; BEQ .word REL .byte $B0 - .byte "BNE" + ; BNE .word REL .byte $C0 - .byte "BNG" + ; BNG .word REL .byte $80 - .byte "BPO" + ; BPO .word REL .byte $70 - .byte "BRA" + ; BRA .word REL .byte $F0 - .byte "BRK" + ; BRK .word IMPL .byte $69 - .byte "BVC" + ; BVC .word REL .byte $E0 - .byte "BVS" + ; BVS .word REL .byte $D0 - .byte "CLC" + ; CLC .word IMPL .byte $09 - .byte "CLI" + ; CLI .word IMPL .byte $29 - .byte "CLV" + ; CLV .word IMPL .byte $49 - .byte "CMP" + ; CMP .word IMM|ZM|IND|INDY|ABS|BREG|INDX2 .byte $82 - .byte "CPB" + ; CPB .word IMM|ZM|IND|INDY|ABS|INDX2 .byte $04 - .byte "CPS" + ; CPS .word IMPL .byte $00 - .byte "CPX" + ; CPX .word IMM|ZM|IND|ABS .byte $24 - .byte "CPY" + ; CPY .word IMM|ZM|IND|ABS .byte $44 - .byte "DEB" + ; DEB .word IMPL .byte $99 - .byte "DEC" + ; DEC .word IMPL|ZM|ABS .byte $84 - .byte "DEX" + ; DEX .word IMPL .byte $B9 - .byte "DEY" + ; DEY .word IMPL .byte $79 - .byte "DIV" + ; DIV .word IMM|ZM|ABS|BREG .byte $42 - .byte "INB" + ; INB .word IMPL .byte $A9 - .byte "INC" + ; INC .word IMPL|ZM|ABS .byte $A4 - .byte "INX" + ; INX .word IMPL .byte $C9 - .byte "INY" + ; INY .word IMPL .byte $89 - .byte "JMP" + ; JMP .word ABS|IND|ZM2 .byte $00 - .byte "JSR" + ; JSR .word ABS|IND|ZM2 .byte $20 - .byte "LDA" + ; LDA .word IMM|ZM|ZMX|ZMY|IND|INDX|INDY|ABS .byte $C2 - .byte "LDB" + ; LDB .word IMM|ZM|ZMX|ZMY|IND|INDX|INDY|ABS .byte $E2 - .byte "LDX" + ; LDX .word IMM|ZM|IND|ABS .byte $64 - .byte "LDY" + ; LDY .word IMM|ZM|IND|ABS .byte $A2 - .byte "LSL" + ; LSL .word IMM|ZM|ABS|BREG .byte $A1 - .byte "LSR" + ; LSR .word IMM|ZM|ABS|BREG .byte $C1 - .byte "MUL" + ; MUL .word IMM|ZM|ABS|BREG .byte $22 - .byte "NOP" + ; NOP .word IMPL .byte $EA - .byte "ORA" + ; ORA .word IMM|ZM|ABS|BREG .byte $61 - .byte "PHA" + ; PHA .word IMPL .byte $8E - .byte "PHB" + ; PHB .word IMPL .byte $AE - .byte "PHP" + ; PHP .word IMPL .byte $6E - .byte "PHX" + ; PHX .word IMPL .byte $EE - .byte "PHY" + ; PHY .word IMPL .byte $CE - .byte "PLA" + ; PLA .word IMPL .byte $9E - .byte "PLB" + ; PLB .word IMPL .byte $BE - .byte "PLP" + ; PLP .word IMPL .byte $7E - .byte "PLX" + ; PLX .word IMPL .byte $FE - .byte "PLY" + ; PLY .word IMPL .byte $DE - .byte "ROL" + ; ROL .word IMM|ZM|ABS|BREG .byte $E1 - .byte "ROR" + ; ROR .word IMM|ZM|ABS|BREG .byte $02 - .byte "RTI" + ; RTI .word IMPL .byte $60 - .byte "RTS" + ; RTS .word IMPL .byte $50 - .byte "SBC" + ; SBC .word IMM|ZM|ABS|BREG .byte $21 - .byte "SEC" + ; SEC .word IMPL .byte $19 - .byte "SEI" + ; SEI .word IMPL .byte $39 - .byte "STA" + ; STA .word ZM|ZMX|ZMY|IND|INDX|INDY|ABS .byte $28 - .byte "STB" + ; STB .word ZM|ZMX|ZMY|IND|INDX|INDY|ABS .byte $48 - .byte "STX" + ; STX .word ZM|IND|ABS .byte $68 - .byte "STY" + ; STY .word ZM|IND|ABS .byte $08 - .byte "TAB" + ; TAB .word IMPL .byte $0A - .byte "TAX" + ; TAX .word IMPL .byte $4A - .byte "TAY" + ; TAY .word IMPL .byte $2A - .byte "TBA" + ; TBA .word IMPL .byte $1A - .byte "TSX" + ; TSX .word IMPL .byte $8A - .byte "TXA" + ; TXA .word IMPL .byte $5A - .byte "TXS" + ; TXS .word IMPL|IMM .byte $9A - .byte "TXY" + ; TXY .word IMPL .byte $7A - .byte "TYA" + ; TYA .word IMPL .byte $3A - .byte "TYX" + ; TYX .word IMPL .byte $6A - .byte "WAI" + ; WAI .word IMPL .byte $59 - .byte "XOR" + ; XOR .word IMM|ZM|ABS|BREG .byte $81 +; Mnemonic Table. +mne: + .byte "ADC" + .byte "AND" + .byte "ASR" + .byte "BCC" + .byte "BCS" + .byte "BEQ" + .byte "BNE" + .byte "BNG" + .byte "BPO" + .byte "BRA" + .byte "BRK" + .byte "BVC" + .byte "BVS" + .byte "CLC" + .byte "CLI" + .byte "CLV" + .byte "CMP" + .byte "CPB" + .byte "CPS" + .byte "CPX" + .byte "CPY" + .byte "DEB" + .byte "DEC" + .byte "DEX" + .byte "DEY" + .byte "DIV" + .byte "INB" + .byte "INC" + .byte "INX" + .byte "INY" + .byte "JMP" + .byte "JSR" + .byte "LDA" + .byte "LDB" + .byte "LDX" + .byte "LDY" + .byte "LSL" + .byte "LSR" + .byte "MUL" + .byte "NOP" + .byte "ORA" + .byte "PHA" + .byte "PHB" + .byte "PHP" + .byte "PHX" + .byte "PHY" + .byte "PLA" + .byte "PLB" + .byte "PLP" + .byte "PLX" + .byte "PLY" + .byte "ROL" + .byte "ROR" + .byte "RTI" + .byte "RTS" + .byte "SBC" + .byte "SEC" + .byte "SEI" + .byte "STA" + .byte "STB" + .byte "STX" + .byte "STY" + .byte "TAB" + .byte "TAX" + .byte "TAY" + .byte "TBA" + .byte "TSX" + .byte "TXA" + .byte "TXS" + .byte "TXY" + .byte "TYA" + .byte "TYX" + .byte "WAI" + .byte "XOR" + ; Command subroutine table. cmd_srt: diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s index dc5a3b0..3a856b5 100644 --- a/programs/sub-suite/lexer.s +++ b/programs/sub-suite/lexer.s @@ -119,11 +119,11 @@ ptok_dot: ldb idx1 ; Get the directive ID. cpb #7 ; Have we reached the end of the directive table? beq @end ; Yes, so we're done. - lda.w #dir ; Get pointer to the start of the directive table. + lda.w #dir ; No, so get the start of the directive table. clc ; Prepare for a non carrying add. adc.w idx2 ; Offset the pointer, by the length of the previous string. pha.q ; Preserve the directive string pointer. - jsr strcaseptr ; Is the lexeme buffer, the same as the directive string? + jsr strcaseg ; Is the lexeme buffer, the same as the directive string? pla.q ; Get the directive string pointer back. beq @found ; Yes, so create a new token. inc idx1 ; No, so increment the directive ID. @@ -156,10 +156,14 @@ ptok_min: lda #EXPR_MINUS ; Set the expresion type to EXPR_MINUS. bra ptok_expr ; Set up the token. ptok_gt: + lda #EXPR_LOW ; Set the expresion type to EXPR_LOW. bra ptok_expr ; Set up the token. ptok_lt: lda #EXPR_HIGH ; Set the expresion type to EXPR_HIGH. + bra ptok_expr ; Set up the token. +ptok_pipe: + lda #EXPR_OR ; Set the expresion type to EXPR_OR. ptok_expr: lda #TOK_EXPR ; Set the lexeme type to TOK_EXPR. sta lex_type ; @@ -254,19 +258,23 @@ ptok_alph: stb.q idx1 ; Reset the second index. jsr set_lexptr ; Set up the lexeme buffer. @isop_loop: - lda.w #mne ; Get pointer to the start of the instruction table. + ldb idx1 ; Get the instruction ID. + cpb #OPNUM-1 ; Have we reached the end of the mnemonic table? + beq @end ; Yes, so we're done. + lda.w #mne ; No, so get the start of the mnemonic table. clc ; Prepare for a non carrying add. adc.w idx2 ; Offset the pointer, by the length of the previous string. + pha.q ; Preserve the mnemonic string pointer. jsr strcaseg ; Is the lexeme buffer, the same as the mnemonic string? + pla.q ; Get the mnemonic string pointer back. beq @found ; Yes, so create a new token. - ldb idx1 ; No, so Get the instruction ID. - cpb #OPNUM-1 ; Have we reached the end of the instruction table? beq @end ; Yes, so we're done. inc idx1 ; No, so increment the instruction ID. @offset: - lda #14 ; Get the base size of the instruction table. - clc ; Prepare for a non carrying multiply. - mul idx1 ; Multiply the base offset, by the instruction ID. + jsr strlen ; Get the string's length. + inc ; Add one to the length. + clc ; Prepare for a non carrying add. + adc.w idx2 ; Add the string offset to the current length sta.w idx2 ; Save the offset in the third index. bra @isop_loop ; Keep looping. @found: diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s index 476f1cf..e624990 100644 --- a/programs/sub-suite/subeditor.s +++ b/programs/sub-suite/subeditor.s @@ -402,11 +402,12 @@ printc: @update1: jsr findend ; Find the end of the line. sta rege ; Use it for redrawing the line. - sta scr_row ; Set the row position to to the end of the line. - jsr findst ; Find the start of the line. - lda scr_row ; Get the start of the line. +; sta scr_row ; Set the row position to to the end of the line. +; jsr findst ; Find the start of the line. +; lda scr_row ; Get the start of the line. + lda scr_trow ; Get the current row position. @update2: - sta regf ; Set the starting line, to the start of the line. + sta regf ; Set the starting line, to the current row position. jsr rdrw_ln ; Redraw the line. lda scr_trow ; Get the real row position back. sta scr_row ; @@ -620,7 +621,9 @@ back: jsr update_pos ; and update it's position. rts ; We are done. @update: - lda scr_row ; Set the line to start redrawing, to the start of the line. + lda (ptr3), y ; Are we at the end of the line? + beq @shift ; Yes, so skip redrawing. + lda scr_trow ; No, so set the line to start redrawing, to the line that the cursor is on. sta regf ; inc rege ; Set the redraw flag to true. bra @shift ; Start shifting the line back. @@ -939,10 +942,21 @@ update_ptr: clc ; Clear the carry flag. lda scr_row ; Add the cursor's line number, adc scr_str ; with the starting line number to get the absolute line number. - tay ; Place it in the Y regster for now. mul #maxcol+1 ; Multiply the line number by the screen's max column count, plus 1. clc ; Clear the carry flag. adc scr_col ; Add the cursor's column number to get the screen index. +; cmp.w #$2000 ; Is the index greater than, or equal to the end of the screen buffer? +; bcc @end ; No, so we're done. +;@wrap: +; and #0 ; Reset the screen's starting line. +; sta scr_str ; +; sta regf ; Setup the starting line for rdrw_ln. +; lda #maxrow ; Reset the screen's ending line. +; sta scr_end ; +; sta rege ; Setup the ending line for rdrw_ln. +; jsr rdrw_ln ; Redraw the entire screen. +; bra update_ptr ; Get the screen index. +@end: rts ; End of update_ptr. @@ -201,7 +201,7 @@ void *run(void *args) { step = 1; } if (isrw(opcode) && am != REL) { - value = read_value(cpu, address.u64, size, 1, check_io); + value.u64 = read_value(cpu, address.u64, size, 1, check_io); } } switch(opcode) { @@ -474,7 +474,7 @@ void *run(void *args) { case JSR_IN: /* JSR Indirect. */ case JSR_AB: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ - push(cpu, cpu->pc, 7, thread); + push(cpu, cpu->pc, (size) ? size : 7, thread); cpu->pc = address.u64; break; case INC_AB: /* INC Absolute. */ @@ -484,9 +484,10 @@ void *run(void *args) { case NOP_IMP: /* No OPeration. */ break; case RTI_IMP: /* ReTurn from Interrupt routine. */ - cpu->ps.u64 = pull(cpu, 0, thread); + cpu->ps.u8[thread] = pull(cpu, 0, thread); + size = 0; case RTS_IMP: /* ReTurn from Subroutine. */ - cpu->pc = pull(cpu, 7, thread); + cpu->pc = pull(cpu, (size) ? size : 7, thread); break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ @@ -513,6 +514,10 @@ void *run(void *args) { default: break; } + /*if (cpu->pc <= 0xFF) { + step = 1; + wrefresh(scr); + }*/ #if !IO ins++; #endif @@ -534,7 +539,7 @@ void *run(void *args) { #if getclk wprintw(scr, ", Clock cycles: %"PRIu64, cpu->clk); #endif - if (step && !subdbg) { + if (step || !subdbg) { wrefresh(scr); } #if keypoll @@ -49,7 +49,7 @@ extern int get_key(WINDOW *scr); extern void io(uint64_t address, uint8_t rw); extern void init_scr(); -static inline union reg read_value(struct sux *cpu, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { +static inline uint64_t read_value(struct sux *cpu, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { union reg value; value.u64 = 0; #if (IO || debug) && !branch @@ -74,11 +74,9 @@ static inline union reg read_value(struct sux *cpu, uint64_t address, uint8_t si case 0: value.u8[0] = addr[address+0]; } #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif - return value; + return value.u64; } static inline void write_value(struct sux *cpu, union reg value, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { @@ -104,32 +102,28 @@ static inline void write_value(struct sux *cpu, union reg value, uint64_t addres #endif #endif #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif } -static inline uint64_t offset_addr(struct sux *cpu, union reg offset, uint8_t size, uint8_t inc_clk, uint8_t prefix) { +static inline uint64_t offset_addr(struct sux *cpu, uint64_t offset, uint8_t size, uint8_t inc_clk, uint8_t prefix) { uint64_t of; switch (prefix >> 6) { case 1: of = ((cpu->stk_st << 16) | cpu->sp); break; case 2: of = cpu->pc ; break; } #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif switch (size) { - case 0: return of + (int8_t )offset.u8 [0]; - case 1: return of + (int16_t)offset.u16[0]; + case 0: return of + (int8_t )offset; + case 1: return of + (int16_t)offset; case 2: - case 3: return of + (int32_t)offset.u32[0]; + case 3: return of + (int32_t)offset; case 4: case 5: case 6: - case 7: return of + (int64_t)offset.u64 ; + case 7: return of + (int64_t)offset; } } @@ -137,66 +131,49 @@ static inline uint64_t imm_addr(struct sux *cpu) { return cpu->pc; } -static inline uint64_t zm_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { - union reg address = read_value(cpu, cpu->pc, get_addrsize(prefix, ZM), inc_clk, 0); +static inline uint64_t read_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) { + uint64_t address; + uint8_t size = get_addrsize(prefix, type); if (prefix >> 6) { - address.u64 = offset_addr(cpu, address, get_addrsize(prefix, ZM), inc_clk, prefix); + address = offset_addr(cpu, read_value(cpu, cpu->pc, size, inc_clk, 0), size, inc_clk, prefix); + } else { + address = read_value(cpu, cpu->pc, size, inc_clk, 0); } if (inc_pc) { - cpu->pc += get_addrsize(prefix, ZM)+1; + cpu->pc += size+1; } - return address.u64; + return address; } static inline uint64_t zmx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif - return zm_addr(cpu, prefix, inc_clk, inc_pc) + cpu->x; + return read_addr(cpu, prefix, inc_clk, ZM, inc_pc) + cpu->x; } static inline uint64_t zmy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif - return zm_addr(cpu, prefix, inc_clk, inc_pc) + cpu->y; + return read_addr(cpu, prefix, inc_clk, ZM, inc_pc) + cpu->y; } -static inline uint64_t abs_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { - union reg address = read_value(cpu, cpu->pc, get_addrsize(prefix, ABS), inc_clk, 0); - if (prefix >> 6) { - address.u64 = offset_addr(cpu, address, get_addrsize(prefix, ABS), inc_clk, prefix); - } - if (inc_pc) { - cpu->pc += get_addrsize(prefix, ABS)+1; - } - return address.u64; -} static inline uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { - union reg address = read_value(cpu, zm_addr(cpu, prefix, inc_clk, inc_pc), 7, inc_clk, 0); - return address.u64; + return read_value(cpu, read_addr(cpu, prefix, inc_clk, ZM, inc_pc), 7, inc_clk, 0); } static inline uint64_t indx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { - union reg address = read_value(cpu, zm_addr(cpu, prefix, inc_clk, inc_pc)+cpu->x, 7, inc_clk, 0); #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif - return address.u64; + return read_value(cpu, read_addr(cpu, prefix, inc_clk, ZM, inc_pc)+cpu->x, 7, inc_clk, 0); } static inline uint64_t indy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif return ind_addr(cpu, prefix, inc_clk, inc_pc) + cpu->y; } @@ -204,39 +181,30 @@ static inline uint64_t indy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_cl static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { uint8_t rs = (prefix >> 4) & 3; uint8_t size = (1 << rs) - 1; - union reg offset = read_value(cpu, cpu->pc, size, inc_clk, 0); + uint64_t offset = read_value(cpu, cpu->pc, size, inc_clk, 0); uint64_t address; if (inc_pc) { cpu->pc += (size + 1); } - switch (rs) { - default: address = cpu->pc + (int8_t )offset.u8 [0]; break; - case 1 : address = cpu->pc + (int16_t)offset.u16[0]; break; - case 2 : address = cpu->pc + (int32_t)offset.u32[0]; break; - case 3 : address = cpu->pc + (int64_t)offset.u64 ; break; - } #if getclk - if (inc_clk) { - ++cpu->clk; - } + cpu->clk += inc_clk; #endif - return address; + switch (rs) { + default: return cpu->pc + (int8_t )offset; + case 1 : return cpu->pc + (int16_t)offset; + case 2 : return cpu->pc + (int32_t)offset; + case 3 : return cpu->pc + (int64_t)offset; + } } static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) { - union reg address; - union reg value; - uint8_t tmp = 0; - uint64_t tmp2 = 0; - union reg saveaddr; - address.u64 = 0; - value.u64 = 0; + uint64_t address = 0; switch (optype[opcode]) { case BREG: case IMPL: break; case IMM: - address.u64 = imm_addr(cpu); + address = imm_addr(cpu); switch (opcode) { case LSL_IMM: case LSR_IMM: @@ -255,17 +223,17 @@ static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, case TXS_IMM: break; } break; - case ZM : address.u64 = zm_addr(cpu, prefix, inc_clk, inc_pc); break; - case ZMX : address.u64 = zmx_addr(cpu, prefix, inc_clk, inc_pc); break; - case ZMY : address.u64 = zmy_addr(cpu, prefix, inc_clk, inc_pc); break; - case IND : address.u64 = ind_addr(cpu, prefix, inc_clk, inc_pc); break; - case INDX: address.u64 = indx_addr(cpu, prefix, inc_clk, inc_pc); break; - case INDY: address.u64 = indy_addr(cpu, prefix, inc_clk, inc_pc); break; - case ABS : address.u64 = abs_addr(cpu, prefix, inc_clk, inc_pc); break; - case REL : address.u64 = rel_addr(cpu, prefix, inc_clk, inc_pc); break; + case ZM : return read_addr(cpu, prefix, inc_clk, ZM, inc_pc); + case ABS : return read_addr(cpu, prefix, inc_clk, ABS, inc_pc); + case ZMX : return zmx_addr(cpu, prefix, inc_clk, /**/ inc_pc); + case ZMY : return zmy_addr(cpu, prefix, inc_clk, /**/ inc_pc); + case IND : return ind_addr(cpu, prefix, inc_clk, /**/ inc_pc); + case INDX: return indx_addr(cpu, prefix, inc_clk, /**/ inc_pc); + case INDY: return indy_addr(cpu, prefix, inc_clk, /**/ inc_pc); + case REL : return rel_addr(cpu, prefix, inc_clk, /**/ inc_pc); } - return address.u64; + return address; } static inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { @@ -319,9 +287,9 @@ static inline void push(struct sux *cpu, uint64_t value, uint8_t size, uint8_t t static inline uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) { uint64_t sbr = (cpu->stk_st << 16); - union reg reg = read_value(cpu, sbr+cpu->sp+1, size, 1, 0); + uint64_t value = read_value(cpu, sbr+cpu->sp+1, size, 1, 0); cpu->sp += size+1; - return reg.u64; + return value; } static inline void and(struct sux *cpu, uint64_t value, uint8_t thread) { @@ -425,7 +393,8 @@ static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t t /* Increment, or Decrement memory. */ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) { uint8_t size = (1 << ((prefix >> 4) & 3))-1; - union reg value = read_value(cpu, address, size, 1, 0); + union reg value; + value.u64 = read_value(cpu, address, size, 1, 0); if (inc) { value.u64++; } else { diff --git a/test/bit-or.s b/test/bit-or.s new file mode 100644 index 0000000..d87f2d2 --- /dev/null +++ b/test/bit-or.s @@ -0,0 +1,317 @@ +.org 0 +IMM = 1 << 0 ; Immediate Data. +ZM = 1 << 1 ; Zero Matrix. +ZMX = 1 << 2 ; Zero Matrix, indexed with X. +ZMY = 1 << 3 ; Zero Matrix, indexed with Y. +IND = 1 << 4 ; Indirect. +INDX = 1 << 5 ; Indexed Indirect. +INDY = 1 << 6 ; Indirect Indexed. +ABS = 1 << 7 ; Absolute. +REL = 1 << 8 ; Relative. +BREG = 1 << 9 ; B Register. +IMPL = 1 << 10 ; Implied. +INDX2 = 1 << 11 ; Special case of INDX that uses the indirect table. +ZM2 = 1 << 12 ; Special case of Zero Matrix used by JMP, and JSR. + +inst: + ; ADC + .word IMM|ZM|ABS|BREG + .byte $01 + + ; AND + .word IMM|ZM|ABS|BREG + .byte $41 + + ; ASR + .word IMM|ZM|ABS|BREG + .byte $62 + + ; BCC + .word REL + .byte $A0 + + ; BCS + .word REL + .byte $90 + + ; BEQ + .word REL + .byte $B0 + + ; BNE + .word REL + .byte $C0 + + ; BNG + .word REL + .byte $80 + + ; BPO + .word REL + .byte $70 + + ; BRA + .word REL + .byte $F0 + + ; BRK + .word IMPL + .byte $69 + + ; BVC + .word REL + .byte $E0 + + ; BVS + .word REL + .byte $D0 + + ; CLC + .word IMPL + .byte $09 + + ; CLI + .word IMPL + .byte $29 + + ; CLV + .word IMPL + .byte $49 + + ; CMP + .word IMM|ZM|IND|INDY|ABS|BREG|INDX2 + .byte $82 + + ; CPB + .word IMM|ZM|IND|INDY|ABS|INDX2 + .byte $04 + + ; CPS + .word IMPL + .byte $00 + + ; CPX + .word IMM|ZM|IND|ABS + .byte $24 + + ; CPY + .word IMM|ZM|IND|ABS + .byte $44 + + ; DEB + .word IMPL + .byte $99 + + ; DEC + .word IMPL|ZM|ABS + .byte $84 + + ; DEX + .word IMPL + .byte $B9 + + ; DEY + .word IMPL + .byte $79 + + ; DIV + .word IMM|ZM|ABS|BREG + .byte $42 + + ; INB + .word IMPL + .byte $A9 + + ; INC + .word IMPL|ZM|ABS + .byte $A4 + + ; INX + .word IMPL + .byte $C9 + + ; INY + .word IMPL + .byte $89 + + ; JMP + .word ABS|IND|ZM2 + .byte $00 + + ; JSR + .word ABS|IND|ZM2 + .byte $20 + + ; LDA + .word IMM|ZM|ZMX|ZMY|IND|INDX|INDY|ABS + .byte $C2 + + ; LDB + .word IMM|ZM|ZMX|ZMY|IND|INDX|INDY|ABS + .byte $E2 + + ; LDX + .word IMM|ZM|IND|ABS + .byte $64 + + ; LDY + .word IMM|ZM|IND|ABS + .byte $A2 + + ; LSL + .word IMM|ZM|ABS|BREG + .byte $A1 + + ; LSR + .word IMM|ZM|ABS|BREG + .byte $C1 + + ; MUL + .word IMM|ZM|ABS|BREG + .byte $22 + + ; NOP + .word IMPL + .byte $EA + + ; ORA + .word IMM|ZM|ABS|BREG + .byte $61 + + ; PHA + .word IMPL + .byte $8E + + ; PHB + .word IMPL + .byte $AE + + ; PHP + .word IMPL + .byte $6E + + ; PHX + .word IMPL + .byte $EE + + ; PHY + .word IMPL + .byte $CE + + ; PLA + .word IMPL + .byte $9E + + ; PLB + .word IMPL + .byte $BE + + ; PLP + .word IMPL + .byte $7E + + ; PLX + .word IMPL + .byte $FE + + ; PLY + .word IMPL + .byte $DE + + ; ROL + .word IMM|ZM|ABS|BREG + .byte $E1 + + ; ROR + .word IMM|ZM|ABS|BREG + .byte $02 + + ; RTI + .word IMPL + .byte $60 + + ; RTS + .word IMPL + .byte $50 + + ; SBC + .word IMM|ZM|ABS|BREG + .byte $21 + + ; SEC + .word IMPL + .byte $19 + + ; SEI + .word IMPL + .byte $39 + + ; STA + .word ZM|ZMX|ZMY|IND|INDX|INDY|ABS + .byte $28 + + ; STB + .word ZM|ZMX|ZMY|IND|INDX|INDY|ABS + .byte $48 + + ; STX + .word ZM|IND|ABS + .byte $68 + + ; STY + .word ZM|IND|ABS + .byte $08 + + ; TAB + .word IMPL + .byte $0A + + ; TAX + .word IMPL + .byte $4A + + ; TAY + .word IMPL + .byte $2A + + ; TBA + .word IMPL + .byte $1A + + ; TSX + .word IMPL + .byte $8A + + ; TXA + .word IMPL + .byte $5A + + ; TXS + .word IMPL|IMM + .byte $9A + + ; TXY + .word IMPL + .byte $7A + + ; TYA + .word IMPL + .byte $3A + + ; TYX + .word IMPL + .byte $6A + + ; WAI + .word IMPL + .byte $59 + + ; XOR + .word IMM|ZM|ABS|BREG + .byte $81 + + +a +.org 0 +v +q diff --git a/test/fib2.s b/test/fib2.s index ee58697..23f0bf5 100644 --- a/test/fib2.s +++ b/test/fib2.s @@ -18,6 +18,6 @@ fib: tab ; txa ; tay ; - jmp fib ; No, so keep looping. + bra fib ; No, so keep looping. a d diff --git a/test/popcnt2.s b/test/popcnt2.s index 503b074..3aa38f0 100644 --- a/test/popcnt2.s +++ b/test/popcnt2.s @@ -14,7 +14,7 @@ popcnt: bra @loop ; Keep looping. @end: tya ; Return the bit count. - rts ; End of popcnt. + rts.w ; End of popcnt. reset: @@ -27,7 +27,7 @@ reset: tay ; Reset Y. main: pha.q ; Save A. - jsr popcnt ; Get population count. + jsr.w popcnt ; Get population count. tay ; Save it in Y. pla.q ; Get A back. inc ; Increment A by one. diff --git a/test/reg-transfer.s b/test/reg-transfer.s index 37e0d51..b9d1280 100644 --- a/test/reg-transfer.s +++ b/test/reg-transfer.s @@ -17,5 +17,4 @@ bench: ; Execute the program. a -done - +d diff --git a/test/subroutine.s b/test/subroutine.s index d39fc15..122c34c 100644 --- a/test/subroutine.s +++ b/test/subroutine.s @@ -23,21 +23,21 @@ start: ;inb ;stb $C010 ;deb -bench: +@bench: jsr clr_buf - jmp bench + bra @bench clr_buf: tba ; Reset the Accumulator. cpy.w #$1FFF ; Did we clear all of the screen buffer? - bcs clr_buf_end ; Yes, so we're done. + bcs @end ; Yes, so we're done. sta.q (ptr), y ; No, so clear eight bytes. sta.q (ptr2), y ; Clear eight more bytes. tya ; Copy the buffer index. adc #$10 ; Increment the index by 16. tay ; Update the index. - jmp clr_buf ; Keep looping. -clr_buf_end: + bra clr_buf ; Keep looping. +@end: tay ; Set the index back to zero. rts ; End of clr_buf. @@ -46,5 +46,4 @@ clr_buf_end: .org $FFC0 .qword reset a -done - +d |