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 2005 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 /* 54 * If this is a 32-bit program, chop the address accordingly. 55 * The intermediate uintptr_t casts prevent warnings under a 56 * certain compiler, and the temporary 32 bit storage is 57 * intended to force proper code generation and break up what 58 * would otherwise be a quadruple cast. 59 */ 60 caddr32_t address32 = (caddr32_t)(uintptr_t)address; 61 address = (uint32_t *)(uintptr_t)address32; 62 } 63 64 if (fuword32(address, pvalue) == -1) { 65 pfpsd->fp_trapaddr = (caddr_t)address; 66 pfpsd->fp_traprw = S_READ; 67 return (ftt_fault); 68 } 69 return (ftt_none); 70 } 71 72 enum ftt_type 73 _fp_read_extword( 74 const uint64_t *address, /* FPU data address. */ 75 uint64_t *pvalue, /* Place for extended word value. */ 76 fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */ 77 { 78 if (((uintptr_t)address & 0x7) != 0) 79 return (ftt_alignment); /* Must be extword-aligned. */ 80 81 if (get_udatamodel() == DATAMODEL_ILP32) { 82 /* 83 * If this is a 32-bit program, chop the address accordingly. 84 * The intermediate uintptr_t casts prevent warnings under a 85 * certain compiler, and the temporary 32 bit storage is 86 * intended to force proper code generation and break up what 87 * would otherwise be a quadruple cast. 88 */ 89 caddr32_t address32 = (caddr32_t)(uintptr_t)address; 90 address = (uint64_t *)(uintptr_t)address32; 91 } 92 93 if (fuword64(address, pvalue) == -1) { 94 pfpsd->fp_trapaddr = (caddr_t)address; 95 pfpsd->fp_traprw = S_READ; 96 return (ftt_fault); 97 } 98 return (ftt_none); 99 } 100 101 enum ftt_type 102 _fp_read_word( 103 const uint32_t *address, /* FPU data address. */ 104 uint32_t *pvalue, /* Place for word value. */ 105 fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */ 106 { 107 if (((uintptr_t)address & 0x3) != 0) 108 return (ftt_alignment); /* Must be word-aligned. */ 109 110 if (get_udatamodel() == DATAMODEL_ILP32) { 111 /* 112 * If this is a 32-bit program, chop the address accordingly. 113 * The intermediate uintptr_t casts prevent warnings under a 114 * certain compiler, and the temporary 32 bit storage is 115 * intended to force proper code generation and break up what 116 * would otherwise be a quadruple cast. 117 */ 118 caddr32_t address32 = (caddr32_t)(uintptr_t)address; 119 address = (uint32_t *)(uintptr_t)address32; 120 } 121 122 if (fuword32(address, pvalue) == -1) { 123 pfpsd->fp_trapaddr = (caddr_t)address; 124 pfpsd->fp_traprw = S_READ; 125 return (ftt_fault); 126 } 127 return (ftt_none); 128 } 129 130 enum ftt_type 131 _fp_write_extword( 132 uint64_t *address, /* FPU data address. */ 133 uint64_t value, /* Extended word value to write. */ 134 fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */ 135 { 136 if (((uintptr_t)address & 0x7) != 0) 137 return (ftt_alignment); /* Must be extword-aligned. */ 138 139 if (get_udatamodel() == DATAMODEL_ILP32) { 140 /* 141 * If this is a 32-bit program, chop the address accordingly. 142 * The intermediate uintptr_t casts prevent warnings under a 143 * certain compiler, and the temporary 32 bit storage is 144 * intended to force proper code generation and break up what 145 * would otherwise be a quadruple cast. 146 */ 147 caddr32_t address32 = (caddr32_t)(uintptr_t)address; 148 address = (uint64_t *)(uintptr_t)address32; 149 } 150 151 if (suword64(address, value) == -1) { 152 pfpsd->fp_trapaddr = (caddr_t)address; 153 pfpsd->fp_traprw = S_WRITE; 154 return (ftt_fault); 155 } 156 return (ftt_none); 157 } 158 159 enum ftt_type 160 _fp_write_word( 161 uint32_t *address, /* FPU data address. */ 162 uint32_t value, /* Word value to write. */ 163 fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */ 164 { 165 if (((uintptr_t)address & 0x3) != 0) 166 return (ftt_alignment); /* Must be word-aligned. */ 167 168 if (get_udatamodel() == DATAMODEL_ILP32) { 169 /* 170 * If this is a 32-bit program, chop the address accordingly. 171 * The intermediate uintptr_t casts prevent warnings under a 172 * certain compiler, and the temporary 32 bit storage is 173 * intended to force proper code generation and break up what 174 * would otherwise be a quadruple cast. 175 */ 176 caddr32_t address32 = (caddr32_t)(uintptr_t)address; 177 address = (uint32_t *)(uintptr_t)address32; 178 } 179 180 if (suword32(address, value) == -1) { 181 pfpsd->fp_trapaddr = (caddr_t)address; 182 pfpsd->fp_traprw = S_WRITE; 183 return (ftt_fault); 184 } 185 return (ftt_none); 186 } 187 188 /* 189 * Reads integer unit's register n. 190 */ 191 enum ftt_type 192 read_iureg( 193 fp_simd_type *pfpsd, /* Pointer to fpu simulator data */ 194 uint_t n, /* IU register n */ 195 struct regs *pregs, /* Pointer to PCB image of registers. */ 196 void *prw, /* Pointer to locals and ins. */ 197 uint64_t *pvalue) /* Place for extended word value. */ 198 { 199 enum ftt_type ftt; 200 201 if (n == 0) { 202 *pvalue = 0; 203 return (ftt_none); /* Read global register 0. */ 204 } else if (n < 16) { 205 long long *preg; 206 207 preg = &pregs->r_ps; /* globals and outs */ 208 *pvalue = preg[n]; 209 return (ftt_none); 210 } else if (USERMODE(pregs->r_tstate)) { /* locals and ins */ 211 if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) { 212 uint32_t res, *addr, *rw; 213 caddr32_t rw32; 214 215 /* 216 * If this is a 32-bit program, chop the address 217 * accordingly. The intermediate uintptr_t casts 218 * prevent warnings under a certain compiler, and the 219 * temporary 32 bit storage is intended to force proper 220 * code generation and break up what would otherwise be 221 * a quadruple cast. 222 */ 223 rw32 = (caddr32_t)(uintptr_t)prw; 224 rw = (uint32_t *)(uintptr_t)rw32; 225 226 addr = (uint32_t *)&rw[n - 16]; 227 ftt = _fp_read_word(addr, &res, pfpsd); 228 *pvalue = (uint64_t)res; 229 } else { 230 uint64_t res, *addr, *rw = (uint64_t *) 231 ((uintptr_t)prw + STACK_BIAS); 232 233 addr = (uint64_t *)&rw[n - 16]; 234 ftt = _fp_read_extword(addr, &res, pfpsd); 235 *pvalue = res; 236 } 237 return (ftt); 238 } else { 239 ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS); 240 ulong_t res; 241 242 addr = (ulong_t *)&rw[n - 16]; 243 res = *addr; 244 *pvalue = res; 245 246 return (ftt_none); 247 } 248 } 249 250 /* 251 * Writes integer unit's register n. 252 */ 253 enum ftt_type 254 write_iureg( 255 fp_simd_type *pfpsd, /* Pointer to fpu simulator data. */ 256 uint_t n, /* IU register n. */ 257 struct regs *pregs, /* Pointer to PCB image of registers. */ 258 void *prw, /* Pointer to locals and ins. */ 259 uint64_t *pvalue) /* Extended word value to write. */ 260 { 261 long long *preg; 262 enum ftt_type ftt; 263 264 if (n == 0) { 265 return (ftt_none); /* Read global register 0. */ 266 } else if (n < 16) { 267 preg = &pregs->r_ps; /* globals and outs */ 268 preg[n] = *pvalue; 269 return (ftt_none); 270 } else if (USERMODE(pregs->r_tstate)) { /* locals and ins */ 271 if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) { 272 uint32_t res, *addr, *rw; 273 caddr32_t rw32; 274 275 /* 276 * If this is a 32-bit program, chop the address 277 * accordingly. The intermediate uintptr_t casts 278 * prevent warnings under a certain compiler, and the 279 * temporary 32 bit storage is intended to force proper 280 * code generation and break up what would otherwise be 281 * a quadruple cast. 282 */ 283 rw32 = (caddr32_t)(uintptr_t)prw; 284 rw = (uint32_t *)(uintptr_t)rw32; 285 286 addr = &rw[n - 16]; 287 res = (uint_t)*pvalue; 288 ftt = _fp_write_word(addr, res, pfpsd); 289 } else { 290 uint64_t *addr, *rw = (uint64_t *) 291 ((uintptr_t)prw + STACK_BIAS); 292 uint64_t res; 293 294 addr = &rw[n - 16]; 295 res = *pvalue; 296 ftt = _fp_write_extword(addr, res, pfpsd); 297 } 298 return (ftt); 299 } else { 300 ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS); 301 ulong_t res = *pvalue; 302 303 addr = &rw[n - 16]; 304 *addr = res; 305 306 return (ftt_none); 307 } 308 } 309