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
compare_regs(union fpregs * fr1,union fpregs * fr2)80 compare_regs(union fpregs *fr1, union fpregs *fr2)
81 {
82 return (memcmp(fr1, fr2, sizeof(*fr2)));
83 }
84
85 void
dump_reg(union fpregs * fr)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
dump_regs(union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)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
compare_quads(struct fpquad * q1,struct fpquad * q2)111 compare_quads(struct fpquad *q1, struct fpquad *q2)
112 {
113 return (memcmp(q1, q2, sizeof(*q2)));
114 }
115
116 void
c_stqa_asi(int asi,union fpregs * frp,struct fpquad * q)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
c_ldqa_asi(int asi,union fpregs * frp,struct fpquad * q)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
asm_stqa_imm(int asi,struct fpquad * q)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
asm_ldqa_imm(int asi,struct fpquad * q)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
check_asi(int asi,union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)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
check_asi_asi(int asi,union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)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
check_asi_imm(int asi,union fpregs * fr1,union fpregs * fr2,union fpregs * fr3)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
main(int argc,char * argv[])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