summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-10-04 18:22:00 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-10-04 18:22:00 -0400
commitca8e2f93acc794b00464c5513956bd84de258913 (patch)
tree83153822fdea777bd11a8254c0e4bd87fe1d8350
parent784ff59108b887e246b0f33ff696dfd981659ab2 (diff)
- Added support for reading, and writing outside the
emulator's memory. All reads outside of the emulator's memory give back $/0xFF bytes, while all writes outside of the emulator's memory are ignored. - Implemented malloc(), and free() in the SuB Suite. In order to do this, I had to add support for a heap, which I did by reserving the first 3 banks of the address space (the first 192K), and by adding a routine that finds the end of the RAM. In this case, I set the starting address for the routine at bank 3 (bank 4 with one indexing), but, the routine's starting address isn't hardcoded, and thus, any starting address can be passed as an argument. The routine uses the fact that we can now read/write outside the emulator's memory, and also uses the fact that writing outside the emulator's memory will be ignored, and that reading outside the emulator's memory will always read $/0xFF bytes, and uses that to signal that it's reached the end of the RAM. - Added a test program for getting the size of RAM starting at address $/0x20000.
-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