1 /* $OpenBSD: goodfreg.c,v 1.2 2003/07/12 04:23:16 jason Exp $ */
2
3 /*
4 * Copyright (c) 2003 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <err.h>
32 #include "fpregs.h"
33
34 struct fpquad {
35 u_int32_t x1;
36 u_int32_t x2;
37 u_int32_t x3;
38 u_int32_t x4;
39 };
40
41 void asm_ldq_f0(struct fpquad *);
42 void asm_ldq_f4(struct fpquad *);
43 void asm_ldq_f8(struct fpquad *);
44 void asm_ldq_f12(struct fpquad *);
45 void asm_ldq_f16(struct fpquad *);
46 void asm_ldq_f20(struct fpquad *);
47 void asm_ldq_f24(struct fpquad *);
48 void asm_ldq_f28(struct fpquad *);
49 void asm_ldq_f32(struct fpquad *);
50 void asm_ldq_f36(struct fpquad *);
51 void asm_ldq_f40(struct fpquad *);
52 void asm_ldq_f44(struct fpquad *);
53 void asm_ldq_f48(struct fpquad *);
54 void asm_ldq_f52(struct fpquad *);
55 void asm_ldq_f56(struct fpquad *);
56 void asm_ldq_f60(struct fpquad *);
57
58 void asm_stq_f0(struct fpquad *);
59 void asm_stq_f4(struct fpquad *);
60 void asm_stq_f8(struct fpquad *);
61 void asm_stq_f12(struct fpquad *);
62 void asm_stq_f16(struct fpquad *);
63 void asm_stq_f20(struct fpquad *);
64 void asm_stq_f24(struct fpquad *);
65 void asm_stq_f28(struct fpquad *);
66 void asm_stq_f32(struct fpquad *);
67 void asm_stq_f36(struct fpquad *);
68 void asm_stq_f40(struct fpquad *);
69 void asm_stq_f44(struct fpquad *);
70 void asm_stq_f48(struct fpquad *);
71 void asm_stq_f52(struct fpquad *);
72 void asm_stq_f56(struct fpquad *);
73 void asm_stq_f60(struct fpquad *);
74
75 int compare_regs(union fpregs *, union fpregs *);
76 void dump_reg(union fpregs *);
77 void dump_regs(union fpregs *, union fpregs *, union fpregs *);
78 int compare_quads(struct fpquad *, struct fpquad *);
79 void check_saves(union fpregs *, union fpregs *, union fpregs *);
80 void c_stq(union fpregs *, int, struct fpquad *);
81 void c_ldq(union fpregs *, int, struct fpquad *);
82 void asm_ldq(int, struct fpquad *);
83 void asm_stq(int, struct fpquad *);
84 void check_reg(int, union fpregs *, union fpregs *, union fpregs *);
85 void check_regs(union fpregs *, union fpregs *, union fpregs *);
86 int main(void);
87
88 int
compare_regs(union fpregs * fr1,union fpregs * fr2)89 compare_regs(union fpregs *fr1, union fpregs *fr2)
90 {
91 return (memcmp(fr1, fr2, sizeof(*fr2)));
92 }
93
94 void
dump_reg(union fpregs * fr)95 dump_reg(union fpregs *fr)
96 {
97 int i;
98
99 for (i = 0; i < 64; i++) {
100 if ((i & 3) == 0)
101 printf("f%-2d:", i);
102 printf(" %08x", fr->f_reg32[i]);
103 if ((i & 3) == 3)
104 printf("\n");
105 }
106 }
107
108 void
dump_regs(union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)109 dump_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
110 {
111 printf("BEFORE ASM\n");
112 dump_reg(fr1);
113 printf("AFTER ASM\n");
114 dump_reg(fr2);
115 printf("MANUAL\n");
116 dump_reg(fr3);
117 }
118
119 int
compare_quads(struct fpquad * q1,struct fpquad * q2)120 compare_quads(struct fpquad *q1, struct fpquad *q2)
121 {
122 return (memcmp(q1, q2, sizeof(*q2)));
123 }
124
125 /*
126 * Verify that savefpregs, loadfpregs, and initfpregs actually seem to work.
127 */
128 void
check_saves(union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)129 check_saves(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
130 {
131 memset(fr1, 0x55, sizeof(*fr1));
132 memset(fr2, 0x55, sizeof(*fr2));
133 memset(fr3, 0x55, sizeof(*fr3));
134 loadfpregs(fr1);
135 if (compare_regs(fr1, fr2))
136 errx(1, "check_saves: loadfpregs1 differs");
137
138 savefpregs(fr2);
139 if (compare_regs(fr1, fr2) || compare_regs(fr2, fr3))
140 errx(1, "check_saves: savefpregs1 differs");
141
142 memset(fr1, 0xaa, sizeof(*fr1));
143 memset(fr2, 0xaa, sizeof(*fr2));
144 memset(fr3, 0xaa, sizeof(*fr3));
145 loadfpregs(fr1);
146 if (compare_regs(fr1, fr2))
147 errx(1, "check_saves: loadfpregs2 differs");
148
149 savefpregs(fr2);
150 if (compare_regs(fr1, fr2) || compare_regs(fr2, fr3))
151 errx(1, "check_saves: savefpregs2 differs");
152
153 memset(fr1, 0xff, sizeof(*fr1));
154 initfpregs(fr2);
155 if (compare_regs(fr1, fr2))
156 errx(1, "check_saves: initfpregs differs");
157 }
158
159 void
c_stq(union fpregs * frp,int freg,struct fpquad * q)160 c_stq(union fpregs *frp, int freg, struct fpquad *q)
161 {
162 q->x1 = frp->f_reg32[freg];
163 q->x2 = frp->f_reg32[freg + 1];
164 q->x3 = frp->f_reg32[freg + 2];
165 q->x4 = frp->f_reg32[freg + 3];
166 }
167
168 void
c_ldq(union fpregs * frp,int freg,struct fpquad * q)169 c_ldq(union fpregs *frp, int freg, struct fpquad *q)
170 {
171 frp->f_reg32[freg] = q->x1;
172 frp->f_reg32[freg + 1] = q->x2;
173 frp->f_reg32[freg + 2] = q->x3;
174 frp->f_reg32[freg + 3] = q->x4;
175 }
176
177 void
asm_ldq(int freg,struct fpquad * q)178 asm_ldq(int freg, struct fpquad *q)
179 {
180 switch (freg) {
181 case 0:
182 asm_ldq_f0(q);
183 break;
184 case 4:
185 asm_ldq_f4(q);
186 break;
187 case 8:
188 asm_ldq_f8(q);
189 break;
190 case 12:
191 asm_ldq_f12(q);
192 break;
193 case 16:
194 asm_ldq_f16(q);
195 break;
196 case 20:
197 asm_ldq_f20(q);
198 break;
199 case 24:
200 asm_ldq_f24(q);
201 break;
202 case 28:
203 asm_ldq_f28(q);
204 break;
205 case 32:
206 asm_ldq_f32(q);
207 break;
208 case 36:
209 asm_ldq_f36(q);
210 break;
211 case 40:
212 asm_ldq_f40(q);
213 break;
214 case 44:
215 asm_ldq_f44(q);
216 break;
217 case 48:
218 asm_ldq_f48(q);
219 break;
220 case 52:
221 asm_ldq_f52(q);
222 break;
223 case 56:
224 asm_ldq_f56(q);
225 break;
226 case 60:
227 asm_ldq_f60(q);
228 break;
229 default:
230 errx(1, "asm_ldq: bad freg %d", freg);
231 }
232 }
233
234 void
asm_stq(int freg,struct fpquad * q)235 asm_stq(int freg, struct fpquad *q)
236 {
237 switch (freg) {
238 case 0:
239 asm_stq_f0(q);
240 break;
241 case 4:
242 asm_stq_f4(q);
243 break;
244 case 8:
245 asm_stq_f8(q);
246 break;
247 case 12:
248 asm_stq_f12(q);
249 break;
250 case 16:
251 asm_stq_f16(q);
252 break;
253 case 20:
254 asm_stq_f20(q);
255 break;
256 case 24:
257 asm_stq_f24(q);
258 break;
259 case 28:
260 asm_stq_f28(q);
261 break;
262 case 32:
263 asm_stq_f32(q);
264 break;
265 case 36:
266 asm_stq_f36(q);
267 break;
268 case 40:
269 asm_stq_f40(q);
270 break;
271 case 44:
272 asm_stq_f44(q);
273 break;
274 case 48:
275 asm_stq_f48(q);
276 break;
277 case 52:
278 asm_stq_f52(q);
279 break;
280 case 56:
281 asm_stq_f56(q);
282 break;
283 case 60:
284 asm_stq_f60(q);
285 break;
286 default:
287 errx(1, "asm_stq: bad freg %d", freg);
288 }
289 }
290
291 void
check_reg(int freg,union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)292 check_reg(int freg, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
293 {
294 struct fpquad q1, q2, q3;
295
296 initfpregs(fr1);
297 initfpregs(fr2);
298 initfpregs(fr3);
299
300 loadfpregs(fr1);
301 q1.x1 = 0x01234567;
302 q1.x2 = 0x89abcdef;
303 q1.x3 = 0x55aa55aa;
304 q1.x4 = 0xa5a5a5a5;
305 asm_ldq(freg, &q1);
306 savefpregs(fr2);
307
308 c_ldq(fr3, freg, &q1);
309
310 if (compare_regs(fr2, fr3)) {
311 errx(1, "ldq: c/asm differ");
312 dump_regs(fr1, fr2, fr3);
313 }
314
315 q2.x1 = q2.x2 = q2.x3 = q2.x4 = 0;
316 q3.x1 = q3.x2 = q3.x3 = q3.x4 = 1;
317 asm_stq(freg, &q2);
318 c_stq(fr3, freg, &q3);
319
320 if (compare_quads(&q1, &q3))
321 errx(1, "c_stq %d differs...", freg);
322
323 if (compare_quads(&q1, &q2))
324 errx(1, "asm_stq %d differs...", freg);
325 }
326
327 void
check_regs(union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)328 check_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
329 {
330 int i;
331
332 for (i = 0; i < 16; i++)
333 check_reg(i * 4, fr1, fr2, fr3);
334 }
335
336 int
main()337 main()
338 {
339 union fpregs fr1, fr2, fr3;
340
341 check_saves(&fr1, &fr2, &fr3);
342 check_regs(&fr1, &fr2, &fr3);
343 return (0);
344 }
345