17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*aad98a6dSmathue * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /* Read/write user memory procedures for Sparc9 FPU simulator. */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/fpu/fpu_simulator.h>
347c478bd9Sstevel@tonic-gate #include <sys/fpu/globals.h>
357c478bd9Sstevel@tonic-gate #include <sys/systm.h>
367c478bd9Sstevel@tonic-gate #include <vm/seg.h>
377c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
387c478bd9Sstevel@tonic-gate #include <sys/stack.h>
397c478bd9Sstevel@tonic-gate #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate #include <sys/model.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate /* read the user instruction */
437c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_inst(const uint32_t * address,uint32_t * pvalue,fp_simd_type * pfpsd)447c478bd9Sstevel@tonic-gate _fp_read_inst(
457c478bd9Sstevel@tonic-gate const uint32_t *address, /* FPU instruction address. */
467c478bd9Sstevel@tonic-gate uint32_t *pvalue, /* Place for instruction value. */
477c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate if (((uintptr_t)address & 0x3) != 0)
507c478bd9Sstevel@tonic-gate return (ftt_alignment); /* Must be word-aligned. */
517c478bd9Sstevel@tonic-gate
52*aad98a6dSmathue if (get_udatamodel() == DATAMODEL_ILP32) {
53*aad98a6dSmathue /*
54*aad98a6dSmathue * If this is a 32-bit program, chop the address accordingly.
55*aad98a6dSmathue * The intermediate uintptr_t casts prevent warnings under a
56*aad98a6dSmathue * certain compiler, and the temporary 32 bit storage is
57*aad98a6dSmathue * intended to force proper code generation and break up what
58*aad98a6dSmathue * would otherwise be a quadruple cast.
59*aad98a6dSmathue */
60*aad98a6dSmathue caddr32_t address32 = (caddr32_t)(uintptr_t)address;
61*aad98a6dSmathue address = (uint32_t *)(uintptr_t)address32;
62*aad98a6dSmathue }
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate if (fuword32(address, pvalue) == -1) {
657c478bd9Sstevel@tonic-gate pfpsd->fp_trapaddr = (caddr_t)address;
667c478bd9Sstevel@tonic-gate pfpsd->fp_traprw = S_READ;
677c478bd9Sstevel@tonic-gate return (ftt_fault);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate return (ftt_none);
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_extword(const uint64_t * address,uint64_t * pvalue,fp_simd_type * pfpsd)737c478bd9Sstevel@tonic-gate _fp_read_extword(
747c478bd9Sstevel@tonic-gate const uint64_t *address, /* FPU data address. */
757c478bd9Sstevel@tonic-gate uint64_t *pvalue, /* Place for extended word value. */
767c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate if (((uintptr_t)address & 0x7) != 0)
797c478bd9Sstevel@tonic-gate return (ftt_alignment); /* Must be extword-aligned. */
807c478bd9Sstevel@tonic-gate
81*aad98a6dSmathue if (get_udatamodel() == DATAMODEL_ILP32) {
82*aad98a6dSmathue /*
83*aad98a6dSmathue * If this is a 32-bit program, chop the address accordingly.
84*aad98a6dSmathue * The intermediate uintptr_t casts prevent warnings under a
85*aad98a6dSmathue * certain compiler, and the temporary 32 bit storage is
86*aad98a6dSmathue * intended to force proper code generation and break up what
87*aad98a6dSmathue * would otherwise be a quadruple cast.
88*aad98a6dSmathue */
89*aad98a6dSmathue caddr32_t address32 = (caddr32_t)(uintptr_t)address;
90*aad98a6dSmathue address = (uint64_t *)(uintptr_t)address32;
91*aad98a6dSmathue }
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate if (fuword64(address, pvalue) == -1) {
947c478bd9Sstevel@tonic-gate pfpsd->fp_trapaddr = (caddr_t)address;
957c478bd9Sstevel@tonic-gate pfpsd->fp_traprw = S_READ;
967c478bd9Sstevel@tonic-gate return (ftt_fault);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate return (ftt_none);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_word(const uint32_t * address,uint32_t * pvalue,fp_simd_type * pfpsd)1027c478bd9Sstevel@tonic-gate _fp_read_word(
1037c478bd9Sstevel@tonic-gate const uint32_t *address, /* FPU data address. */
1047c478bd9Sstevel@tonic-gate uint32_t *pvalue, /* Place for word value. */
1057c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate if (((uintptr_t)address & 0x3) != 0)
1087c478bd9Sstevel@tonic-gate return (ftt_alignment); /* Must be word-aligned. */
1097c478bd9Sstevel@tonic-gate
110*aad98a6dSmathue if (get_udatamodel() == DATAMODEL_ILP32) {
111*aad98a6dSmathue /*
112*aad98a6dSmathue * If this is a 32-bit program, chop the address accordingly.
113*aad98a6dSmathue * The intermediate uintptr_t casts prevent warnings under a
114*aad98a6dSmathue * certain compiler, and the temporary 32 bit storage is
115*aad98a6dSmathue * intended to force proper code generation and break up what
116*aad98a6dSmathue * would otherwise be a quadruple cast.
117*aad98a6dSmathue */
118*aad98a6dSmathue caddr32_t address32 = (caddr32_t)(uintptr_t)address;
119*aad98a6dSmathue address = (uint32_t *)(uintptr_t)address32;
120*aad98a6dSmathue }
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate if (fuword32(address, pvalue) == -1) {
1237c478bd9Sstevel@tonic-gate pfpsd->fp_trapaddr = (caddr_t)address;
1247c478bd9Sstevel@tonic-gate pfpsd->fp_traprw = S_READ;
1257c478bd9Sstevel@tonic-gate return (ftt_fault);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate return (ftt_none);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate enum ftt_type
_fp_write_extword(uint64_t * address,uint64_t value,fp_simd_type * pfpsd)1317c478bd9Sstevel@tonic-gate _fp_write_extword(
1327c478bd9Sstevel@tonic-gate uint64_t *address, /* FPU data address. */
1337c478bd9Sstevel@tonic-gate uint64_t value, /* Extended word value to write. */
1347c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate if (((uintptr_t)address & 0x7) != 0)
1377c478bd9Sstevel@tonic-gate return (ftt_alignment); /* Must be extword-aligned. */
1387c478bd9Sstevel@tonic-gate
139*aad98a6dSmathue if (get_udatamodel() == DATAMODEL_ILP32) {
140*aad98a6dSmathue /*
141*aad98a6dSmathue * If this is a 32-bit program, chop the address accordingly.
142*aad98a6dSmathue * The intermediate uintptr_t casts prevent warnings under a
143*aad98a6dSmathue * certain compiler, and the temporary 32 bit storage is
144*aad98a6dSmathue * intended to force proper code generation and break up what
145*aad98a6dSmathue * would otherwise be a quadruple cast.
146*aad98a6dSmathue */
147*aad98a6dSmathue caddr32_t address32 = (caddr32_t)(uintptr_t)address;
148*aad98a6dSmathue address = (uint64_t *)(uintptr_t)address32;
149*aad98a6dSmathue }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (suword64(address, value) == -1) {
1527c478bd9Sstevel@tonic-gate pfpsd->fp_trapaddr = (caddr_t)address;
1537c478bd9Sstevel@tonic-gate pfpsd->fp_traprw = S_WRITE;
1547c478bd9Sstevel@tonic-gate return (ftt_fault);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate return (ftt_none);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate enum ftt_type
_fp_write_word(uint32_t * address,uint32_t value,fp_simd_type * pfpsd)1607c478bd9Sstevel@tonic-gate _fp_write_word(
1617c478bd9Sstevel@tonic-gate uint32_t *address, /* FPU data address. */
1627c478bd9Sstevel@tonic-gate uint32_t value, /* Word value to write. */
1637c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd) /* Pointer to fpu simulator data. */
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate if (((uintptr_t)address & 0x3) != 0)
1667c478bd9Sstevel@tonic-gate return (ftt_alignment); /* Must be word-aligned. */
1677c478bd9Sstevel@tonic-gate
168*aad98a6dSmathue if (get_udatamodel() == DATAMODEL_ILP32) {
169*aad98a6dSmathue /*
170*aad98a6dSmathue * If this is a 32-bit program, chop the address accordingly.
171*aad98a6dSmathue * The intermediate uintptr_t casts prevent warnings under a
172*aad98a6dSmathue * certain compiler, and the temporary 32 bit storage is
173*aad98a6dSmathue * intended to force proper code generation and break up what
174*aad98a6dSmathue * would otherwise be a quadruple cast.
175*aad98a6dSmathue */
176*aad98a6dSmathue caddr32_t address32 = (caddr32_t)(uintptr_t)address;
177*aad98a6dSmathue address = (uint32_t *)(uintptr_t)address32;
178*aad98a6dSmathue }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate if (suword32(address, value) == -1) {
1817c478bd9Sstevel@tonic-gate pfpsd->fp_trapaddr = (caddr_t)address;
1827c478bd9Sstevel@tonic-gate pfpsd->fp_traprw = S_WRITE;
1837c478bd9Sstevel@tonic-gate return (ftt_fault);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate return (ftt_none);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate * Reads integer unit's register n.
1907c478bd9Sstevel@tonic-gate */
1917c478bd9Sstevel@tonic-gate enum ftt_type
read_iureg(fp_simd_type * pfpsd,uint_t n,struct regs * pregs,void * prw,uint64_t * pvalue)1927c478bd9Sstevel@tonic-gate read_iureg(
1937c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to fpu simulator data */
1947c478bd9Sstevel@tonic-gate uint_t n, /* IU register n */
1957c478bd9Sstevel@tonic-gate struct regs *pregs, /* Pointer to PCB image of registers. */
1967c478bd9Sstevel@tonic-gate void *prw, /* Pointer to locals and ins. */
1977c478bd9Sstevel@tonic-gate uint64_t *pvalue) /* Place for extended word value. */
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate enum ftt_type ftt;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate if (n == 0) {
2027c478bd9Sstevel@tonic-gate *pvalue = 0;
2037c478bd9Sstevel@tonic-gate return (ftt_none); /* Read global register 0. */
2047c478bd9Sstevel@tonic-gate } else if (n < 16) {
2057c478bd9Sstevel@tonic-gate long long *preg;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate preg = &pregs->r_ps; /* globals and outs */
2087c478bd9Sstevel@tonic-gate *pvalue = preg[n];
2097c478bd9Sstevel@tonic-gate return (ftt_none);
2107c478bd9Sstevel@tonic-gate } else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
2117c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
2127c478bd9Sstevel@tonic-gate uint32_t res, *addr, *rw;
213*aad98a6dSmathue caddr32_t rw32;
2147c478bd9Sstevel@tonic-gate
215*aad98a6dSmathue /*
216*aad98a6dSmathue * If this is a 32-bit program, chop the address
217*aad98a6dSmathue * accordingly. The intermediate uintptr_t casts
218*aad98a6dSmathue * prevent warnings under a certain compiler, and the
219*aad98a6dSmathue * temporary 32 bit storage is intended to force proper
220*aad98a6dSmathue * code generation and break up what would otherwise be
221*aad98a6dSmathue * a quadruple cast.
222*aad98a6dSmathue */
223*aad98a6dSmathue rw32 = (caddr32_t)(uintptr_t)prw;
224*aad98a6dSmathue rw = (uint32_t *)(uintptr_t)rw32;
225*aad98a6dSmathue
2267c478bd9Sstevel@tonic-gate addr = (uint32_t *)&rw[n - 16];
2277c478bd9Sstevel@tonic-gate ftt = _fp_read_word(addr, &res, pfpsd);
2287c478bd9Sstevel@tonic-gate *pvalue = (uint64_t)res;
2297c478bd9Sstevel@tonic-gate } else {
2307c478bd9Sstevel@tonic-gate uint64_t res, *addr, *rw = (uint64_t *)
2317c478bd9Sstevel@tonic-gate ((uintptr_t)prw + STACK_BIAS);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate addr = (uint64_t *)&rw[n - 16];
2347c478bd9Sstevel@tonic-gate ftt = _fp_read_extword(addr, &res, pfpsd);
2357c478bd9Sstevel@tonic-gate *pvalue = res;
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate return (ftt);
2387c478bd9Sstevel@tonic-gate } else {
2397c478bd9Sstevel@tonic-gate ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
2407c478bd9Sstevel@tonic-gate ulong_t res;
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate addr = (ulong_t *)&rw[n - 16];
2437c478bd9Sstevel@tonic-gate res = *addr;
2447c478bd9Sstevel@tonic-gate *pvalue = res;
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate return (ftt_none);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate * Writes integer unit's register n.
2527c478bd9Sstevel@tonic-gate */
2537c478bd9Sstevel@tonic-gate enum ftt_type
write_iureg(fp_simd_type * pfpsd,uint_t n,struct regs * pregs,void * prw,uint64_t * pvalue)2547c478bd9Sstevel@tonic-gate write_iureg(
2557c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to fpu simulator data. */
2567c478bd9Sstevel@tonic-gate uint_t n, /* IU register n. */
2577c478bd9Sstevel@tonic-gate struct regs *pregs, /* Pointer to PCB image of registers. */
2587c478bd9Sstevel@tonic-gate void *prw, /* Pointer to locals and ins. */
2597c478bd9Sstevel@tonic-gate uint64_t *pvalue) /* Extended word value to write. */
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate long long *preg;
2627c478bd9Sstevel@tonic-gate enum ftt_type ftt;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate if (n == 0) {
2657c478bd9Sstevel@tonic-gate return (ftt_none); /* Read global register 0. */
2667c478bd9Sstevel@tonic-gate } else if (n < 16) {
2677c478bd9Sstevel@tonic-gate preg = &pregs->r_ps; /* globals and outs */
2687c478bd9Sstevel@tonic-gate preg[n] = *pvalue;
2697c478bd9Sstevel@tonic-gate return (ftt_none);
2707c478bd9Sstevel@tonic-gate } else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
2717c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
2727c478bd9Sstevel@tonic-gate uint32_t res, *addr, *rw;
273*aad98a6dSmathue caddr32_t rw32;
2747c478bd9Sstevel@tonic-gate
275*aad98a6dSmathue /*
276*aad98a6dSmathue * If this is a 32-bit program, chop the address
277*aad98a6dSmathue * accordingly. The intermediate uintptr_t casts
278*aad98a6dSmathue * prevent warnings under a certain compiler, and the
279*aad98a6dSmathue * temporary 32 bit storage is intended to force proper
280*aad98a6dSmathue * code generation and break up what would otherwise be
281*aad98a6dSmathue * a quadruple cast.
282*aad98a6dSmathue */
283*aad98a6dSmathue rw32 = (caddr32_t)(uintptr_t)prw;
284*aad98a6dSmathue rw = (uint32_t *)(uintptr_t)rw32;
285*aad98a6dSmathue
2867c478bd9Sstevel@tonic-gate addr = &rw[n - 16];
2877c478bd9Sstevel@tonic-gate res = (uint_t)*pvalue;
2887c478bd9Sstevel@tonic-gate ftt = _fp_write_word(addr, res, pfpsd);
2897c478bd9Sstevel@tonic-gate } else {
2907c478bd9Sstevel@tonic-gate uint64_t *addr, *rw = (uint64_t *)
2917c478bd9Sstevel@tonic-gate ((uintptr_t)prw + STACK_BIAS);
2927c478bd9Sstevel@tonic-gate uint64_t res;
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate addr = &rw[n - 16];
2957c478bd9Sstevel@tonic-gate res = *pvalue;
2967c478bd9Sstevel@tonic-gate ftt = _fp_write_extword(addr, res, pfpsd);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate return (ftt);
2997c478bd9Sstevel@tonic-gate } else {
3007c478bd9Sstevel@tonic-gate ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
3017c478bd9Sstevel@tonic-gate ulong_t res = *pvalue;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate addr = &rw[n - 16];
3047c478bd9Sstevel@tonic-gate *addr = res;
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate return (ftt_none);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate }
309