diff options
-rw-r--r-- | disasm.c | 15 | ||||
-rw-r--r-- | lexer.c | 4 | ||||
-rw-r--r-- | programs/sub-suite/declare.s | 88 | ||||
-rw-r--r-- | programs/sub-suite/lexer.s | 22 | ||||
-rw-r--r-- | programs/sub-suite/libc.s | 355 | ||||
-rw-r--r-- | programs/sub-suite/subasm.s | 2 | ||||
-rw-r--r-- | programs/sub-suite/subeditor.s | 62 | ||||
-rw-r--r-- | programs/sub-suite/subsuite.s | 2 | ||||
-rw-r--r-- | programs/sub-suite/utils.s | 30 | ||||
-rw-r--r-- | sux.c | 30 | ||||
-rw-r--r-- | sux.h | 88 | ||||
-rw-r--r-- | test/getramsize.s | 45 |
12 files changed, 607 insertions, 136 deletions
@@ -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); }*/ @@ -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. @@ -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); @@ -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(®, addr+address, size+1); + #endif } else { - return *(uint64_t *)(addr+address); + return (size < 7) ? (reg & ~mask) | (mask) : mask; } - #else - return *(uint64_t *)memcopy(®, 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 |