summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-06-11 21:39:59 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-06-11 22:05:03 -0400
commit460832c13c9d476d71e626a0c42de4eeff3feb63 (patch)
treeb3e5ea55f704d7e1672504eca8e99ffabe9c558a
parent0bc02d48d100aff63e40132786a89123ac43ae48 (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--Makefile2
-rw-r--r--asmmon.c1
-rw-r--r--assemble.c2
-rw-r--r--io.c34
-rw-r--r--lexer.c6
-rw-r--r--opcode.c25
-rw-r--r--programs/lexer.s231
-rw-r--r--programs/subasm.s92
-rw-r--r--programs/subeditor.s20
-rw-r--r--programs/utils.s257
-rw-r--r--sux.c166
-rw-r--r--sux.h259
12 files changed, 747 insertions, 348 deletions
diff --git a/Makefile b/Makefile
index 406a735..0bf43f0 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/asmmon.c b/asmmon.c
index 585d443..9f1b511 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -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.");
diff --git a/assemble.c b/assemble.c
index 4d95c33..1ff88df 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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;
}
diff --git a/io.c b/io.c
index 9027da9..dc07d52 100644
--- a/io.c
+++ b/io.c
@@ -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;
diff --git a/lexer.c b/lexer.c
index 47109ca..df478b0 100644
--- a/lexer.c
+++ b/lexer.c
@@ -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.
diff --git a/sux.c b/sux.c
index 41fbb5a..84bab1c 100644
--- a/sux.c
+++ b/sux.c
@@ -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. */
diff --git a/sux.h b/sux.h
index 241362b..4678eb9 100644
--- a/sux.h
+++ b/sux.h
@@ -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