initial commit
[metatoy] / src / libc / string_s.asm
1 ; pcboot - bootable PC demo/game kernel
2 ; Copyright (C) 2018  John Tsiombikas <nuclear@member.fsf.org>
3
4 ; This program is free software: you can redistribute it and/or modify
5 ; it under the terms of the GNU General Public License as published by
6 ; the Free Software Foundation, either version 3 of the License, or
7 ; (at your option) any later version.
8
9 ; This program is distributed in the hope that it will be useful,
10 ; but WITHOUT ANY WARRANTY, without even the implied warranty of
11 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ; GNU General Public License for more details.
13
14 ; You should have received a copy of the GNU General Public License
15 ; along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17         ; standard C memset
18         global memset
19 memset:
20         push ebp
21         mov ebp, esp
22         push edi
23
24         mov edi, [ebp + 8]
25         push edi
26         mov al, [ebp + 12]
27         mov ah, al
28         mov cx, ax
29         shl eax, 16
30         mov ax, cx
31         mov ecx, [ebp + 16]
32
33         test ecx, ecx
34         jz .done
35
36         ; write 1, 2, or 3 times until we reache a 32bit-aligned dest address
37         mov edx, edi
38         and edx, 3
39         jz .main
40         jmp [.pre_tab + ecx * 4]
41
42 .pre_tab dd .main, .pre1, .pre2, .pre3
43 .pre3:  stosb
44         dec ecx
45 .pre2:  stosb
46         dec ecx
47 .pre1:  stosb
48         dec ecx
49         jz .done
50
51         ; edi is 32bit-aligned here, write ecx>>2 32bit values
52 .main:
53         push ecx
54         shr ecx, 2
55         rep stosd
56         pop ecx
57
58         ; write any trailing bytes
59         and ecx, 3
60         jmp [.post_tab + ecx * 4]
61
62 .post_tab dd .done, .post1, .post2, .post3
63 .post3: stosb
64 .post2: stosb
65 .post1: stosb
66
67 .done:  pop eax
68         pop edi
69         pop ebp
70         ret
71
72
73         ; same as memset but copies 16bit values, and the count is the number
74         ; of 16bit values to copy, not bytes.
75         global memset16
76 memset16:
77         push ebp
78         mov ebp, esp
79         push edi
80
81         mov edi, [ebp + 8]
82         push edi
83         mov ax, [ebp + 12]
84         shl eax, 16
85         mov ax, [ebp + 12]
86         mov ecx, [ebp + 16]
87
88         test ecx, ecx
89         jz .done
90
91         mov edx, edi
92         and edx, 3
93         jz .main
94         jmp [.pre_tab + edx * 4]
95
96 .pre_tab dd .main, .pre1, .pre2, .pre3
97 .pre3:
98         ; unaligned by +3:
99         ; same as next one, but jump to ms16main instead of falling through
100         mov [edi], al
101         mov [edi + ecx * 2 - 1], ah
102         rol eax, 8
103         inc edi
104         dec ecx
105         jz .done
106         jmp .main
107 .pre1:
108         ; unaligned by +1:
109         ; - write low byte at edi
110         ; - write high byte at the end
111         ; - rotate by 8 for the rest
112         ; - decrement ecx
113         mov [edi], al
114         mov [edi + ecx * 2 - 1], ah
115         rol eax, 8
116         inc edi
117         dec ecx
118         jz .done
119 .pre2:
120         ; unaligned by +2
121         stosw
122         dec ecx
123         jz .done
124
125 .main:
126         push ecx
127         shr ecx, 1
128         rep stosd
129         pop ecx
130
131         and ecx, 1
132         jz .done
133         stosw
134 .done:
135         pop eax
136         pop edi
137         pop ebp
138         ret
139
140
141         ; standard C memcpy
142         global memcpy
143 memcpy:
144         push ebp
145         mov ebp, esp
146         push edi
147         push esi
148
149         mov edi, [ebp + 8]
150         mov esi, [ebp + 12]
151         mov ecx, [ebp + 16]
152
153         test ecx, ecx
154         jz .done
155
156         mov edx, ecx
157         shr ecx, 2
158         rep movsd
159
160         and edx, 3
161         jmp [.post_tab + edx * 4]
162
163 .post_tab dd .done, .post1, .post2, .post3
164 .post3: movsb
165 .post2: movsb
166 .post1: movsb
167
168 .done:
169         pop esi
170         pop edi
171         pop ebp
172         ret
173
174 ; vi:set ts=8 sts=8 sw=8 ft=nasm: