summaryrefslogtreecommitdiff
path: root/programs/sub-suite/libc.s
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-08-08 10:28:36 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-08-08 10:28:36 -0400
commit1ec19679b3db209429b0897f6ccda6d09d018a70 (patch)
treeef17e28b388a04fadeb14982a5332eb647981d8b /programs/sub-suite/libc.s
parent39081609ec4f1f5d96e15e346eecd09ca2cc9f41 (diff)
Did a ton of stuff.
- Changed the file structure of the SuB Suite, so that all variable declarations, symbols, and constants are in a single file. - Moved the C library functionss into a separate file, and made them use stack frames. - Added support for using the emulator's assembler for realtime debugging, to enter it, get in to stepping mode by pressing Ctrl+s, press any other key, then press F1, The reason for having to press some other key before pressing F1 is because it only allows entering the assembler when the keyboard is not ready. - Added the ".res" directive to the emulator's assembler, the ".res" directive tells the assembler to reserve however many bytes specified by the operand. - Fixed some bugs in the emulator's assembler.
Diffstat (limited to 'programs/sub-suite/libc.s')
-rw-r--r--programs/sub-suite/libc.s201
1 files changed, 201 insertions, 0 deletions
diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s
new file mode 100644
index 0000000..bd55f9c
--- /dev/null
+++ b/programs/sub-suite/libc.s
@@ -0,0 +1,201 @@
+; Simple libc implementation for the SuB Suite
+
+strtoull:
+ phy.w ; 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.
+ pha ; Preserve the character.
+ jsr isdigit ; Is this character, a digit?
+ pla ; Get the character back.
+ bne @digit ; Yes, so extract the value from it.
+ jsr tolower ; No, so convert the character to lowercase.
+ pha ; Preserve the character.
+ jsr islower ; Is this an alphabetical character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@alpha:
+ sec ; Yes, so prepare for a non borrowing subtract.
+ sbc #'a'-10 ; Get the numeric value from this digit.
+ bra @chkbase ; Check if the value matches the base.
+@digit:
+ 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?
+ 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.
+ clc ; Prepare for a non carrying add.
+ aab ; Add the digit value to the total value.
+ sta.q sp+1 ; Place the value in the value buffer.
+ iny ; Increment the string index.
+ and #0 ; Reset A.
+ bra @loop ; Keep looping.
+@end:
+ pla.q ; Get the value buffer back.
+ ply.w ; Get Y back.
+ ldb #0 ; Reset B.
+ rts ; End of strtoull.
+
+
+strlen:
+ 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.
+@loop:
+ lda (sp+3), 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.
+ rts ; End of strlen.
+
+
+strcmp:
+ ldb #0 ; Reset B.
+ tba ; Reset A.
+ phy.w ; 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?
+ 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?
+ bne cmpr ; No, so check if we're too short, or too long.
+ iny ; Yes, so increment the index.
+ bra @loop ; Keep looping.
+
+strccmp:
+strcasecmp:
+ ldb #0 ; Reset B.
+ tba ; Reset A.
+ phy.w ; 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?
+ 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.
+ jsr tolower ; Convert the character of string 2 to lowercase.
+ tab ; Place it in B.
+ pla ; Get the character of string 1 back.
+ cab ; Is the character of both strings, the same?
+ plb ; Get the islong flag back.
+ bne cmpr ; No, so check if we're too short, or too long.
+ iny ; Yes, so increment the index.
+ bra @loop ; Keep looping.
+
+cmpr:
+ lda (sp+11), 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?
+ beq @short ; Yes, so return -1.
+@islong:
+ cpb #1 ; Is the islong flag true?
+ bne @equ ; No, so return 0.
+@long:
+ lda #1 ; Yes, so return 1.
+ bra @end ; We are done.
+@equ:
+ lda #0 ; Return 0.
+ bra @end ; We are done.
+@short:
+ lda #$FF ; Return -1.
+@end:
+ ply.w ; Get the preserved value back.
+ rts ; End of cmpr.
+
+
+isdigit:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'0' ; Subtract $30 from the passed character.
+ and #$FF ; Make sure that we have only one byte.
+ cmp #10 ; Is the subtracted value, less than 10?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isdigit.
+
+isxdigit:
+ pha ; Preserve the character.
+ jsr isdigit ; Is this character, a decimal digit?
+ pla ; Get the character back.
+ bne @true ; Yes, so return true.
+@alpha:
+ sec ; No, so prepare for a non carrying subtract.
+ ora #$20 ; Convert it to lowercase.
+ sbc #'a' ; Subtract $61 from the character.
+ and #$FF ; Make sure that we have only one byte.
+ cmp #6 ; Is the subtracted value, less than 6?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isxdigit.
+
+
+isupper:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'A' ; Subtract $41 from the passed character.
+ bra isletter ; Check if it's less than 26.
+islower:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'a' ; Subtract $61 from the passed character.
+isletter:
+ and #$FF ; Make sure that we have only one byte.
+ cmp #26 ; Is the subtracted value, less than 26?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isletter.
+
+
+tolower:
+ pha ; Preserve the character.
+ jsr isupper ; Is this character, an uppercase character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@lower:
+ ora #$20 ; Yes, so convert it to lowercase.
+@end:
+ rts ; End of tolower.
+
+
+toupper:
+ pha ; Preserve the character.
+ jsr islower ; Is this character, a lowercase character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@upper:
+ and #$5F ; Yes, so convert it to uppercase.
+@end:
+ rts ; End of toupper.