1 /*	$OpenBSD: asi.c,v 1.2 2003/07/12 07:09:25 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 
30 #include <machine/psl.h>
31 #include <machine/ctlreg.h>
32 
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <err.h>
38 #include <errno.h>
39 #include "fpregs.h"
40 
41 struct fpquad {
42         u_int32_t x1;
43         u_int32_t x2;
44         u_int32_t x3;
45         u_int32_t x4;
46 };
47 
48 int compare_regs(union fpregs *, union fpregs *);
49 void dump_reg(union fpregs *);
50 void dump_regs(union fpregs *, union fpregs *, union fpregs *);
51 int compare_quads(struct fpquad *, struct fpquad *);
52 void c_stqa_asi(int, union fpregs *, struct fpquad *);
53 void c_ldqa_asi(int, union fpregs *, struct fpquad *);
54 void asm_ldqa_asi(int, struct fpquad *);
55 void asm_stqa_asi(int, struct fpquad *);
56 void asm_ldqa_imm(int asi, struct fpquad *);
57 void asm_stqa_imm(int asi, struct fpquad *);
58 void asm_stqa_primary(struct fpquad *);
59 void asm_ldqa_primary(struct fpquad *);
60 void asm_stqa_secondary(struct fpquad *);
61 void asm_ldqa_secondary(struct fpquad *);
62 void asm_stqa_primary_nofault(struct fpquad *);
63 void asm_ldqa_primary_nofault(struct fpquad *);
64 void asm_stqa_secondary_nofault(struct fpquad *);
65 void asm_ldqa_secondary_nofault(struct fpquad *);
66 void asm_stqa_primary_little(struct fpquad *);
67 void asm_ldqa_primary_little(struct fpquad *);
68 void asm_stqa_secondary_little(struct fpquad *);
69 void asm_ldqa_secondary_little(struct fpquad *);
70 void asm_stqa_primary_nofault_little(struct fpquad *);
71 void asm_ldqa_primary_nofault_little(struct fpquad *);
72 void asm_stqa_secondary_nofault_little(struct fpquad *);
73 void asm_ldqa_secondary_nofault_little(struct fpquad *);
74 void check_asi(int, union fpregs *, union fpregs *, union fpregs *);
75 void check_asi_asi(int, union fpregs *, union fpregs *, union fpregs *);
76 void check_asi_imm(int, union fpregs *, union fpregs *, union fpregs *);
77 int main(int, char *[]);
78 
79 int
80 compare_regs(union fpregs *fr1, union fpregs *fr2)
81 {
82 	return (memcmp(fr1, fr2, sizeof(*fr2)));
83 }
84 
85 void
86 dump_reg(union fpregs *fr)
87 {
88 	int i;
89 
90 	for (i = 0; i < 64; i++) {
91 		if ((i & 3) == 0)
92 			printf("f%-2d:", i);
93 		printf(" %08x", fr->f_reg32[i]);
94 		if ((i & 3) == 3)
95 			printf("\n");
96 	}
97 }
98 
99 void
100 dump_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
101 {
102 	printf("BEFORE ASM\n");
103 	dump_reg(fr1);
104 	printf("AFTER ASM\n");
105 	dump_reg(fr2);
106 	printf("MANUAL\n");
107 	dump_reg(fr3);
108 }
109 
110 int
111 compare_quads(struct fpquad *q1, struct fpquad *q2)
112 {
113 	return (memcmp(q1, q2, sizeof(*q2)));
114 }
115 
116 void
117 c_stqa_asi(int asi, union fpregs *frp, struct fpquad *q)
118 {
119 	if (asi == ASI_PRIMARY ||
120 	    asi == ASI_PRIMARY_NOFAULT ||
121 	    asi == ASI_SECONDARY ||
122 	    asi == ASI_SECONDARY_NOFAULT) {
123 		q->x1 = frp->f_reg32[0];
124 		q->x2 = frp->f_reg32[0 + 1];
125 		q->x3 = frp->f_reg32[0 + 2];
126 		q->x4 = frp->f_reg32[0 + 3];
127 		return;
128 	}
129 	if (asi == ASI_PRIMARY_LITTLE ||
130 	    asi == ASI_PRIMARY_NOFAULT_LITTLE ||
131 	    asi == ASI_SECONDARY_LITTLE ||
132 	    asi == ASI_SECONDARY_NOFAULT_LITTLE) {
133 		q->x4 = htole32(frp->f_reg32[0]);
134 		q->x3 = htole32(frp->f_reg32[0 + 1]);
135 		q->x2 = htole32(frp->f_reg32[0 + 2]);
136 		q->x1 = htole32(frp->f_reg32[0 + 3]);
137 		return;
138 	}
139 	errx(1, "c_stqa_asi: bad asi %d", asi);
140 }
141 
142 void
143 c_ldqa_asi(int asi, union fpregs *frp, struct fpquad *q)
144 {
145 	if (asi == ASI_PRIMARY ||
146 	    asi == ASI_PRIMARY_NOFAULT ||
147 	    asi == ASI_SECONDARY ||
148 	    asi == ASI_SECONDARY_NOFAULT) {
149 		frp->f_reg32[0] = q->x1;
150 		frp->f_reg32[0 + 1] = q->x2;
151 		frp->f_reg32[0 + 2] = q->x3;
152 		frp->f_reg32[0 + 3] = q->x4;
153 		return;
154 	}
155 	if (asi == ASI_PRIMARY_LITTLE ||
156 	    asi == ASI_PRIMARY_NOFAULT_LITTLE ||
157 	    asi == ASI_SECONDARY_LITTLE ||
158 	    asi == ASI_SECONDARY_NOFAULT_LITTLE) {
159 		frp->f_reg32[0] = htole32(q->x4);
160 		frp->f_reg32[0 + 1] = htole32(q->x3);
161 		frp->f_reg32[0 + 2] = htole32(q->x2);
162 		frp->f_reg32[0 + 3] = htole32(q->x1);
163 		return;
164 	}
165 	errx(1, "c_ldqa_asi: bad asi %d", asi);
166 }
167 
168 void
169 asm_stqa_imm(int asi, struct fpquad *q)
170 {
171 	switch (asi) {
172 	case ASI_PRIMARY:
173 		asm_stqa_primary(q);
174 		break;
175 	case ASI_SECONDARY:
176 		asm_stqa_secondary(q);
177 		break;
178 	case ASI_PRIMARY_NOFAULT:
179 		asm_stqa_primary_nofault(q);
180 		break;
181 	case ASI_SECONDARY_NOFAULT:
182 		asm_stqa_secondary_nofault(q);
183 		break;
184 	case ASI_PRIMARY_LITTLE:
185 		asm_stqa_primary_little(q);
186 		break;
187 	case ASI_SECONDARY_LITTLE:
188 		asm_stqa_secondary_little(q);
189 		break;
190 	case ASI_PRIMARY_NOFAULT_LITTLE:
191 		asm_stqa_primary_nofault_little(q);
192 		break;
193 	case ASI_SECONDARY_NOFAULT_LITTLE:
194 		asm_stqa_secondary_nofault_little(q);
195 		break;
196 	default:
197 		errx(1, "asm_stqa_imm: bad asi %d", asi);
198 	}
199 }
200 
201 void
202 asm_ldqa_imm(int asi, struct fpquad *q)
203 {
204 	switch (asi) {
205 	case ASI_PRIMARY:
206 		asm_ldqa_primary(q);
207 		break;
208 	case ASI_SECONDARY:
209 		asm_ldqa_secondary(q);
210 		break;
211 	case ASI_PRIMARY_NOFAULT:
212 		asm_ldqa_primary_nofault(q);
213 		break;
214 	case ASI_SECONDARY_NOFAULT:
215 		asm_ldqa_secondary_nofault(q);
216 		break;
217 	case ASI_PRIMARY_LITTLE:
218 		asm_ldqa_primary_little(q);
219 		break;
220 	case ASI_SECONDARY_LITTLE:
221 		asm_ldqa_secondary_little(q);
222 		break;
223 	case ASI_PRIMARY_NOFAULT_LITTLE:
224 		asm_ldqa_primary_nofault_little(q);
225 		break;
226 	case ASI_SECONDARY_NOFAULT_LITTLE:
227 		asm_ldqa_secondary_nofault_little(q);
228 		break;
229 	default:
230 		errx(1, "asm_ldqa_imm: bad asi %d", asi);
231 	}
232 }
233 
234 void
235 check_asi(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
236 {
237 	check_asi_asi(asi, fr1, fr2, fr3);
238 	check_asi_imm(asi, fr1, fr2, fr3);
239 }
240 
241 void
242 check_asi_asi(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
243 {
244 	struct fpquad q1;
245 
246 	initfpregs(fr1);
247 	initfpregs(fr2);
248 	initfpregs(fr3);
249 
250 	q1.x1 = 0x01234567;
251 	q1.x2 = 0x89abcdef;
252 	q1.x3 = 0x55aa55aa;
253 	q1.x4 = 0xa5a5a5a5;
254 
255 	loadfpregs(fr1);
256 	asm_ldqa_asi(asi, &q1);
257 	savefpregs(fr2);
258 
259 	c_ldqa_asi(asi, fr3, &q1);
260 
261 	if (compare_regs(fr2, fr3)) {
262 		printf("ASI 0x%x failed\n", asi);
263 		dump_regs(fr1, fr2, fr3);
264 		exit(1);
265 	}
266 }
267 
268 void
269 check_asi_imm(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3)
270 {
271 	struct fpquad q1;
272 
273 	initfpregs(fr1);
274 	initfpregs(fr2);
275 	initfpregs(fr3);
276 
277 	q1.x1 = 0x01234567;
278 	q1.x2 = 0x89abcdef;
279 	q1.x3 = 0x55aa55aa;
280 	q1.x4 = 0xa5a5a5a5;
281 
282 	loadfpregs(fr1);
283 	asm_ldqa_imm(asi, &q1);
284 	savefpregs(fr2);
285 
286 	c_ldqa_asi(asi, fr3, &q1);
287 
288 	if (compare_regs(fr2, fr3)) {
289 		printf("ASI 0x%x failed\n", asi);
290 		dump_regs(fr1, fr2, fr3);
291 		exit(1);
292 	}
293 }
294 
295 int
296 main(int argc, char *argv[])
297 {
298 	union fpregs fr1, fr2, fr3;
299 
300 	check_asi(ASI_PRIMARY, &fr1, &fr2, &fr3);
301 	check_asi(ASI_PRIMARY_NOFAULT, &fr1, &fr2, &fr3);
302 	check_asi(ASI_PRIMARY_LITTLE, &fr1, &fr2, &fr3);
303 	check_asi(ASI_PRIMARY_NOFAULT_LITTLE, &fr1, &fr2, &fr3);
304 	check_asi(ASI_SECONDARY, &fr1, &fr2, &fr3);
305 	check_asi(ASI_SECONDARY_NOFAULT, &fr1, &fr2, &fr3);
306 	check_asi(ASI_SECONDARY_LITTLE, &fr1, &fr2, &fr3);
307 	check_asi(ASI_SECONDARY_NOFAULT_LITTLE, &fr1, &fr2, &fr3);
308 	return (0);
309 }
310