backported fixes from 256boss
[bootcensus] / src / libc / string_asm.s
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 %esp, %ebp
22         push %edi
23
24         mov 8(%ebp), %edi
25         push %edi
26         mov 12(%ebp), %al
27         mov %al, %ah
28         mov %ax, %cx
29         shl $16, %eax
30         mov %cx, %ax
31         mov 16(%ebp), %ecx
32
33         cmp $0, %ecx
34         jz msdone
35
36         # write 1, 2, or 3 times until we reache a 32bit-aligned dest address
37         mov %edi, %edx
38         and $3, %edx
39         jz msmain
40         jmp *mspre_tab(,%edx,4)
41
42 mspre_tab: .long msmain, mspre1, mspre2, mspre3
43 mspre3: stosb
44         dec %ecx
45 mspre2: stosb
46         dec %ecx
47 mspre1: stosb
48         dec %ecx
49         jz msdone
50
51         # edi is 32bit-aligned here, write ecx>>2 32bit values
52 msmain:
53         push %ecx
54         shr $2, %ecx
55         rep stosl
56         pop %ecx
57
58         # write any trailing bytes
59         and $3, %ecx
60         jmp *mspost_tab(,%ecx,4)
61
62 mspost_tab: .long msdone, mspost1, mspost2, mspost3
63 mspost3:stosb
64 mspost2:stosb
65 mspost1:stosb
66
67 msdone:
68         pop %eax
69         pop %edi
70         pop %ebp
71         ret
72
73
74         # same as memset but copies 16bit values, and the count is the number
75         # of 16bit values to copy, not bytes.
76         .global memset16
77 memset16:
78         push %ebp
79         mov %esp, %ebp
80         push %edi
81
82         mov 8(%ebp), %edi
83         push %edi
84         mov 12(%ebp), %ax
85         shl $16, %eax
86         mov 12(%ebp), %ax
87         mov 16(%ebp), %ecx
88
89         cmp $0, %ecx
90         jz ms16done
91
92         mov %edi, %edx
93         and $3, %edx
94         jz ms16main
95         jmp *ms16pre_tab(,%edx,4)
96
97 ms16pre_tab: .long ms16main, ms16pre1, ms16pre2, ms16pre3
98 ms16pre3:
99         # unaligned by +3:
100         # same as next one, but jump to ms16main instead of falling through
101         mov %al, (%edi)
102         mov %ah, -1(%edi,%ecx,2)
103         rol $8, %eax
104         inc %edi
105         dec %ecx
106         jz ms16done
107         jmp ms16main
108 ms16pre1:
109         # unaligned by +1:
110         # - write low byte at edi
111         # - write high byte at the end
112         # - rotate by 8 for the rest
113         # - decrement ecx
114         mov %al, (%edi)
115         mov %ah, -1(%edi,%ecx,2)
116         rol $8, %eax
117         inc %edi
118         dec %ecx
119         jz ms16done
120 ms16pre2:
121         # unaligned by +2
122         stosw
123         dec %ecx
124         jz ms16done
125
126 ms16main:
127         push %ecx
128         shr $1, %ecx
129         rep stosl
130         pop %ecx
131
132         and $1, %ecx
133         jz ms16done
134         stosw
135 ms16done:
136         pop %eax
137         pop %edi
138         pop %ebp
139         ret
140
141         # standard C memcpy
142         .global memcpy
143 memcpy:
144         push %ebp
145         mov %esp, %ebp
146         push %edi
147         push %esi
148
149         mov 8(%ebp), %edi
150         mov 12(%ebp), %esi
151         mov 16(%ebp), %ecx
152
153         cmp $0, %ecx
154         jz mcdone
155
156         mov %ecx, %edx
157         shr $2, %ecx
158         rep movsl
159
160         and $3, %edx
161         jmp *mcpost_tab(,%edx,4)
162
163 mcpost_tab: .long mcdone, mcpost1, mcpost2, mcpost3
164 mcpost3:movsb
165 mcpost2:movsb
166 mcpost1:movsb
167
168 mcdone:
169         pop %esi
170         pop %edi
171         pop %ebp
172         ret