xref: /titanic_51/usr/src/uts/sparc/v9/fpu/uword.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /* Read/write user memory procedures for Sparc9 FPU simulator. */
30 
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/fpu/fpu_simulator.h>
34 #include <sys/fpu/globals.h>
35 #include <sys/systm.h>
36 #include <vm/seg.h>
37 #include <sys/privregs.h>
38 #include <sys/stack.h>
39 #include <sys/debug.h>
40 #include <sys/model.h>
41 
42 /* read the user instruction */
43 enum ftt_type
44 _fp_read_inst(
45 	const uint32_t *address,	/* FPU instruction address. */
46 	uint32_t *pvalue,		/* Place for instruction value. */
47 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
48 {
49 	if (((uintptr_t)address & 0x3) != 0)
50 		return (ftt_alignment);	/* Must be word-aligned. */
51 
52 	if (get_udatamodel() == DATAMODEL_ILP32)
53 		address = (uint32_t *)(caddr32_t)address;
54 
55 	if (fuword32(address, pvalue) == -1) {
56 		pfpsd->fp_trapaddr = (caddr_t)address;
57 		pfpsd->fp_traprw = S_READ;
58 		return (ftt_fault);
59 	}
60 	return (ftt_none);
61 }
62 
63 enum ftt_type
64 _fp_read_extword(
65 	const uint64_t *address,	/* FPU data address. */
66 	uint64_t *pvalue,		/* Place for extended word value. */
67 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
68 {
69 	if (((uintptr_t)address & 0x7) != 0)
70 		return (ftt_alignment);	/* Must be extword-aligned. */
71 
72 	if (get_udatamodel() == DATAMODEL_ILP32)
73 		address = (uint64_t *)(caddr32_t)address;
74 
75 	if (fuword64(address, pvalue) == -1) {
76 		pfpsd->fp_trapaddr = (caddr_t)address;
77 		pfpsd->fp_traprw = S_READ;
78 		return (ftt_fault);
79 	}
80 	return (ftt_none);
81 }
82 
83 enum ftt_type
84 _fp_read_word(
85 	const uint32_t *address,	/* FPU data address. */
86 	uint32_t *pvalue,		/* Place for word value. */
87 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
88 {
89 	if (((uintptr_t)address & 0x3) != 0)
90 		return (ftt_alignment);	/* Must be word-aligned. */
91 
92 	if (get_udatamodel() == DATAMODEL_ILP32)
93 		address = (uint32_t *)(caddr32_t)address;
94 
95 	if (fuword32(address, pvalue) == -1) {
96 		pfpsd->fp_trapaddr = (caddr_t)address;
97 		pfpsd->fp_traprw = S_READ;
98 		return (ftt_fault);
99 	}
100 	return (ftt_none);
101 }
102 
103 enum ftt_type
104 _fp_write_extword(
105 	uint64_t *address,		/* FPU data address. */
106 	uint64_t value,			/* Extended word value to write. */
107 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
108 {
109 	if (((uintptr_t)address & 0x7) != 0)
110 		return (ftt_alignment);	/* Must be extword-aligned. */
111 
112 	if (get_udatamodel() == DATAMODEL_ILP32)
113 		address = (uint64_t *)(caddr32_t)address;
114 
115 	if (suword64(address, value) == -1) {
116 		pfpsd->fp_trapaddr = (caddr_t)address;
117 		pfpsd->fp_traprw = S_WRITE;
118 		return (ftt_fault);
119 	}
120 	return (ftt_none);
121 }
122 
123 enum ftt_type
124 _fp_write_word(
125 	uint32_t *address,		/* FPU data address. */
126 	uint32_t value,			/* Word value to write. */
127 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
128 {
129 	if (((uintptr_t)address & 0x3) != 0)
130 		return (ftt_alignment);	/* Must be word-aligned. */
131 
132 	if (get_udatamodel() == DATAMODEL_ILP32)
133 		address = (uint32_t *)(caddr32_t)address;
134 
135 	if (suword32(address, value) == -1) {
136 		pfpsd->fp_trapaddr = (caddr_t)address;
137 		pfpsd->fp_traprw = S_WRITE;
138 		return (ftt_fault);
139 	}
140 	return (ftt_none);
141 }
142 
143 /*
144  * Reads integer unit's register n.
145  */
146 enum ftt_type
147 read_iureg(
148 	fp_simd_type	*pfpsd,		/* Pointer to fpu simulator data */
149 	uint_t		n,		/* IU register n */
150 	struct regs	*pregs,		/* Pointer to PCB image of registers. */
151 	void		*prw,		/* Pointer to locals and ins. */
152 	uint64_t	*pvalue)	/* Place for extended word value. */
153 {
154 	enum ftt_type ftt;
155 
156 	if (n == 0) {
157 		*pvalue = 0;
158 		return (ftt_none);	/* Read global register 0. */
159 	} else if (n < 16) {
160 		long long *preg;
161 
162 		preg = &pregs->r_ps;		/* globals and outs */
163 		*pvalue = preg[n];
164 		return (ftt_none);
165 	} else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
166 		if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
167 			uint32_t res, *addr, *rw;
168 
169 			rw = (uint32_t *)(caddr32_t)prw;
170 			addr = (uint32_t *)&rw[n - 16];
171 			ftt = _fp_read_word(addr, &res, pfpsd);
172 			*pvalue = (uint64_t)res;
173 		} else {
174 			uint64_t res, *addr, *rw = (uint64_t *)
175 					((uintptr_t)prw + STACK_BIAS);
176 
177 			addr = (uint64_t *)&rw[n - 16];
178 			ftt = _fp_read_extword(addr, &res, pfpsd);
179 			*pvalue = res;
180 		}
181 		return (ftt);
182 	} else {
183 		ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
184 		ulong_t res;
185 
186 		addr = (ulong_t *)&rw[n - 16];
187 		res = *addr;
188 		*pvalue = res;
189 
190 		return (ftt_none);
191 	}
192 }
193 
194 /*
195  * Writes integer unit's register n.
196  */
197 enum ftt_type
198 write_iureg(
199 	fp_simd_type	*pfpsd,		/* Pointer to fpu simulator data. */
200 	uint_t		n,		/* IU register n. */
201 	struct regs	*pregs,		/* Pointer to PCB image of registers. */
202 	void		*prw,		/* Pointer to locals and ins. */
203 	uint64_t	*pvalue)	/* Extended word value to write. */
204 {
205 	long long *preg;
206 	enum ftt_type ftt;
207 
208 	if (n == 0) {
209 		return (ftt_none);	/* Read global register 0. */
210 	} else if (n < 16) {
211 		preg = &pregs->r_ps;		/* globals and outs */
212 		preg[n] = *pvalue;
213 		return (ftt_none);
214 	} else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
215 		if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
216 			uint32_t res, *addr, *rw;
217 
218 			rw = (uint32_t *)(caddr32_t)prw;
219 			addr = &rw[n - 16];
220 			res = (uint_t)*pvalue;
221 			ftt = _fp_write_word(addr, res, pfpsd);
222 		} else {
223 			uint64_t *addr, *rw = (uint64_t *)
224 				((uintptr_t)prw + STACK_BIAS);
225 			uint64_t res;
226 
227 			addr = &rw[n - 16];
228 			res = *pvalue;
229 			ftt = _fp_write_extword(addr, res, pfpsd);
230 		}
231 		return (ftt);
232 	} else {
233 		ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
234 		ulong_t res = *pvalue;
235 
236 		addr = &rw[n - 16];
237 		*addr = res;
238 
239 		return (ftt_none);
240 	}
241 }
242