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