diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-06-11 21:39:59 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-06-11 22:05:03 -0400 |
commit | 460832c13c9d476d71e626a0c42de4eeff3feb63 (patch) | |
tree | b3e5ea55f704d7e1672504eca8e99ffabe9c558a | |
parent | 0bc02d48d100aff63e40132786a89123ac43ae48 (diff) |
Did some more stuff.
- Fix some bugs with strings.
- Started to refactor the instruction functions.
- Added support for using RS prefixes on the memory
based increment, and decrement instructions.
- Started work on SuBAsm's lexer.
Have fun looking at this, BieHDC. :)
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | asmmon.c | 1 | ||||
-rw-r--r-- | assemble.c | 2 | ||||
-rw-r--r-- | io.c | 34 | ||||
-rw-r--r-- | lexer.c | 6 | ||||
-rw-r--r-- | opcode.c | 25 | ||||
-rw-r--r-- | programs/lexer.s | 231 | ||||
-rw-r--r-- | programs/subasm.s | 92 | ||||
-rw-r--r-- | programs/subeditor.s | 20 | ||||
-rw-r--r-- | programs/utils.s | 257 | ||||
-rw-r--r-- | sux.c | 166 | ||||
-rw-r--r-- | sux.h | 259 |
12 files changed, 747 insertions, 348 deletions
@@ -36,7 +36,7 @@ IO_CFLAGS=-DIO=0 endif -OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o assemble.o lexer.o +OBJS = sux.o io.o $(DBG_OBJ) asmmon.o assemble.o lexer.o CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA) OBJS2 = subasm.o subeditor.o @@ -470,7 +470,6 @@ int asmmon(const char *fn) { return 2; } printf("Including %s\n", string[incl[inc_count++]]); - inc_count++; } if (!isinclude) { puts("Finished assembling."); @@ -142,6 +142,8 @@ uint64_t handle_dir(token *t, bytecount *bc, uint8_t isasm, uint64_t address, ui case 'n' : c = '\n'; break; case 'r' : c = '\r'; break; case 't' : c = '\t'; break; + case '\"': c = '\"'; break; + case '\'': c = '\''; break; case '\\': c = '\\'; break; case '0' : c = '\0'; break; } @@ -4,11 +4,16 @@ uint8_t iscol; uint8_t idx = 3; uint8_t bcd[4]; -void io(uint64_t address, uint8_t *esc) { +void io(uint64_t address, uint8_t rw) { int x, y; uint16_t scr_col = 0; + /*step |= (!rw) ? (cpu->pc[thread] == CTRL_ADDR) : step;*/ switch (address) { + case STEP_ADDR: step = (!rw) ? addr[STEP_ADDR] : step; break; case CTRL_ADDR: + if (!rw) { + break; + } kbd_rdy = 1; pthread_mutex_lock(&main_mutex); pthread_cond_signal(&main_cond); @@ -21,6 +26,9 @@ void io(uint64_t address, uint8_t *esc) { kbd_rdy = 0; break; case TX_ADDR: + if (rw) { + break; + } getyx(scr, y, x); #if debug if (!subdbg) { @@ -28,7 +36,7 @@ void io(uint64_t address, uint8_t *esc) { wmove(scr, 28, scr_col); } #endif - if (*esc) { + if (esc) { #if debug if (!subdbg && addr[RX_ADDR] == '\n') { wclrtoeol(scr); @@ -41,7 +49,7 @@ void io(uint64_t address, uint8_t *esc) { #if !debug wmove(scr, y, x); #endif - *esc = 0; + esc = 0; break; case 'B': if (y < getmaxy(scr)) @@ -49,7 +57,7 @@ void io(uint64_t address, uint8_t *esc) { #if !debug wmove(scr, y, x); #endif - *esc = 0; + esc = 0; break; case 'C': if (x < getmaxx(scr)) @@ -57,7 +65,7 @@ void io(uint64_t address, uint8_t *esc) { #if !debug wmove(scr, y, x); #endif - *esc = 0; + esc = 0; break; case 'D': if (x > 0) @@ -65,7 +73,7 @@ void io(uint64_t address, uint8_t *esc) { #if !debug wmove(scr, y, x); #endif - *esc = 0; + esc = 0; break; case 'H': if (!bcd[2] && !bcd[3]) { @@ -81,29 +89,29 @@ void io(uint64_t address, uint8_t *esc) { #if !debug wmove(scr, y, x); #else - mvwprintw(scr, 30, 0, "x: %i, y: %i ", x, y); - /*mvwprintw(scr, 31, 0, "bcd[3-2]: {%u, %u}, bcd[1-0]: {%u, %u}", bcd[3], bcd[2], bcd[1], bcd[0]);*/ + /*mvwprintw(scr, 31, 0, "x: %i, y: %i ", x, y);*/ + mvwprintw(scr, 31, 0, "bcd[3-2]: {%u, %u}, bcd[1-0]: {%u, %u}", bcd[3], bcd[2], bcd[1], bcd[0]); #endif idx = 3; bcd[0] = 0; bcd[1] = 0; bcd[2] = 0; bcd[3] = 0; - *esc = 0; + esc = 0; break; case 'S': #if !debug wscrl(scr, -1); #else #endif - *esc = 0; + esc = 0; break; case 'T': #if !debug wscrl(scr, 1); #else #endif - *esc = 0; + esc = 0; break; case '0': case '1': @@ -150,9 +158,7 @@ void io(uint64_t address, uint8_t *esc) { } #endif break; - case '\033': - *esc = 1; - break; + case '\033': esc = 1; break; case '\n': x = 0; y+=1; @@ -301,7 +301,9 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { break; case PTOK_DQUOTE: i++; - for (; isdelm(str[i+j], dbg) != 4; j++); + for (; isdelm(str[i+j], dbg) != 4 || isesc; j++) { + isesc = (str[i+j] == '\\' && str[i+(j-1)] != '\\'); + } memcpy(lexeme, str+i, j); lexeme[j] = '\0'; i += j; @@ -317,7 +319,7 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); } if (lt->id == TOK_DIR && lt->type == DIR_INCLUDE) { - incl[inc_count] = strid; + incl[inc_count+inc_file] = strid; inc_file++; } lex_type = TOK_STRING; diff --git a/opcode.c b/opcode.c deleted file mode 100644 index 017a298..0000000 --- a/opcode.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "sux.h" - -static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread); -extern inline void adc(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread); -extern inline void push(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); -extern inline void pull(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); -extern inline void and(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void or(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void xor(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void asr(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void rol(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void ror(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void mul(struct sux *cpu, uint64_t value, uint8_t thread); -extern inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); -extern inline void cmp(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); -extern inline void incr(struct sux *cpu, uint8_t opcode, uint8_t thread); -extern inline void decr(struct sux *cpu, uint8_t opcode, uint8_t thread); -extern inline void incm(struct sux *cpu, uint64_t address, uint8_t thread); -extern inline void decm(struct sux *cpu, uint64_t address, uint8_t thread); -extern inline void load(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread); -extern inline void store(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread); diff --git a/programs/lexer.s b/programs/lexer.s new file mode 100644 index 0000000..cd5bb54 --- /dev/null +++ b/programs/lexer.s @@ -0,0 +1,231 @@ +; Lexer, and supporting routines for SuBAsm. + +; Enums. + +; Directives. +DIR_ORG = 0 ; Origin. +DIR_BYTE = 1 ; Byte = 8 bits. +DIR_WORD = 2 ; Word = 16 bits. +DIR_DWORD = 3 ; Dword = 32 bits. +DIR_QWORD = 4 ; Qword = 64 bits. +DIR_INCL = 5 ; Include. + +; Tokens. +TOK_DIR = 0 ; Directive. +TOK_LOCAL = 1 ; Local syobol. +TOK_LABEL = 2 ; Label. +TOK_SYM = 3 ; Symbol. +TOK_EXPR = 4 ; Expression. +TOK_CSV = 5 ; Comma separated value. +TOK_STR = 6 ; String. +TOK_CHAR = 7 ; Character. +TOK_IND = 8 ; Indirect addressing. +TOK_IMM = 9 ; Immediate data. +TOK_MNE = 10 ; Opcode/Mnemonic. +TOK_RS = 11 ; Register size prefix. +TOK_COMM = 12 ; Comment. +TOK_HEX = 13 ; Hex value. +TOK_DEC = 14 ; Decimal value. +TOK_BIN = 15 ; Binary value. +TOK_INCL = 16 ; Include file. + +; Pre-Tokens. +PTOK_DOT = 0 ; . +PTOK_AT = 1 ; @ +PTOK_COLON = 2 ; : +PTOK_EQU = 3 ; = +PTOK_PLUS = 4 ; + +PTOK_MINUS = 5 ; - +PTOK_GT = 6 ; > +PTOK_LT = 7 ; < +PTOK_LBRAK = 8 ; ( +PTOK_RBRAK = 9 ; ) +PTOK_COMMA = 10 ; , +PTOK_X = 11 ; x +PTOK_Y = 12 ; y +PTOK_DQUOT = 13 ; " +PTOK_SQUOT = 14 ; ' +PTOK_HASH = 15 ; # +PTOK_SCOLN = 16 ; ; +PTOK_DOLR = 17 ; $ +PTOK_PRCNT = 18 ; % +PTOK_NUM = 19 ; 0-9 +PTOK_ALPH = 20 ; a-z A-Z +PTOK_OTHR = 21 ; Everything else. + +; Expressions. +EXPR_PLUS = 0 ; Plus. +EXPR_MINUS = 1 ; Minus. +EXPR_LOW = 2 ; Lower half of address. +EXPR_HIGH = 3 ; Upper half of address. +EXPR_NONE = 4 ; No expression. + + +; Data. +.org lexer_data +; Jump table for parsing pre-tokens. +swtab: + .word ptok_dot ; PTOK_DOT + .word ptok_at ; PTOK_AT + .word ptok_col ; PTOK_COLON + .word ptok_equ ; PTOK_EQU + .word ptok_plus ; PTOK_PLUS + .word ptok_min ; PTOK_MINUS + .word ptok_gt ; PTOK_GT + .word ptok_lt ; PTOK_LT + .word ptok_lbrk ; PTOK_LBRAK + .word ptok_rbrk ; PTOK_RBRAK + .word ptok_com ; PTOK_COMMA + .word ptok_xr ; PTOK_X + .word ptok_yr ; PTOK_Y + .word ptok_dqu ; PTOK_DQUOT + .word ptok_squ ; PTOK_SQUOT + .word ptok_hash ; PTOK_HASH + .word ptok_scol ; PTOK_SCOLN + .word ptok_dolr ; PTOK_DOLR + .word ptok_prcn ; PTOK_PRCNT + .word ptok_num ; PTOK_NUM + .word ptok_alph ; PTOK_ALPH + .word ptok_othr ; PTOK_OTHR + +; Data entry point for utility subroutines. +util_data: + + +; Program code. +.org lexer +lex: + ldx #0 ; Reset X. + txa ; Reset A. + phy #2 ; Preserve the screen buffer index. + txy ; Reset Y. + sty.q idx0 ; Clear the first index. + sty.q idx1 ; Clear the second index. + sty.q idx2 ; Clear the third index. +; lda (ptr), y ; Get a character from the line. +; pha #1 ; Preserve the character. +; jsr isdigit ; Is this character a digit? +; pla #1 ; Get the character back. +@getline: + lda #2 ; Get the third byte, of the line table address. + lsl #$10 ; Shift it by 2 bytes. + ldb #1 ; Set the second pointer + lda.w ltok ; to the last line. + jsr set_ptr ; + lda.w (ptr2) ; Get the next line. + jsr set_ptr ; Set the second pointer to the next line. + sta.w ctok ; Make it the current line. + and #0 ; Reset A. +@loop: + ldy.w idx0 ; Get the string index. + lda (ptr), y ; Get a character from the line. + jsr isdelm ; Get the delimiter. + cmp #1 ; Are we at the end of the line? + beq @end ; Yes, so we're done. +@spaces: + ldy.w idx0 ; Get the string index. + inc.w idx0 ; Increment the string index. + lda (ptr), y ; Get a character from the line. + pha #1 ; Preserve the character. + jsr isdelm ; Get the delimiter. + and #$10 ; Is this character, a space, or tab? + pla #1 ; Get the character back. + beq @isstart ; No, so check for the start of the line. + cmp #' ' ; Is this character, a space? + beq @incs ; Yes, so increment the starting space count. + cmp #'\t' ; No, but is it a tab? + beq @inct ; Yes, so increment the starting tab count. + jmp @spaces ; No, so keep looping. +@incs: + inc idx1 ; Increment the space count. + jmp @spaces ; Keep looping. +@inct: + inc idx1+1 ; Increment the tab count. + jmp @spaces ; Keep looping. +@isstart: + pha #2 ; Preserve the character. + lda.w idx1 ; Was there any whitespace? + pla #2 ; Get the character back. + beq @switch ; No, so start lexing. + cpb #1 ; Yes, and are we at the start of the line? + bne @switch ; No, so start lexing. +@whtspace: + ldy #2 ; Yes, so set the line index to the starting whitespace counters. + lda.w idx1 ; Get both indecies. + sta.w (ptr2), y ; Save them in the line. + and #0 ; Reset A. + sta.w idx1 ; Reset the second index. + deb ; Set the isstart flag to false. +@switch: + jsr get_ptok ; Get the pre-token. + jsr parse_ptok ; Parse the pre-token. + beq @end ; We got to the end of the string. + jmp @loop ; Keep looping. +@end: + ply #2 ; Get the screen buffer index back. + rts ; End of lex. + +parse_ptok: + pha #1 ; Preserve the pre-token. + ldb #2 ; Set the third pointer + lda.w #swtab ; to the start of the jump table. + jsr set_ptr ; + and #0 ; Reset A. + pla #1 ; Get the pre-token back. + phy #2 ; Preserve Y. + lsl #1 ; Multiply the pre-token by two, to get the jump index. + tay ; Get the index of the jump table. + lda.w (ptr3), y ; Get the address to jump to. + jsr set_ptr ; Set the third pointer to the case address. + and #0 ; Reset A. + tab ; Reset B. + ply #2 ; Get Y back. + jmp (ptr3) ; Jump to the case label. +ptok_dot: + rts ; End of parse_ptok. +ptok_at: + rts ; End of parse_ptok. +ptok_col: + rts ; End of parse_ptok. +ptok_equ: + rts ; End of parse_ptok. +ptok_plus: + rts ; End of parse_ptok. +ptok_min: + rts ; End of parse_ptok. +ptok_gt: + rts ; End of parse_ptok. +ptok_lt: + rts ; End of parse_ptok. +ptok_lbrk: + rts ; End of parse_ptok. +ptok_rbrk: + rts ; End of parse_ptok. +ptok_com: + rts ; End of parse_ptok. +ptok_xr: + rts ; End of parse_ptok. +ptok_yr: + rts ; End of parse_ptok. +ptok_dqu: + rts ; End of parse_ptok. +ptok_squ: + rts ; End of parse_ptok. +ptok_hash: + rts ; End of parse_ptok. +ptok_scol: + rts ; End of parse_ptok. +ptok_dolr: + rts ; End of parse_ptok. +ptok_prcn: + rts ; End of parse_ptok. +ptok_num: + rts ; End of parse_ptok. +ptok_alph: + rts ; End of parse_ptok. +ptok_othr: + rts ; End of parse_ptok. + + +; Entry point for utility subroutines. +utils: diff --git a/programs/subasm.s b/programs/subasm.s index 4cec219..3c8e767 100644 --- a/programs/subasm.s +++ b/programs/subasm.s @@ -5,6 +5,7 @@ MAX_SYM = $800 ; Max symbol size. +.include "lexer.s" .include "utils.s" .org incl @@ -16,7 +17,7 @@ asm_ver: ; Directives. dir: - .byte "org", + .byte "org" .byte "byte" .byte "word" .byte "dword" @@ -152,8 +153,8 @@ cmd_srt: .word run .word set -; Data entry point for utility subroutines. -util_data: +; Data entry point for the lexer. +lexer_data: ; Token table. @@ -185,27 +186,25 @@ idx2: idx3: .qword 0 +; Current token line. +ctok: + .word 0 + +; Last token line. +ltok: + .word 0 + ; Lexeme string. lexeme: -; Symbol tables. +; Symbol table. .org lexeme+$100 -sym_val: -.org sym_val+$4000 -sym_id: -.org sym_id+$1000 -sym_def: -.org sym_def+$100 -sym_name: +sym: ; Fixup table. ; Fixups are unresolved symbols. -.org sym_name+$1000 -fix_sym: -.org fix_sym+$1000 -fix_ln: -.org fix_ln+$1000 -fix_val: +.org sym+$8000 +fix: ; Start of program code. @@ -217,16 +216,12 @@ subasm: 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 ; + bne @cmd ; Yes, so skip everything else. 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: + 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 ; @@ -234,7 +229,7 @@ parse_cmd: 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. + 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. @@ -244,7 +239,8 @@ parse_cmd: jsr set_ptr ; ldb #0 ; Reset B. jsr (ptr3) ; Run the command's subroutine. - jmp subasm_end ; We are done. +@end: + rts ; End of subasm. chk_shcmd: tba ; Reset A. @@ -259,6 +255,7 @@ chk_shcmd: 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. @@ -286,6 +283,41 @@ chk_shcmd: 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. @@ -347,7 +379,5 @@ set: @end: rts ; End of set. - ; Entry point for utility subroutines. -utils: - +lexer: diff --git a/programs/subeditor.s b/programs/subeditor.s index 26c6f7d..1768d62 100644 --- a/programs/subeditor.s +++ b/programs/subeditor.s @@ -1058,8 +1058,10 @@ update_pos: 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. tay ; Place the index into the Y register. + tba ; Reset A. lda #$1B ; Print an escape character sta scr ; to the screen. lda #'[' ; Print '[' @@ -1072,27 +1074,19 @@ update_pos: getrow: lda scr_row ; Get the cursor's y coordinate. - div #10 ; Divide A by 10. - adc #'0' ; Convert it to ascii, and - sta scr ; print to the screen. - tba ; Get the remainder. - adc #'0' ; Convert it to ascii, and - sta scr ; print to the screen. - rts ; End of getrow. - + jmp bcd ; Convert it to BCD. getcol: lda #';' ; Print ';' sta scr ; to the screen. lda scr_col ; Get the cursor's x coordinate. +bcd: div #10 ; Divide A by 10. - clc ; - adc #'0' ; Convert it to ascii, and + ora #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. - clc - adc #'0' ; Convert it to ascii, and + ora #'0' ; Convert it to ascii, and sta scr ; print to the screen. - rts ; End of getrow. + rts ; End of bcd. scrl_down: inc scr_str ; Increment the starting line of the screen. diff --git a/programs/utils.s b/programs/utils.s index 6032a47..d8d4aa2 100644 --- a/programs/utils.s +++ b/programs/utils.s @@ -5,6 +5,16 @@ hex_char: .byte "0123456789ABCDEF" +; Compare, and return table for pre-tokens. +ptok_tab: + .byte ".@:=+-><(),xy\"\'#;$%" +; Compare, and return table for isdelm. +dtab: + .byte "\n,\"\' " +; Compare, and return table for isdelm2. +dtab2: + .byte "),.+<>-=;\n" + .org utils print_hi: @@ -134,3 +144,250 @@ charcpy: sta strbuf, x ; Save it in the string buffer. inc idx3 ; Increment the string index. rts ; End of charcpy. + + +strlen: + ldb #1 ; Set the second pointer + jsr set_ptr ; to the passed pointer. + deb ; Reset B. + tba ; Reset A. + tax ; Reset X. + phy #2 ; Preserve Y. + txy ; Reset Y. +@loop: + lda (ptr2), y ; Are we at the end of the string? + beq @end ; Yes, so we're done. + iny ; No, so increment the index. + jmp @loop ; Keep looping. +@end: + tyx ; Return the length in X. + ply #2 ; Get the preserved value back. + rts ; End of strlen. + + +strcmp: + ldb #1 ; Set the second pointer + jsr set_ptr ; to the passed pointer. + deb ; Reset B. + tba ; Reset A. + phy #2 ; Preserve Y. + tay ; Reset Y. +@loop: + ldb #0 ; Set the islong flag to false. + lda (ptr), y ; Are we at the end of the first string? + beq cmpr ; Yes, so check if we're too short, or too long. + ldb #1 ; No, so set the islong flag to true. + cmp (ptr2), y ; Is the character of both strings, the same? + bne cmpr ; No, so check if we're too short, or too long. + iny ; Yes, so increment the index. + jmp @loop ; Keep looping. + +strcasecmp: + ldb #1 ; Set the second pointer + jsr set_ptr ; to the passed pointer. + deb ; Reset B. + tba ; Reset A. + phy #2 ; Preserve Y. + tay ; Reset Y. +@loop: + ldb #0 ; Set the islong flag to false. + lda (ptr), y ; Are we at the end of the first string? + beq cmpr ; Yes, so check if we're too short, or too long. + ldb #1 ; No, so set the islong flag to true. + jsr tolower ; Convert the character of string 1 to lowercase. + phb #1 ; Preserve the islong flag. + pha #1 ; Preserve the converted character. + lda (ptr2), y ; Get the character of the second string. + jsr tolower ; Convert the character of string 2 to lowercase. + tab ; Place it in B. + pla #1 ; Get the character of string 1 back. + cab ; Is the character of both strings, the same? + plb #1 ; Get the islong flag back. + bne cmpr ; No, so check if we're too short, or too long. + iny ; Yes, so increment the index. + jmp @loop ; Keep looping. + +cmpr: + lda (ptr2), y ; Are we at the end of the second string? + beq @islong ; Yes, so check the islong flag. +@isshort: + lda (ptr), y ; No, but are we at the end of the first string? + beq @short ; Yes, so return -1. +@islong: + cpb #1 ; Is the islong flag true? + bne @equ ; No, so return 0. +@long: + lda #1 ; Yes, so return 1. + jmp @end ; We are done. +@equ: + lda #0 ; Return 0. + jmp @end ; We are done. +@short: + lda #$FF ; Return -1. +@end: + ply #2 ; Get the preserved value back. + rts ; End of strcmp. + + +isdigit: + sec ; Prepare for a non carrying subtraction. + sbc #'0' ; Subtract $30 from the passed character. + and #$FF ; Make sure that we have only one byte. + cmp #10 ; Is the subtracted value, less than 10? + bcs @false ; No, so return false. +@true: + lda #1 ; Yes, so return true. + jmp @end ; We are done. +@false: + lda #0 ; Return false. +@end: + rts ; End of isdigit. + +isxdigit: + pha #1 ; Preserve the character. + jsr isdigit ; Is this character, a decimal digit? + pla #1 ; Get the character back. + bne @true ; Yes, so return true. +@alpha: + sec ; No, so prepare for a non carrying subtract. + ora #$20 ; Convert it to lowercase. + sbc #'a' ; Subtract $61 from the character. + and #$FF ; Make sure that we have only one byte. + cmp #6 ; Is the subtracted value, less than 6? + bcs @false ; No, so return false. +@true: + lda #1 ; Yes, so return true. + jmp @end ; We are done. +@false: + lda #0 ; Return false. +@end: + rts ; End of isxdigit. + + +isupper: + sec ; Prepare for a non carrying subtraction. + sbc #'A' ; Subtract $41 from the passed character. + jmp isletter ; Check if it's less than 26. +islower: + sec ; Prepare for a non carrying subtraction. + sbc #'a' ; Subtract $61 from the passed character. +isletter: + and #$FF ; Make sure that we have only one byte. + cmp #26 ; Is the subtracted value, less than 26? + bcs @false ; No, so return false. +@true: + lda #1 ; Yes, so return true. + jmp @end ; We are done. +@false: + lda #0 ; Return false. +@end: + rts ; End of isletter. + + +tolower: + pha #1 ; Preserve the character. + jsr isupper ; Is this character, an uppercase character? + pla #1 ; Get the character back. + beq @end ; No, so we're done. +@lower: + ora #$20 ; Yes, so convert it to lowercase. +@end: + rts ; End of tolower. + + +toupper: + pha #1 ; Preserve the character. + jsr islower ; Is this character, a lowercase character? + pla #1 ; Get the character back. + beq @end ; No, so we're done. +@upper: + and #$5F ; Yes, so convert it to uppercase. +@end: + rts ; End of toupper. + + +isdelm2: + ldx #0 ; Reset X. +@loop: + ldb dtab2, x ; Get the compare value. + beq @other ; We hit the end of the table, so check for the others. + cab ; Are they the same? + beq @r1 ; Yes, so return 1. + inx ; No, so increment the table index. + jmp @loop ; Keep looping. +@other: + ldx #0 ; Reset X. + cmp #0 ; Is this a null terminator? + beq @r1 ; Yes, so return 1. + cmp #'\t' ; No, but is it a tab? + beq @r2 ; Yes, so return 2. + cmp #' ' ; No, but is it a space? + beq @r2 ; Yes, so also return 2. +@r0: + lda #0 ; Return 0. + rts ; End of isdelm2. +@r1: + ldx #0 ; Reset X. + lda #1 ; Return 1. + rts ; End of isdelm2. +@r2: + lda #2 ; Return 2. + rts ; End of isdelm2. + + +isdelm: + ldx #0 ; Reset X. +@loop: + ldb dtab, x ; Get the compare value. + beq @other ; We hit the end of the table, so check for the others. + cab ; Are they the same? + beq @rshft ; Yes, so return 1 << index. + inx ; No, so increment the table index. + jmp @loop ; Keep looping. +@other: + ldx #0 ; Reset X. + cmp #0 ; Is this a null terminator? + beq @rshft ; Yes, so return 1. + ldx #4 ; No, so set the shift amount to 4. + cmp #'\t' ; Is this a tab? + beq @rshft ; Yes, so return 16. + ldx #0 ; No, so reset X. +@r0: + lda #0 ; Return 0. + rts ; End of isdelm. +@rshft: + stx a ; Save the shift value. + ldx #0 ; Reset X. + lda #1 ; Set up the bitshift. + lsl a ; Return 1 << X. + rts ; End of isdelm. + + +get_ptok: + ldx #0 ; Reset X. + jsr tolower ; Conver the character to lowercase. +@loop: + ldb ptok_tab, x ; Get the compare value. + beq @other ; We hit the end of the table, so check for the others. + cab ; Are they the same? + beq @rtab ; Yes, so return X. + inx ; No, so increment the table index. + jmp @loop ; Keep looping. +@rtab: + txa ; Return X. + rts ; End of get_ptok. +@other: + tab ; Preserve the character. + jsr isdigit ; Is this character a digit? + bne @rnum ; Yes, so return PTOK_NUM. + tba ; No, so get the character back. + jsr islower ; Is it an alphabetical character? + bne @ralph ; Yes, so return PTOK_ALPH. + lda #PTOK_OTHR ; No, so return PTOK_OTHR. + rts ; End of get_ptok. +@rnum: + lda #PTOK_NUM ; Return PTOK_NUM. + rts ; End of get_ptok. +@ralph: + lda #PTOK_ALPH ; Return PTOK_ALPH. + rts ; End of get_ptok. @@ -29,6 +29,7 @@ pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER; uint8_t threads_done = 0; uint8_t step = 0; +uint8_t esc = 0; uint8_t *addr; @@ -52,7 +53,6 @@ void *run(void *args) { uint8_t thread = thr->th; uint8_t prefix = 0; uint8_t opcode = 0; - uint8_t esc = 0; union reg address; union reg value; #if getclk @@ -165,13 +165,11 @@ void *run(void *args) { case ADC_Z: /* ADC Zero Matrix. */ adc(cpu, value.u64, thread); break; - case PHB: /* PusH B register to stack. */ - case PHP: /* PusH Processor status to stack. */ - case PHA: /* PusH Accumulator to stack. */ - case PHY: /* PusH Y register to stack. */ - case PHX: /* PusH X register to stack. */ - push(cpu, value.u64, opcode, thread); - break; + case PHP: push(cpu, value.u64, cpu->ps.u8[thread], thread); break; /* PusH Processor status to stack. */ + case PHA: push(cpu, value.u64, cpu->a[thread ], thread); break; /* PusH Accumulator to stack. */ + case PHB: push(cpu, value.u64, cpu->b[thread ], thread); break; /* PusH B register to stack. */ + case PHY: push(cpu, value.u64, cpu->y[thread ], thread); break; /* PusH Y register to stack. */ + case PHX: push(cpu, value.u64, cpu->x[thread ], thread); break; /* PusH X register to stack. */ case TAY: /* Transfer Accumulator to Y. */ case TAX: /* Transfer Accumulator to Y. */ case TYX: /* Transfer Y to X. */ @@ -196,12 +194,11 @@ void *run(void *args) { case SBC_Z: /* SBC Zero Matrix. */ sbc(cpu, value.u64, thread); break; - case PLB: /* PuLl B register from stack. */ - case PLP: /* PuLl Processor status from stack. */ - case PLA: /* PuLl Accumulator from stack. */ - case PLY: /* PuLl Y register from stack. */ - case PLX: /* PuLl X register from stack. */ - pull(cpu, value.u64, opcode, thread); + case PLP: cpu->ps.u8[thread] = pull(cpu, value.u64, thread); break; /* PuLl Processor status from stack. */ + case PLA: cpu->a[thread ] = pull(cpu, value.u64, thread); break; /* PuLl Accumulator from stack. */ + case PLB: cpu->b[thread ] = pull(cpu, value.u64, thread); break; /* PuLl B register from stack. */ + case PLY: cpu->y[thread ] = pull(cpu, value.u64, thread); break; /* PuLl Y register from stack. */ + case PLX: cpu->x[thread ] = pull(cpu, value.u64, thread); break; /* PuLl X register from stack. */ break; case ABA: /* bitwise And with Accumulator, and B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ @@ -275,29 +272,34 @@ void *run(void *args) { setflag(1, C); break; case STA: /* STA Absolute. */ - case STY: /* STY Absolute. */ - case STX: /* STX Absolute. */ - case STB: /* STB Absolute. */ case STA_Z: /* STA Zero Matrix. */ - case STY_Z: /* STY Zero Matrix. */ - case STX_Z: /* STX Zero Matrix. */ - case STB_Z: /* STB Zero Matrix. */ case STA_ZX: /* STA Zero Matrix, Indexed with X. */ + case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ + case STA_IN: /* STA Indirect. */ + case STA_IX: /* STA Indexed Indirect. */ + case STA_IY: /* STA Indirect Indexed. */ + store(cpu, address.u64, cpu->a[thread], prefix, thread); + break; + case STY: /* STY Absolute. */ + case STY_Z: /* STY Zero Matrix. */ case STY_ZX: /* STY Zero Matrix, Indexed with X. */ + case STY_IN: /* STY Indirect. */ + store(cpu, address.u64, cpu->y[thread], prefix, thread); + break; + case STX: /* STX Absolute. */ + case STX_Z: /* STX Zero Matrix. */ case STX_ZY: /* STX Zero Matrix, Indexed with Y. */ + case STX_IN: /* STX Indirect. */ + store(cpu, address.u64, cpu->x[thread], prefix, thread); + break; + case STB: /* STB Absolute. */ + case STB_Z: /* STB Zero Matrix. */ case STB_ZX: /* STB Zero Matrix, Indexed with X. */ - case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ - case STY_IN: /* STY Indirect. */ - case STX_IN: /* STX Indirect. */ - case STA_IN: /* STA Indirect. */ case STB_IN: /* STB Indirect. */ - case STA_IX: /* STA Indexed Indirect. */ case STB_IX: /* STB Indexed Indirect. */ - case STA_IY: /* STA Indirect Indexed. */ case STB_IY: /* STB Indirect Indexed. */ - store(cpu, address.u64, &esc, opcode, prefix, thread); - step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; + store(cpu, address.u64, cpu->b[thread], prefix, thread); break; case BCC: /* BCC Absolute. */ case BCC_Z: /* BCC Zero Matrix. */ @@ -323,32 +325,38 @@ void *run(void *args) { setflag(0, C); break; case LDB: /* LDB Immediate. */ - case LDA: /* LDA Immediate. */ - case LDY: /* LDY Immediate. */ - case LDX: /* LDX Immediate. */ case LDB_AB: /* LDB Absolute. */ - case LDA_AB: /* LDA Absolute. */ - case LDY_AB: /* LDY Absolute. */ - case LDX_AB: /* LDX Absolute. */ case LDB_Z: /* LDB Zero Matrix. */ - case LDA_Z: /* LDA Zero Matrix. */ - case LDY_Z: /* LDY Zero Matrix. */ - case LDX_Z: /* LDX Zero Matrix. */ case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ - case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ - case LDY_ZX: /* LDY Zero Matrix, Indexed with X. */ - case LDX_ZY: /* LDX Zero Matrix, Indexed with Y. */ case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ - case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ - case LDB_IN: /* LDY Indirect. */ - case LDA_IN: /* LDX Indirect. */ - case LDY_IN: /* LDB Indirect. */ - case LDX_IN: /* LDA Indirect. */ + case LDB_IN: /* LDB Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ - case LDA_IX: /* LDA Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ + cpu->b[thread] = load(cpu, address.u64, cpu->b[thread], prefix, thread); + break; + case LDA: /* LDA Immediate. */ + case LDA_AB: /* LDA Absolute. */ + case LDA_Z: /* LDA Zero Matrix. */ + case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ + case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ + case LDA_IN: /* LDA Indirect. */ + case LDA_IX: /* LDA Indexed Indirect. */ case LDA_IY: /* LDA Indirect Indexed. */ - load(cpu, address.u64, &esc, opcode, prefix, thread); + cpu->a[thread] = load(cpu, address.u64, cpu->a[thread], prefix, thread); + break; + case LDY: /* LDY Immediate. */ + case LDY_AB: /* LDY Absolute. */ + case LDY_Z: /* LDY Zero Matrix. */ + case LDY_ZX: /* LDY Zero Matrix, Indexed with X. */ + case LDY_IN: /* LDY Indirect. */ + cpu->y[thread] = load(cpu, address.u64, cpu->y[thread], prefix, thread); + break; + case LDX: /* LDX Immediate. */ + case LDX_AB: /* LDX Absolute. */ + case LDX_Z: /* LDX Zero Matrix. */ + case LDX_ZY: /* LDX Zero Matrix, Indexed with Y. */ + case LDX_IN: /* LDX Indirect. */ + cpu->x[thread] = load(cpu, address.u64, cpu->x[thread], prefix, thread); break; case BEQ: /* BEQ Absolute. */ case BEQ_Z: /* BEQ Zero Matrix. */ @@ -404,29 +412,35 @@ void *run(void *args) { case CLV: /* CLear oVerflow flag. */ setflag(0, V); break; + case CPB: /* CPB Immediate. */ + case CPB_AB: /* CPB Absolute. */ + case CPB_Z: /* CPB Zero Matrix. */ + case CPB_IN: /* CPB Indirect. */ + case CPB_IX: /* CPB Indexed Indirect. */ + case CPB_IY: /* CPB Indirect Indexed. */ + cmp(cpu, value.u64, cpu->b[thread], thread); + break; case CAB: /* Compare Accumulator, and B. */ value.u64 = cpu->b[thread]; /* Falls Through. */ - case CPB: /* CPB Immediate. */ case CMP: /* CMP Immediate. */ - case CPY: /* CPY Immediate. */ - case CPX: /* CPX Immediate. */ - case CPY_AB: /* CPY Absolute. */ - case CPX_AB: /* CPX Absolute. */ case CMP_AB: /* CMP Absolute. */ - case CPB_AB: /* CPB Absolute. */ - case CPY_Z: /* CPY Zero Matrix. */ - case CPX_Z: /* CPX Zero Matrix. */ case CMP_Z: /* CMP Zero Matrix. */ - case CPB_Z: /* CPB Zero Matrix. */ - case CPY_IN: /* CMP Indirect. */ - case CPX_IN: /* CPY Indirect. */ - case CMP_IN: /* CPX Indirect. */ - case CPB_IN: /* CPB Indirect. */ + case CMP_IN: /* CMP Indirect. */ case CMP_IX: /* CMP Indexed Indirect. */ - case CPB_IX: /* CPB Indexed Indirect. */ case CMP_IY: /* CMP Indirect Indexed. */ - case CPB_IY: /* CPB Indirect Indexed. */ - cmp(cpu, value.u64, opcode, thread); + cmp(cpu, value.u64, cpu->a[thread], thread); + break; + case CPY: /* CPY Immediate. */ + case CPY_AB: /* CPY Absolute. */ + case CPY_Z: /* CPY Zero Matrix. */ + case CPY_IN: /* CPY Indirect. */ + cmp(cpu, value.u64, cpu->y[thread], thread); + break; + case CPX: /* CPX Immediate. */ + case CPX_AB: /* CPX Absolute. */ + case CPX_Z: /* CPX Zero Matrix. */ + case CPX_IN: /* CPX Indirect. */ + cmp(cpu, value.u64, cpu->x[thread], thread); break; case ENT: /* ENd Thread. */ /* cpu->crt &= ~value; @@ -434,18 +448,14 @@ void *run(void *args) { if ((value >> i) & 1) cpu->pc[i+1] = cpu->pc[0]+(i+1);*/ break; - case INC: /* INC Accumulator. */ - case INB: - case INY: - case INX: - incr(cpu, opcode, thread); - break; - case DEC: /* DEC Accumulator. */ - case DEB: - case DEY: - case DEX: - decr(cpu, opcode, thread); - break; + case INC: cpu->a[thread] = idr(cpu, cpu->a[thread], 1, thread); break; + case INB: cpu->b[thread] = idr(cpu, cpu->b[thread], 1, thread); break; + case INY: cpu->y[thread] = idr(cpu, cpu->y[thread], 1, thread); break; + case INX: cpu->x[thread] = idr(cpu, cpu->x[thread], 1, thread); break; + case DEC: cpu->a[thread] = idr(cpu, cpu->a[thread], 0, thread); break; + case DEB: cpu->b[thread] = idr(cpu, cpu->b[thread], 0, thread); break; + case DEY: cpu->y[thread] = idr(cpu, cpu->y[thread], 0, thread); break; + case DEX: cpu->x[thread] = idr(cpu, cpu->x[thread], 0, thread); break; case JSR_IN: /* JSR Indirect. */ case JSR: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ @@ -463,8 +473,7 @@ void *run(void *args) { break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ - incm(cpu, address.u64, thread); - step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; + idm(cpu, address.u64, prefix, 1, thread); break; case NOP: /* No OPeration. */ break; @@ -485,8 +494,7 @@ void *run(void *args) { break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ - decm(cpu, address.u64, thread); - step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; + idm(cpu, address.u64, prefix, 0, thread); break; case BRK: /* BReaK. */ case WAI: /* WAit for Interrupt. */ @@ -22,6 +22,8 @@ extern WINDOW *scr; extern uint8_t subdbg; #endif +extern uint8_t step; +extern uint8_t esc; #define setflag(flag, bit) ((flag)) ? (cpu->ps.u8[thread] |= bit) : (cpu->ps.u8[thread] &= ~bit) #define getflag(bit) (cpu->ps.u8[thread] & bit) @@ -35,7 +37,7 @@ extern pthread_cond_t main_cond; extern void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread); #endif -extern void io(uint64_t address, uint8_t *esc); +extern void io(uint64_t address, uint8_t rw); static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread) { union reg address; @@ -47,6 +49,7 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco case IMPL: break; case IMM: + address.u64 = cpu->pc[thread]; switch (opcode) { case PHB: case PHP: @@ -64,15 +67,9 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco case ROL: case ROR: case ASR: - case ENT: - address.u64 = cpu->pc[thread]; - ++cpu->pc[thread]; - break; - default: - address.u64 = cpu->pc[thread]; - cpu->pc[thread]+=(1 << (prefix >> 4)); - case TXS: - break; + case ENT: ++cpu->pc[thread]; break; + default : cpu->pc[thread]+=(1 << (prefix >> 4)); + case TXS: break; } break; case ZM: @@ -181,7 +178,7 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco return address.u64; } -inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = cpu->a[thread]+value+getflag(C); setflag(sum == 0, Z); setflag((sum >> 63), N); @@ -189,7 +186,7 @@ inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { setflag((sum < value), C); cpu->a[thread] = sum; } -inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = cpu->a[thread]-value-!getflag(C); setflag(sum == 0, Z); setflag(sum >> 63, N); @@ -198,7 +195,7 @@ inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] = sum; } -inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread) { +static inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread) { uint64_t reg; switch (opcode) { case TBA: cpu->a[thread] = cpu->b[thread]; reg = cpu->a[thread]; break; @@ -222,21 +219,14 @@ inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t pr setflag(reg >> 63, N); } -inline void push(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { +static inline void push(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) { union { uint64_t reg; uint8_t byte[8]; } r; - r.reg = 0; + r.reg = reg; uint8_t size = (value > 0) ? value-1 : 0; uint8_t tmp = (size <= 7) ? size : 7; - switch (opcode) { - case PHA: r.reg = cpu->a[thread]; break; - case PHB: r.reg = cpu->b[thread]; break; - case PHX: r.reg = cpu->x[thread]; break; - case PHY: r.reg = cpu->y[thread]; break; - case PHP: r.reg = cpu->ps.u64; break; - } /* Unroll Loop by implementing Duff's Device. */ switch (tmp) { case 7: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[7];cpu->sp[thread]--; @@ -250,7 +240,7 @@ inline void push(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread } } -inline void pull(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { +static inline uint64_t pull(struct sux *cpu, uint64_t value, uint8_t thread) { union { uint64_t reg; uint8_t byte[8]; @@ -270,32 +260,26 @@ inline void pull(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread case 2: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; case 1: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; } - switch (opcode) { - case PLA: cpu->a[thread] = r.reg; break; - case PLB: cpu->b[thread] = r.reg; break; - case PLX: cpu->x[thread] = r.reg; break; - case PLY: cpu->y[thread] = r.reg; break; - case PLP: cpu->ps.u64 = r.reg; break; - } + return r.reg; } -inline void and(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void and(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] &= value; setflag(cpu->a[thread] == 0, Z); setflag(cpu->a[thread] >> 63, N); } -inline void or(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void or(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] |= value; setflag(cpu->a[thread] == 0, Z); setflag(cpu->a[thread] >> 63, N); } -inline void xor(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void xor(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] ^= value; setflag(cpu->a[thread] == 0, Z); setflag(cpu->a[thread] >> 63, N); } -inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = (value < 64) ? cpu->a[thread] << value : 0; setflag(sum == 0, Z); setflag(sum >> 63, N); @@ -303,7 +287,7 @@ inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] = sum; } -inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = (value < 64) ? cpu->a[thread] >> value : 0; setflag(sum == 0, Z); setflag(sum >> 63, N); @@ -311,7 +295,7 @@ inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] = sum; } -inline void asr(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void asr(struct sux *cpu, uint64_t value, uint8_t thread) { uint8_t sign = cpu->a[thread] >> 63; uint64_t sum = (value < 64) ? (cpu->a[thread] >> value) | ((uint64_t)sign << 63) : 0; setflag(sum == 0, Z); @@ -320,7 +304,7 @@ inline void asr(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] = sum; } -inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = cpu->a[thread] << value; sum |= getflag(C); setflag(sum == 0, Z); @@ -329,7 +313,7 @@ inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) { cpu->a[thread] = sum; } -inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = cpu->a[thread] >> value; sum |= (uint64_t)getflag(C) << (uint64_t)(64-value); setflag(sum == 0, Z); @@ -337,7 +321,7 @@ inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) { setflag(cpu->a[thread] & 1, C); cpu->a[thread] = sum; } -inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) { +static inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t sum = cpu->a[thread]*value; cpu->a[thread] = sum; setflag(sum == 0, Z); @@ -345,7 +329,7 @@ inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) { setflag(!((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); } -inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { +static inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { uint64_t sum = cpu->a[thread]/value; if (opcode != DAB) { cpu->b[thread] = cpu->a[thread] % value; @@ -357,40 +341,7 @@ inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread setflag(sum == 0, Z); setflag((sum >> 63), N); } -inline void cmp(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { - uint64_t reg; - switch (opcode) { - case CPB: - case CPB_AB: - case CPB_Z: - case CPB_IN: - case CPB_IX: - case CPB_IY: - reg = cpu->b[thread]; - break; - case CMP: - case CAB: - case CMP_AB: - case CMP_Z: - case CMP_IN: - case CMP_IX: - case CMP_IY: - reg = cpu->a[thread]; - break; - case CPY: - case CPY_AB: - case CPY_Z: - case CPY_IN: - reg = cpu->y[thread]; - break; - - case CPX: - case CPX_AB: - case CPX_Z: - case CPX_IN: - reg = cpu->x[thread]; - break; - } +static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) { uint64_t sum = reg-value; setflag(sum >> 63, N); setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V); @@ -398,46 +349,20 @@ inline void cmp(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) setflag(reg >= value, C); } -inline void incr(struct sux *cpu, uint8_t opcode, uint8_t thread) { - uint64_t reg; - switch (opcode) { - case INC: cpu->a[thread]+=1; reg = cpu->a[thread]; break; - case INB: cpu->b[thread]+=1; reg = cpu->b[thread]; break; - case INY: cpu->y[thread]+=1; reg = cpu->y[thread]; break; - case INX: cpu->x[thread]+=1; reg = cpu->x[thread]; break; - } - setflag(reg == 0, Z); - setflag(reg >> 63, N); -} - -inline void decr(struct sux *cpu, uint8_t opcode, uint8_t thread) { - uint64_t reg; - switch (opcode) { - case DEC: cpu->a[thread]-=1; reg = cpu->a[thread]; break; - case DEB: cpu->b[thread]-=1; reg = cpu->b[thread]; break; - case DEY: cpu->y[thread]-=1; reg = cpu->y[thread]; break; - case DEX: cpu->x[thread]-=1; reg = cpu->x[thread]; break; +/* Increment, or Decrement register. */ +static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t thread) { + if (inc) { + reg++; + } else { + reg--; } setflag(reg == 0, Z); setflag(reg >> 63, N); + return reg; } -inline void incm(struct sux *cpu, uint64_t address, uint8_t thread) { - addr[address]++; - setflag(addr[address] == 0, Z); - setflag(addr[address] >> 7, N); -} - -inline void decm(struct sux *cpu, uint64_t address, uint8_t thread) { - addr[address]--; - setflag(addr[address] == 0, Z); - setflag(addr[address] >> 7, N); -} - -inline void load(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread) { - if (address == CTRL_ADDR) { - io(address, esc); - } +/* Increment, or Decrement memory. */ +static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) { union reg value; value.u64 = 0; /* Unroll Loop by implementing Duff's Device. */ @@ -454,91 +379,61 @@ inline void load(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode case 2: value.u8[1] = addr[address+1]; } - switch (opcode) { - case LDB: - case LDB_AB: - case LDB_Z: - case LDB_ZX: - case LDB_ZY: - case LDB_IN: - case LDB_IX: - case LDB_IY: - cpu->b[thread] = value.u64; - break; - case LDA: - case LDA_AB: - case LDA_Z: - case LDA_ZX: - case LDA_ZY: - case LDA_IN: - case LDA_IX: - case LDA_IY: - cpu->a[thread] = value.u64; - break; - case LDY: - case LDY_AB: - case LDY_Z: - case LDY_ZX: - case LDY_IN: - cpu->y[thread] = value.u64; - break; + if (inc) { + value.u64++; + } else { + value.u64--; + } + setflag(value.u64 == 0, Z); + setflag(value.u64 >> 7, N); + addr[address] = value.u8[0]; + io(address, 0); + switch (1 << (prefix >> 4)) { + case 8: + addr[address+7] = value.u8[7]; + addr[address+6] = value.u8[6]; + addr[address+5] = value.u8[5]; + addr[address+4] = value.u8[4]; + case 4: + addr[address+3] = value.u8[3]; + addr[address+2] = value.u8[2]; + case 2: + addr[address+1] = value.u8[1]; + } +} - case LDX: - case LDX_AB: - case LDX_Z: - case LDX_ZY: - case LDX_IN: - cpu->x[thread] = value.u64; - break; +static inline uint64_t load(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { + io(address, 1); + union reg value; + value.u64 = reg; + /* Unroll Loop by implementing Duff's Device. */ + value.u8[0] = addr[address]; + switch (1 << (prefix >> 4)) { + case 8: + value.u8[7] = addr[address+7]; + value.u8[6] = addr[address+6]; + value.u8[5] = addr[address+5]; + value.u8[4] = addr[address+4]; + case 4: + value.u8[3] = addr[address+3]; + value.u8[2] = addr[address+2]; + case 2: + value.u8[1] = addr[address+1]; } setflag(value.u64 == 0, Z); setflag(value.u64 >> 63, N); + return value.u64; } -inline void store(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread) { +static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { union reg value; - value.u64 = 0; - switch (opcode) { - case STB: - case STB_Z: - case STB_ZX: - case STB_ZY: - case STB_IN: - case STB_IX: - case STB_IY: - value.u64 = cpu->b[thread]; - break; - case STA: - case STA_Z: - case STA_ZX: - case STA_ZY: - case STA_IN: - case STA_IX: - case STA_IY: - value.u64 = cpu->a[thread]; - break; - case STY: - case STY_Z: - case STY_ZX: - case STY_IN: - value.u64 = cpu->y[thread]; - break; - - case STX: - case STX_Z: - case STX_ZY: - case STX_IN: - value.u64 = cpu->x[thread]; - break; - } + value.u64 = reg; addr[address] = value.u8[0]; #if (IO || debug) && !branch #if keypoll pthread_mutex_lock(&mutex); #endif - if (address != CTRL_ADDR && address == TX_ADDR) { - io(address, esc); - } + io(address, 0); #if keypoll pthread_mutex_unlock(&mutex); #endif |