summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disasm.c15
-rw-r--r--lexer.c4
-rw-r--r--programs/sub-suite/declare.s88
-rw-r--r--programs/sub-suite/lexer.s22
-rw-r--r--programs/sub-suite/libc.s355
-rw-r--r--programs/sub-suite/subasm.s2
-rw-r--r--programs/sub-suite/subeditor.s62
-rw-r--r--programs/sub-suite/subsuite.s2
-rw-r--r--programs/sub-suite/utils.s30
-rw-r--r--sux.c30
-rw-r--r--sux.h88
-rw-r--r--test/getramsize.s45
12 files changed, 607 insertions, 136 deletions
diff --git a/disasm.c b/disasm.c
index 3fd0c11..da468dd 100644
--- a/disasm.c
+++ b/disasm.c
@@ -107,14 +107,15 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
if (subdbg) {
uint8_t ln = 33;
uint16_t line_idx = 0;
- uint32_t tmpad = 0x31000;
+ uint32_t tmpad = 0x20237;
int row, col;
uint8_t iscursor = 0;
union reg ptr;
ptr.u64 = 0;
uint32_t adr;
if (address == CTRL_ADDR || addr[STEP_ADDR]) {
- adr = 0x30000;
+ adr = read_value(cpu, 0, tmpad, 7, 0, 0);
+ tmpad += 8;
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: ");
@@ -125,10 +126,11 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
wmove(scr, ln++, 0);
uint8_t maxrow = 10;
int line_offset = (addr[0]-(maxrow-1) >= 0) ? addr[0]-(maxrow-1) : 0;
+ adr = read_value(cpu, 0, tmpad, 7, 0, 0);
for (uint8_t i = 0; i < maxrow; i++) {
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]);
+ wprintw(scr, "%02X", addr[adr+j+line_idx]);
if ((addr[0] == i+line_offset) && addr[1] == j) {
iscursor=1;
getyx(scr,row, col);
@@ -183,7 +185,7 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
wmove(scr, 31, 0);
wclrtoeol(scr);
- adr = 0x204CA;
+ adr = 0x200CA;
ptr.u64 = read_value(cpu, 0, adr, 3, 0, 0);
wprintw(scr, "t_id: $%02X", ptr.u8[0]);
wprintw(scr, ", t_type: $%02X", ptr.u8[1]);
@@ -209,7 +211,8 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
wprintw(scr, " d: $%02X,", addr[0x0D]);
wprintw(scr, " e: $%02X,", addr[0x0E]);
wprintw(scr, " f: $%02X", addr[0x0F]);
- tmpad = 0x33000;
+ tmpad += 8;
+ adr = read_value(cpu, 0, tmpad, 7, 0, 0);
line_idx = 0;
wprintw(scr, "cmd_buf:");
for (uint8_t i = 0; i < 1; i++) {
@@ -217,7 +220,7 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
wclrtoeol(scr);
line_idx = (i << 4)+(i << 6);
for (uint8_t j = 0; j < 0x50; j++) {
- wprintw(scr, "%02X", addr[tmpad+j+line_idx]);
+ wprintw(scr, "%02X", addr[adr+j+line_idx]);
}
wprintw(scr, ", i: %02X", i);
}*/
diff --git a/lexer.c b/lexer.c
index 31c205f..7cc9b87 100644
--- a/lexer.c
+++ b/lexer.c
@@ -824,7 +824,9 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
case TOK_CHAR:
case TOK_EXPR:
s->val = get_val(tok, address, 3, dbg);
- tok = skip_expr(tok, dbg);
+ if (tok->next) {
+ tok = skip_expr(tok, dbg);
+ }
break;
}
}
diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s
index 183d09d..6a8c90f 100644
--- a/programs/sub-suite/declare.s
+++ b/programs/sub-suite/declare.s
@@ -68,6 +68,19 @@
op .byte ; Base value used to get the actual opcode.
.endstruct
+; Free memory block struct, used by malloc.
+.struct fblk
+ size .qword ; Size of free memory block.
+ next .qword ; Pointer to next free block.
+ prev .qword ; Pointer to previous free block.
+.endstruct
+
+; Used memory block struct, used by malloc.
+.struct ublk
+ size .qword ; Size of used memory block.
+ start .qword ; Starting address of memory block.
+.endstruct
+
; Enums.
@@ -81,8 +94,17 @@ step = $110 ; Enables clock stepping, when set.
maxrow = 23 ; Screen's row count.
maxcol = 79 ; Screen's column count.
-MAX_SYM = $800 ; Max symbol size.
-OPNUM = 74 ; Instruction count.
+; Table sizes.
+SCRSIZE = $2000 ; Screen buffer size, in bytes.
+CMDSIZE = $400 ; Command buffer size, in bytes.
+LWSIZE = $1000 ; Linewrap table size, in bytes.
+
+; Magic number used by findramend.
+MAGIC = $AA
+
+; Heap related values.
+HEAPORG = $30000 ; Starting point of the heap.
+
; Directives.
DIR_ORG = 0 ; Origin.
@@ -164,23 +186,10 @@ 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.
-
+OPNUM = 74 ; Instruction count.
; RAM declarations.
-; Linewrap table.
-.org $30000
-bitabl:
- .res $1000
-
-; Screen buffer.
-buffer:
- .res $2000
-
-; Command buffer.
-cmd_buf:
- .res $400
-
; Screen variables.
.org 0
scr_row:
@@ -238,10 +247,7 @@ ptr3:
.res 8
-; Token table.
.org $20000
-tokline:
- .res $400
; Program Counter.
prg_cnt:
@@ -327,14 +333,54 @@ lex_type:
lexeme:
.res $100
+; Size of the heap.
+heapsize:
+ .res 8
+
+; Start of the heap.
+heapstr:
+ .res 8
+
+; End of the heap.
+heapend:
+ .res 8
+
+; Current top of the heap.
+heapptr:
+ .res 8
+
+; First heap entry.
+heapf:
+ .res 8
+
+; Last heap entry.
+heapl:
+ .res 8
+
+; Linewrap table.
+bitabl:
+ .res 8
+
+; Screen buffer.
+buffer:
+ .res 8
+
+; Command buffer.
+cmd_buf:
+ .res 8
+
+; Token table.
+tokline:
+ .res 8
+
; Symbol table.
symbol:
- .res $8000
+ .res 8
; Fixup table.
; Fixups are unresolved symbols.
fixup:
- .res $2000
+ .res 8
; ROM data declarations.
diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s
index 50bf21e..fc47f10 100644
--- a/programs/sub-suite/lexer.s
+++ b/programs/sub-suite/lexer.s
@@ -17,16 +17,16 @@ lex:
; pha ; Preserve the character.
; jsr isdigit ; Is this character a digit?
; pla ; Get the character back.
-@getline:
- ldb #1 ; Set the second pointer
- lda.q lline ; to the last line.
- jsr set_ptr ;
- ldy #ln.next ; Set the index to the next line pointer.
- lda.q (ptr2), y ; Get the next line.
- jsr set_ptr ; Set the second pointer to the next line.
- sta.q cline ; Make it the current line.
- and #0 ; Reset A.
- tay ; Reset Y.
+;@getline:
+; ldb #1 ; Set the second pointer
+; lda.q lline ; to the last line.
+; jsr set_ptr ;
+; ldy #ln.next ; Set the index to the next line pointer.
+; lda.q (ptr2), y ; Get the next line.
+; jsr set_ptr ; Set the second pointer to the next line.
+; sta.q cline ; Make it the current line.
+; and #0 ; Reset A.
+; tay ; Reset Y.
@loop:
ldy.w idx0 ; Get the string index.
lda (ptr), y ; Get a character from the line.
@@ -396,7 +396,7 @@ set_lexptr:
set_cmdbuf:
and #0 ; Reset A.
tab ; Reset B.
- lda.d #cmd_buf ; to the command buffer.
+ lda.q cmd_buf ; Set the first pointer to the command buffer.
jsr set_ptr ;
and #0 ; Reset A.
tab ; Reset B.
diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s
index d13d983..18c10db 100644
--- a/programs/sub-suite/libc.s
+++ b/programs/sub-suite/libc.s
@@ -1,12 +1,12 @@
; Simple libc implementation for the SuB Suite
strtoull:
- phy.w ; Preserve Y.
+ phy.q ; Preserve Y.
and #0 ; Reset A.
tay ; Reset Y.
pha.q ; Reset the value buffer.
@loop:
- lda (sp+20), y ; Get a character from the string.
+ lda (sp+26), y ; Get a character from the string.
pha ; Preserve the character.
jsr isdigit ; Is this character, a digit?
pla ; Get the character back.
@@ -24,12 +24,12 @@ strtoull:
sec ; Prepare for a non borrowing subtract.
sbc #'0' ; Get the numeric value from this digit.
@chkbase:
- cmp sp+19 ; Does the value match the base?
+ cmp sp+25 ; Does the value match the base?
bcs @end ; No, so we're done.
@addval:
tab ; Save the digit value.
lda.q sp+1 ; Get the value from the value buffer.
- mul sp+19 ; Multiply the value by the base.
+ mul sp+25 ; Multiply the value by the base.
clc ; Prepare for a non carrying add.
adc b ; Add the digit value to the total value.
sta.q sp+1 ; Place the value in the value buffer.
@@ -38,42 +38,39 @@ strtoull:
bra @loop ; Keep looping.
@end:
pla.q ; Get the value buffer back.
- ply.w ; Get Y back.
+ ply.q ; Get Y back.
ldb #0 ; Reset B.
rts ; End of strtoull.
strlen:
+ phy.q ; Preserve Y.
pha.q ; Set the temp variable to the argument.
- ldb #0 ; Reset B.
- tba ; Reset A.
- tax ; Reset X.
- phy.w ; Preserve Y.
- txy ; Reset Y.
+ and #0 ; Reset A.
+ tay ; Reset Y.
@loop:
- lda (sp+3), y ; Are we at the end of the string?
+ lda (sp+1), y ; Are we at the end of the string?
beq @end ; Yes, so we're done.
iny ; No, so increment the index.
bra @loop ; Keep looping.
@end:
- tyx ; Return the length in X.
- ply.w ; Get the preserved value back.
pla.q ; Get the argument back.
- txa ; Get the return value.
+ tya ; Get the return value.
+ ply.q ; Get the preserved value back.
rts ; End of strlen.
strcmp:
ldb #0 ; Reset B.
tba ; Reset A.
- phy.w ; Preserve Y.
+ phy.q ; Preserve Y.
tay ; Reset Y.
@loop:
ldb #0 ; Set the islong flag to false.
- lda (sp+19), y ; Are we at the end of the first string?
+ lda (sp+25), 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 (sp+11), y ; Is the character of both strings, the same?
+ cmp (sp+19), 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.
bra @loop ; Keep looping.
@@ -82,17 +79,17 @@ strccmp:
strcasecmp:
ldb #0 ; Reset B.
tba ; Reset A.
- phy.w ; Preserve Y.
+ phy.q ; Preserve Y.
tay ; Reset Y.
@loop:
ldb #0 ; Set the islong flag to false.
- lda (sp+19), y ; Are we at the end of the first string?
+ lda (sp+25), 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 ; Preserve the islong flag.
pha ; Preserve the converted character.
- lda (sp+13), y ; Get the character of the second string.
+ lda (sp+19), y ; Get the character of the second string.
jsr tolower ; Convert the character of string 2 to lowercase.
tab ; Place it in B.
pla ; Get the character of string 1 back.
@@ -103,10 +100,10 @@ strcasecmp:
bra @loop ; Keep looping.
cmpr:
- lda (sp+11), y ; Are we at the end of the second string?
+ lda (sp+17), y ; Are we at the end of the second string?
beq @islong ; Yes, so check the islong flag.
@isshort:
- lda (sp+19), y ; No, but are we at the end of the first string?
+ lda (sp+25), 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?
@@ -120,7 +117,7 @@ cmpr:
@short:
lda #$FF ; Return -1.
@end:
- ply.w ; Get the preserved value back.
+ ply.q ; Get the preserved value back.
rts ; End of cmpr.
@@ -199,3 +196,315 @@ toupper:
and #$5F ; Yes, so convert it to uppercase.
@end:
rts ; End of toupper.
+
+
+; malloc: Dynamically allocate memory.
+; Input: A = size in bytes to allocate.
+; Output: A = Pointer to allocated memory.
+; Caller preserved registers: none.
+; Callie preserved registers: Y.
+
+malloc:
+ phy.q ; Preserve Y.
+ pha.q ; Preserve the size.
+ and #0 ; Reset A.
+ tay ; Reset Y.
+ pha.q ; Create two more local variables.
+ pha.q ;
+ lda.q sp+17 ; Get the size.
+ ora.d sp+21 ; Is the size zero?
+ beq @end ; Yes, so we're done.
+ lda.q sp+17 ; No, so get back the size.
+ clc ; Prepare for a non carrying add.
+ adc #ublk ; Add the size of a used block struct, to the size.
+ sta.q sp+17 ; Set the actual size.
+ lda.q heapf ; Get the first heap entry.
+ sta.q sp+9 ; Save it in the second local variable.
+ bra @checkblk ; Check the block.
+@findfblk:
+ ldy #fblk.size ; Get the size of this free block.
+ lda.q (sp+9), y ;
+ sec ; Prepare for a non borrowing subtract.
+ sbc.q sp+17 ; Subtract the size of this free block, with the passed size.
+ bcs @blkfound ; The result is less than, or equal to the free size, so return the found block.
+ ldy #fblk.next ; Get the next free block.
+ lda.q (sp+9), y ;
+ sta.q sp+9 ; Set the current free block, to the next free block.
+@checkblk:
+ ora.d sp+13 ; Is the address of this block, zero?
+ bne @findfblk ; No, so keep looping.
+ lda.q heapptr ; Yes, so get the current top of the heap.
+ clc ; Prepare for a non carrying add.
+ adc.q sp+17 ; Add the top of the heap, with the passed size.
+ bcs @outofspace ; The result overflowed, so return zero.
+ cmp.q heapend ; Is the top of the heap, less than, or equal to the max heap size?
+ bcc @inctop ; Yes, so increase the current top of the heap.
+ beq @inctop ;
+@outofspace:
+ and #0 ; Return zero.
+ bra @end ; We are done.
+@inctop:
+ pha.q ; Preserve heapptr + size.
+ lda.q heapptr ; Get the previous top of the heap.
+ sta.q sp+17 ; Set the current free block to the previous top of the heap.
+ pla.q ; Restore heapptr + size.
+ sta.q heapptr ; Increment the current top of the heap by the passed size.
+ bra @setsize ; Set the size, and start address into the used space of the block.
+@blkfound:
+ bne @sliceblk ; The block is big enough to slice.
+ cmp #fblk ; Is the block big enough to slice?
+ bcs @sliceblk ; Yes, so slice the block.
+ ldy #fblk.prev ; No, so get the previous free block.
+ lda.q (sp+9), y ;
+ sta.q sp+1 ; Set the third local variable, to the previous free block.
+ ora.d sp+5 ; Is the previous block, set to zero?
+ beq @setheapf ; Yes, so set the first block.
+ ldy #fblk.next ; No, so get the next free block.
+ lda.q (sp+9), y ;
+ sta.q (sp+1), y ; Set the previous block's next block, to the next block.
+ bra @chknxtblk ; Check the next block.
+@setheapf:
+ lda.q (sp+9), y ; Get the next block.
+ sta.q heapf ; Set the first heap entry to it.
+@chknxtblk:
+ lda.q (sp+9), y ; Get the next free block.
+ sta.q sp+1 ; Set the third local variable to the next free block.
+ ora.d sp+5 ; Is the next block, zero?
+ beq @setheapl ; Yes, so set the least heap entry.
+ ldy #fblk.prev ; No, so get the current previous block.
+ lda.q (sp+9), y ;
+ sta.q (sp+1), y ; Set the next block's previous block to the current previous block.
+ bra @retptr ; Return the pointer.
+@setheapl:
+ ldy #fblk.prev ; Get the current previous block.
+ lda.q (sp+9), y ;
+ sta.q heapl ; Set the last heap entry to the current previous block.
+ bra @retptr ; Return the pointer.
+@sliceblk:
+ ldy #fblk.size ; Get the size of the current block.
+ lda.q (sp+9). y ;
+ sec ; Prepare for a non borrowing subtract.
+ sbc.q sp+17 ; Subtract the current block's size from the passed size.
+ sta.q (sp+9), y ; Set the current block's size to the subtracted size.
+ clc ; Prepare for a non carrying add.
+ adc.q sp+9 ; Add the current block's size to the pointer of the current block.
+ sta.q sp+9 ; Set the current block to the space above it (return value).
+@setsize:
+ ldy #ublk.size ; Start setting the used block's size, to the passed size.
+ lda.q sp+17 ; Get the passed size.
+ sta.q (sp+9), y ; Set the used block's size to the passed size.
+@retptr:
+ ldy #ublk.start ; Start setting the used block's starting address, to the used block.
+ lda.q sp+9 ; Get the used block.
+ sta.q (sp+9), y ; Set the used block's starting address, to the used block.
+ clc ; Prepare for a non carrying add.
+ adc #ublk ; Return the pointer to the real memory block.
+@end:
+ ply.q ; Clean up the stack frame.
+ ply.q ;
+ ply.q ;
+ ply.q ; Restore Y.
+ rts ; End of malloc.
+
+
+; free: Free allocated memory.
+; Input: A = Pointer to allocated memory.
+; Output: none.
+; Caller preserved registers: none.
+; Callie preserved registers: A, B, Y.
+
+free:
+ pha.q ; Preserve A.
+ phb.q ; Preserve B.
+ phy.q ; Preserve Y.
+ pha.q ; Push the pointer argument to the stack.
+ and #0 ; Reset A.
+ tay ; Reset Y.
+ pha.q ; Add 3 more local variables.
+ pha.q ;
+ pha.q ;
+ lda.q sp+25 ; Get the passed pointer.
+ ora.d sp+29 ; Is the passed pointer NULL?
+ bne @getrealblk ; No, so get the real block.
+ bra @end ; Yes, so we're done.
+@getrealblk:
+ lda.q sp+25 ; Get the passed pointer.
+ sec ; Prepare for a non borrowing subtract.
+ sbc #8 ; Move the passed pointer back by one.
+ sta.q sp+25 ; Set the first local variable to the start of the used block.
+ lda.q (sp+25) ; Get the real block address.
+ sta.q sp+25 ; Set the passed pointer to the start of the real block.
+ ldy #ublk.size ; Get the size of the real block.
+ lda.q (sp+25), y;
+ sta.q sp+17 ; Save the size of the real block.
+ clc ; Prepare for a non carrying add.
+ adc.q sp+25 ; Add the size of the real block with the start of the real block.
+ cmp.q heapptr ; Is this block on top of the heap?
+ bne @heapadd ; No, so add it to the free block list.
+@dectop:
+ lda.q sp+25 ; Get the block.
+ sta.q heapptr ; Set the top of the heap to it.
+@chklastblk:
+ lda.q heapl ; Get the last free list entry.
+ sta.q sp+17 ; Copy it into the second local variable.
+ ora.d sp+21 ; Is the free list empty?
+ beq @end ; Yes, so we're done.
+ lda.q sp+17 ; No, so Get the last free list entry.
+ ldy #fblk.size ; Get the size of the block.
+ lda.q (sp+17), y;
+ clc ; Prepare for a non carrying add.
+ adc.q sp+17 ; Add the size of the block, with the address of the block entry.
+ cmp.q heapptr ; Is the last block on top of the heap?
+ bne @end ; No, so we're done.
+@delblk:
+ lda.q sp+17 ; Yes, so remove the last block.
+ sta.q heapptr ;
+@correctblk:
+ ldy #fblk.prev ; Get the previous block.
+ lda.q (sp+17), y;
+ sta.q sp+25 ; Save the previous block for now.
+ sta.q heapl ; Set the last block to the previous block.
+ ora.d sp+29 ; Is the previous block non NULL?
+ bne @delnxtblk ; Yes, so delete the next block.
+ sta.q heapf ; No, so empty the free list.
+ bra @end ; We are done.
+@delnxtblk:
+ and #0 ; Reset A.
+ ldy #fblk.next ; Delete the next block.
+ sta.q (sp+25), y;
+@end:
+ pla.q ; Clean up the stack frame.
+ pla.q ;
+ pla.q ;
+ pla.q ;
+ ply.q ; Restore Y.
+ plb.q ; Restore B.
+ pla.q ; Restore A.
+ rts ; End of free.
+
+
+@heapadd:
+ lda.q heapf ; Get the first block.
+ sta.q sp+9 ; Copy it into the third local variable.
+ ora.d sp+13 ; Is the free list empty?
+ bne @srchflst ; No, so start searching the free list.
+@empty:
+ ldy #fblk.next ; Clear the next block.
+ sta.q (sp+25), y;
+ ldy #fblk.prev ; Clear the previous block.
+ sta.q (sp+25), y;
+ lda.q sp+25 ; Reset A.
+ sta.q heapf ; Clear the first block entry.
+ sta.q heapf ; Clear the last block entry.
+ bra @end ; We are done.
+@srchflst:
+ and #0 ; Reset A.
+ sta.q sp+1 ; Reset the left pointer.
+ ldy #fblk.next ; Setup for the loop.
+@loop:
+ lda.q sp+9 ; Get the right pointer.
+ cmp.q sp+25 ; Is the right pointer at, or below the current block?
+ beq @nextright ; Yes, so get the next right pointer.
+ bcs @chkrmerge ; No, so do the right block merge.
+@nextright:
+ sta.q sp+1 ; Set the left pointer, to the right pointer.
+ lda.q (sp+9), y ; Get the next right pointer.
+ sta.q sp+9 ; Set the current right pointer to the next right pointer.
+ ora.d sp+13 ; Is the next right pointer NULL?
+ bne @loop ; No, so keep looping.
+@st_lmerge2:
+ sta.q (sp+25), y; Clear the next block.
+ lda.q sp+25 ; Get the current block.
+ sta.q heapl ; Set the last free block entry to it.
+ bra @chklmerge2 ; Do the left block merge.
+@chkrmerge:
+ lda.q sp+25 ; Get the current block.
+ clc ; Prepare for a non carrying add.
+ adc.q sp+17 ; Add the size of the current block, to the current block.
+ cmp.q sp+9 ; Is the right pointer NULL?
+ bne @normerge ; No, so don't merge the right block.
+@rmerge:
+ ldy #fblk.size : Get the size of the right pointer.
+ lda.q sp+17 ; Get the size of the current block.
+ clc ; Prepare for a non carrying add.
+ adc.q (sp+9), y ; Add the size of the current block, with the size of the right pointer.
+ sta.q (sp+25), y; Set the size of the current block, to the new size.
+@rmerge2:
+ ldy #fblk.next ; Get the next right pointer.
+ lda.q (sp+9), y ;
+ sta.q (sp+25), y; Set the next block, to the next right pointer.
+ sta.q sp+17 ; Save the next block in the second local variable.
+ ora.d sp+21 ; Is the next block NULL?
+ beq @setheapl ; Yes, so set the last block.
+@setprev:
+ lda.q sp+25 ; Get the current block.
+ ldy #fblk.prev ; Set the previous block to the current block.
+ sta.q (sp+17), y;
+ bra @chklmerge ; Do the left block merge.
+@setheapl:
+ lda.q sp+25 ; Get the current block.
+ sta.q heapl ; Set the last block to the current block.
+ bra @chklmerge ; Do the left block merge.
+@normerge:
+ lda.q sp+9 ; Get the right pointer.
+ ldy #fblk.next ; Set the next block to the right pointer.
+ sta.q (sp+25), y;
+ lda.q sp+25 ; Get the current block.
+ ldy #fblk.prev ; Set the previous right pointer to the current block.
+ lda.q (sp+9), y ;
+@chklmerge:
+ lda.q sp+1 ; Get the left pointer.
+ ora.d sp+5 ; Is the left pointer NULL?
+ bne @chklmerge2 ; No, so keep checking.
+@newstart:
+ ldy #fblk.prev ; Clear the previous block.
+ sta.q (sp+25), y;
+ lda.q sp+25 ; Get the current block.
+ sta.q heapf ; Set the first block, to the current block.
+ bra @end2 ; We are done.
+@chklmerge2:
+ ldy #fblk.size ; Get the size of the left block.
+ lda.q (sp+1), y ;
+ clc ; Prepare for a non carrying add.
+ adc.q sp+1 ; Add the size of the left block, to the left pointer.
+ cmp.q sp+25 ; Is the left block adjacent?
+ bne @nolmerge ; No, so don't merge the left block.
+@lmerge:
+ lda.q (sp+1), y ; Get the size of the left block.
+ clc ; Prepare for a non carrying add.
+ ldb.q (sp+25), y; Get the size of the current block.
+ adc b ; Add the size of the left block, with the size of the current block.
+ sta.q (sp+1), y ; Set the size of the left block to the new size.
+@lmerge2:
+ ldy #fblk.next ; Get the next block.
+ lda.q (sp+25), y;
+ sta.q (sp+1), y ; Set the next left pointer, to the next block.
+ sta.q sp+17 ; Set the second local variable to the next block.
+ ora.d sp+21 ; Is the next left pointer NULL?
+ beq @newlast ; Yes, so set the last block.
+@lprev:
+ lda.q sp+1 ; Get the left pointer.
+ ldy #fblk.prev ; Set the next left pointer's previous pointer to the left pointer.
+ sta.q (sp+17), y;
+ bra @end2 ; We are done.
+@newlast:
+ lda.q sp+1 ; Get the left pointer.
+ sta.q heapl ; Set the last block, to the left pointer.
+ bra @end2 ; We are done.
+@nolmerge:
+ lda.q sp+25 ; Get the current block.
+ ldy #fblk.next ; Set the next left pointer, to the current block.
+ sta.q (sp+1), y ;
+@nolmerge2:
+ lda.q sp+1 ; Get the left pointer.
+ ldy #fblk.prev ; Set the previous block, to the left pointer.
+ sta.q (sp+25), y;
+@end2:
+ pla.q ; Clean up the stack frame.
+ pla.q ;
+ pla.q ;
+ pla.q ;
+ ply.q ; Restore Y.
+ plb.q ; Restore B.
+ pla.q ; Restore A.
+ rts ; End of free.
diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s
index 3957caa..0a3ee80 100644
--- a/programs/sub-suite/subasm.s
+++ b/programs/sub-suite/subasm.s
@@ -5,7 +5,7 @@
subasm:
ldb #0 ; Set the first pointer
- lda.d #cmd_buf ; to the command buffer.
+ lda.q cmd_buf ; to the command buffer.
jsr set_ptr ;
tba ; Reset A.
tax ; Reset X.
diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s
index fdf1e4b..7e124a2 100644
--- a/programs/sub-suite/subeditor.s
+++ b/programs/sub-suite/subeditor.s
@@ -10,10 +10,44 @@ reset:
txs ;
ldy #0 ; Reset Y.
tyx ; Reset X.
+ jsr init_heap ; Initialize the heap.
+ jsr init_tables ; Initialize the main tables.
jsr clr_scr ; Clear the screen.
jsr pnt_strt ; Print the starting message.
bra start ; Goto the start of the main program.
+
+init_heap:
+ and #0 ; Reset A.
+ lda.d #HEAPORG ; Get the heap's starting point.
+ sta.q heapptr ;
+ phb.q ; Preserve the value in B.
+ phx.q ; Preserve the value in X.
+ jsr findramend ; Find the end of the heap.
+ plb.q ; Restore the value in B.
+ plx.q ; Restore the value in X.
+ sta.q heapend ; Save the end of the heap.
+ and #0 ; Reset A.
+ rts ; End of init_heap.
+
+
+init_tables:
+ and #0 ; Reset A.
+ lda.w #SCRSIZE ; Allocate SCRSIZE bytes of RAM for the screen buffer.
+ jsr malloc ;
+ sta.q buffer ;
+ and #0 ; Reset A.
+ lda.w #CMDSIZE ; Allocate CMDSIZE bytes of RAM for the command buffer.
+ jsr malloc ;
+ sta.q cmd_buf ;
+ and #0 ; Reset A.
+ lda.w #LWSIZE ; Allocate LWSIZE bytes of RAM for the linewrap table.
+ jsr malloc ;
+ sta.q bitabl ;
+ and #0 ; Reset A.
+ rts ; End of init_tables.
+
+
clr_arr:
phb ; Preserve whatever was in B.
ldb #0 ; Clear B.
@@ -67,9 +101,9 @@ pnt_strt:
clr_cmd:
and #0 ; Reset A.
tay ; Reset Y.
- lda.w #$3FF ; Set the clear count to $3FF.
+ lda.w #CMDSIZE ; Set the clear count to CMDSIZE.
sta.w scr_ptr ;
- lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
+ lda.q cmd_buf ; Set the array to be cleared to the command buffer.
jsr clr_arr ; Clear the command buffer.
rts ; End of clr_cmd.
@@ -152,7 +186,7 @@ getbt0:
getbt1:
pha ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.d #bitabl ; Set the second pointer to the linewrap table.
+ lda.q bitabl ; Set the second pointer to the linewrap table.
jsr set_ptr ;
lsr #$10 ; Clear the Accumulator.
pla ; Get the return byte back.
@@ -168,7 +202,7 @@ getbt1:
clrbit:
pha ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.d #bitabl ; Set the second pointer to the linewrap table.
+ lda.q bitabl ; Set the second pointer to the linewrap table.
jsr set_ptr ;
and #0 ; Clear the Accumulator.
pla ; Get the return byte back.
@@ -188,7 +222,7 @@ bitout:
setbit:
pha ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.d #bitabl ; Set the second pointer to the linewrap table.
+ lda.q bitabl ; Set the second pointer to the linewrap table.
jsr set_ptr ;
and #0 ; Clear the Accumulator.
pla ; Get the return byte back.
@@ -283,10 +317,10 @@ cmd_cpy:
tay ; Place it into the index.
ldx.w #0 ; Reset the X register.
ldb #0 ; Make sure that set_ptr sets the first pointer.
- lda.d #buffer ; Set the first pointer to the start of the screen buffer.
+ lda.q buffer ; Set the first pointer to the start of the screen buffer.
jsr set_ptr ;
inb ; Make sure that set_ptr sets the second pointer.
- lda.d #cmd_buf ; Set the second pointer to the start of the command buffer.
+ lda.q cmd_buf ; Set the second pointer to the start of the command buffer.
jsr set_ptr ;
deb ; Set B back to zero.
tba ; Set the accumulator to zero.
@@ -344,7 +378,7 @@ findst:
fndend:
phb ; Save the contents of the B register.
ldb #0 ; Make sure that set_ptr sets the first pointer.
- lda.d #buffer ; Set the first pointer to the start of the screen buffer.
+ lda.q buffer ; Set the first pointer to the start of the screen buffer.
jsr set_ptr ;
tba ; Set the Accumulator to zero.
plb ; Restore the contents of the B register.
@@ -369,7 +403,7 @@ findend:
print_char:
sta rega ; Preserve the character.
ldb #2 ; Make sure that set_ptr sets the third pointer.
- lda.d #buffer ; Set the third pointer to the start of the screen buffer.
+ lda.q buffer ; Set the third pointer to the start of the screen buffer.
jsr set_ptr ;
deb ; Set B to one.
tba ; Reset A.
@@ -504,12 +538,14 @@ clr_scr:
sta scr_end ;
lda #0 ;
sta scr_str ;
- sta.q bitabl ;
- sta.q bitabl+8 ;
tay ;
- lda.w #$1FFF ; Set the clear count to $1FFF.
+ lda.w #LWSIZE ; Set the clear count to LWSIZE.
+ sta.w scr_ptr ;
+ lda.q bitabl ; Set the array to be cleared to the linewrap table.
+ jsr clr_arr ; Clear the linewrap table.
+ lda.w #SCRSIZE ; Set the clear count to SCRSIZE.
sta.w scr_ptr ;
- lda.d #buffer ; Set the array to be cleared to the screen buffer.
+ lda.q buffer ; Set the array to be cleared to the screen buffer.
jsr clr_arr ; Clear the screen buffer.
; tay ;
; lda.w #$3FF ; Set the clear count to $3FF.
diff --git a/programs/sub-suite/subsuite.s b/programs/sub-suite/subsuite.s
index d28b4f2..0cfad1e 100644
--- a/programs/sub-suite/subsuite.s
+++ b/programs/sub-suite/subsuite.s
@@ -17,7 +17,7 @@
.qword reset
a
;l a
-;.org reset
+;.org $8FA0
;v
;q
d
diff --git a/programs/sub-suite/utils.s b/programs/sub-suite/utils.s
index 7e7469c..21539eb 100644
--- a/programs/sub-suite/utils.s
+++ b/programs/sub-suite/utils.s
@@ -318,3 +318,33 @@ get_ctrlidx:
@del:
lda #2 ; Return 2.
rts ; End of get_ctrlidx.
+
+
+findramend:
+ pha.q ; Set the end of RAM pointer to the argument.
+ and #0 ; Reset A.
+ tab ; Reset B.
+ lda #MAGIC ; Set A to a magic number.
+@loop:
+ ldx (sp+1) ; Preserve the value.
+ sta (sp+1) ; Write the magic number to the current end of RAM.
+ cmp (sp+1) ; Is the value in RAM, the same as the magic number we wrote?
+ bne @moveback ; No, so move back until we find the last writable memory location.
+ stx (sp+1) ; Yes, so restore the previous value.
+ pha.q ; Preserve the magic number.
+ lda.q sp+9 ; Get the end of RAM pointer.
+ clc ; Prepare for a non carrying add.
+ adc.w #$4000 ; Increment the end of RAM pointer by 16K.
+ sta.q sp+9 ; Save the new end of RAM pointer.
+ pla.q ; Restore the magic number.
+ bra @loop ; Keep looping.
+@moveback:
+ dec.q sp+1 ; Decrement the end of RAM pointer.
+ ldx (sp+1) ; Preserve the value.
+ sta (sp+1) ; Write the magic number to the current end of RAM.
+ cmp (sp+1) ; Is the value in RAM, the same as the magic number we wrote?
+ bne @moveback ; No, so keep looping.
+ stx (sp+1) ; Yes, so restore the previous value.
+@end:
+ pla.q ; Restore the argument.
+ rts ; End of findramend.
diff --git a/sux.c b/sux.c
index f1b07df..daabdc2 100644
--- a/sux.c
+++ b/sux.c
@@ -218,17 +218,12 @@ void *run(void *args) {
pthread_mutex_unlock(&mutex);
#endif
#endif
- prefix = addr[cpu->pc];
- if ((prefix & 0x03) != 0x03) {
- prefix = 0;
- }
- cpu->pc += ((prefix & 0x03) == 0x03);
- opcode = addr[cpu->pc];
- ++cpu->pc;
+ uint16_t instr = read_value(cpu, 0, cpu->pc, 1, 1, 0);
+ uint8_t *tmp_inst = (uint8_t *)&instr;
+ prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0;
+ opcode = *tmp_inst;
+ cpu->pc += ((instr & 3) == 3)+1;
address.u64 = cpu->pc;
- #if getclk
- ++cpu->clk;
- #endif
uint8_t am = optype[opcode];
uint8_t rs = (prefix >> 4) & 3;
uint8_t size = (/***/1 << rs) - 1;
@@ -246,15 +241,15 @@ void *run(void *args) {
#endif
if (am != IMPL && am != BREG) {
address.u64 = get_addr(cpu, opcode, prefix, 1, 1, thread);
- if (address.u64 > mem_size-1) {
+ /*if (address.u64 > mem_size-1) {
addr[STEP_ADDR] = 1;
step = 1;
- }
+ }*/
if (isrw(opcode) && am != REL && isread(opcode)) {
value.u64 = read_value(cpu, 0, address.u64, size, 1, check_io);
}
}
- switch(opcode) {
+ switch (opcode) {
case CPS_IMP: /* Clear Processor Status. */
cpu->ps.u64 = 0;
break;
@@ -563,16 +558,15 @@ void *run(void *args) {
default:
break;
}
- /*if (cpu->pc <= 0xFF) {
- step = 1;
- wrefresh(scr);
- }*/
#if !IO
ins++;
#endif
#if !bench
if (step) {
- int c = 0;;
+ int c = 0;
+ #if debug
+ wrefresh(scr);
+ #endif
for (; step && c != 19 && !end; c = get_key(scr));
#if debug
wrefresh(scr);
diff --git a/sux.h b/sux.h
index 8dbc064..509a6bc 100644
--- a/sux.h
+++ b/sux.h
@@ -77,56 +77,62 @@ static void *memcopy(void *restrict dst, const void *restrict src, unsigned int
static inline uint64_t read_value(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) {
- #if (IO || debug) && !branch
- #if keypoll
- pthread_mutex_lock(&mutex);
- #endif
- if (check_io) {
- io(address, 1);
- }
- #if keypoll
- pthread_mutex_unlock(&mutex);
- #endif
- #endif
#if getclk
cpu->clk += inc_clk;
#endif
size = (size > 7) ? 7 : size;
- #if 1
- if (size < 7) {
- uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
- return (reg & ~mask) | (*(uint64_t *)(addr+address) & mask);
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ if (address < mem_size) {
+ #if (IO || debug) && !branch
+ #if keypoll
+ pthread_mutex_lock(&mutex);
+ #endif
+ if (check_io) {
+ io(address, 1);
+ }
+ #if keypoll
+ pthread_mutex_unlock(&mutex);
+ #endif
+ #endif
+ #if 1
+ if (size < 7) {
+ return (reg & ~mask) | (*(uint64_t *)(addr+address) & mask);
+ } else {
+ return *(uint64_t *)(addr+address);
+ }
+ #else
+ return *(uint64_t *)memcopy(&reg, addr+address, size+1);
+ #endif
} else {
- return *(uint64_t *)(addr+address);
+ return (size < 7) ? (reg & ~mask) | (mask) : mask;
}
- #else
- return *(uint64_t *)memcopy(&reg, addr+address, size+1);
- #endif
}
static inline void write_value(struct sux *cpu, uint64_t value, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) {
- size = (size > 7) ? 7 : size;
- #if 1
- if (size < 7) {
- uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
- *(uint64_t *)(addr+address) = (*(uint64_t *)(addr+address) & ~mask) | (value & mask);
- } else {
- *(uint64_t *)(addr+address) = value;
+ if (address < mem_size) {
+ size = (size > 7) ? 7 : size;
+ #if 1
+ if (size < 7) {
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ *(uint64_t *)(addr+address) = (*(uint64_t *)(addr+address) & ~mask) | (value & mask);
+ } else {
+ *(uint64_t *)(addr+address) = value;
+ }
+ #else
+ memcopy(addr+address, &value, size+1);
+ #endif
+ #if (IO || debug) && !branch
+ #if keypoll
+ pthread_mutex_lock(&mutex);
+ #endif
+ if (check_io) {
+ io(address, 0);
+ }
+ #if keypoll
+ pthread_mutex_unlock(&mutex);
+ #endif
+ #endif
}
- #else
- memcopy(addr+address, &value, size+1);
- #endif
- #if (IO || debug) && !branch
- #if keypoll
- pthread_mutex_lock(&mutex);
- #endif
- if (check_io) {
- io(address, 0);
- }
- #if keypoll
- pthread_mutex_unlock(&mutex);
- #endif
- #endif
#if getclk
cpu->clk += inc_clk;
#endif
@@ -276,7 +282,7 @@ static inline uint64_t sbc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_
setflag(sum == 0, Z);
setflag(sum >> 63, N);
setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V);
- setflag((sum > value), C);
+ setflag((sum < value), C);
return sum;
}
diff --git a/test/getramsize.s b/test/getramsize.s
new file mode 100644
index 0000000..cd2c69b
--- /dev/null
+++ b/test/getramsize.s
@@ -0,0 +1,45 @@
+; Find the end of RAM, and get the size of the RAM.
+; Written by mr b0nk 500 <b0nk@b0nk.xyz>.
+
+RAMSTART = $20000
+MAGIC = $AA
+
+.org 0
+; End of RAM.
+ptr1:
+ .res 8
+
+.org $8000
+reset:
+ cps ; Boilerplate reset code.
+ ldx.w #$FFFF ;
+ txs ;
+ and #0 ; Reset A.
+ tax ;
+start:
+ lda.d #RAMSTART ; Set the starting point of getramsize to the start of our RAM.
+ jsr getramsize ; Get the size of the RAM.
+ bra start ;
+
+
+getramsize:
+ sta.q ptr1 ; Set the end of RAM pointer to the argument.
+ and #0 ; Reset A.
+ tab ; Reset B.
+ lda #MAGIC ; Set A to a magic number.
+@loop:
+ sta (ptr1) ; Write the magic number to the current end of RAM.
+ cmp (ptr1) ; Is the value in RAM, the same as the magic number we wrote?
+ bne @end ; No, so we're done.
+ inc.q ptr1 ; Yes, so increment the end of RAM pointer.
+ inb ; Increment the byte count.
+ bra @loop ; Keep looping.
+@end:
+ inc $0110 ;
+ rts ; End of getramsize.
+
+.org $FFC0
+.qword reset
+
+a
+d