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
41struct fpquad {
42        u_int32_t x1;
43        u_int32_t x2;
44        u_int32_t x3;
45        u_int32_t x4;
46};
47
48int compare_regs(union fpregs *, union fpregs *);
49void dump_reg(union fpregs *);
50void dump_regs(union fpregs *, union fpregs *, union fpregs *);
51int compare_quads(struct fpquad *, struct fpquad *);
52void c_stqa_asi(int, union fpregs *, struct fpquad *);
53void c_ldqa_asi(int, union fpregs *, struct fpquad *);
54void asm_ldqa_asi(int, struct fpquad *);
55void asm_stqa_asi(int, struct fpquad *);
56void asm_ldqa_imm(int asi, struct fpquad *);
57void asm_stqa_imm(int asi, struct fpquad *);
58void asm_stqa_primary(struct fpquad *);
59void asm_ldqa_primary(struct fpquad *);
60void asm_stqa_secondary(struct fpquad *);
61void asm_ldqa_secondary(struct fpquad *);
62void asm_stqa_primary_nofault(struct fpquad *);
63void asm_ldqa_primary_nofault(struct fpquad *);
64void asm_stqa_secondary_nofault(struct fpquad *);
65void asm_ldqa_secondary_nofault(struct fpquad *);
66void asm_stqa_primary_little(struct fpquad *);
67void asm_ldqa_primary_little(struct fpquad *);
68void asm_stqa_secondary_little(struct fpquad *);
69void asm_ldqa_secondary_little(struct fpquad *);
70void asm_stqa_primary_nofault_little(struct fpquad *);
71void asm_ldqa_primary_nofault_little(struct fpquad *);
72void asm_stqa_secondary_nofault_little(struct fpquad *);
73void asm_ldqa_secondary_nofault_little(struct fpquad *);
74void check_asi(int, union fpregs *, union fpregs *, union fpregs *);
75void check_asi_asi(int, union fpregs *, union fpregs *, union fpregs *);
76void check_asi_imm(int, union fpregs *, union fpregs *, union fpregs *);
77int main(int, char *[]);
78
79int
80compare_regs(union fpregs *fr1, union fpregs *fr2)
81{
82	return (memcmp(fr1, fr2, sizeof(*fr2)));
83}
84
85void
86dump_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
99void
100dump_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
110int
111compare_quads(struct fpquad *q1, struct fpquad *q2)
112{
113	return (memcmp(q1, q2, sizeof(*q2)));
114}
115
116void
117c_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
142void
143c_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
168void
169asm_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
201void
202asm_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
234void
235check_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
241void
242check_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
268void
269check_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
295int
296main(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