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