summaryrefslogtreecommitdiff
path: root/programs/sub-suite/libc.s
blob: d13d983e614686802d4f1221ab2ca9c8dff93ae9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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.
	adc b		; 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.
	cmp b		; 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.