diff options
Diffstat (limited to 'programs/sub-suite/libc.s')
-rw-r--r-- | programs/sub-suite/libc.s | 201 |
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. |