xref: /titanic_53/usr/src/uts/sun4v/cpu/niagara.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h>
36*7c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
37*7c478bd9Sstevel@tonic-gate #include <vm/page.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/async.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/dditypes.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/prom_debug.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/intreg.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/machtrap.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/ontrap.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/ivintr.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/panic.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/dtrace.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/simulate.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/fault.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	S_VAC_SIZE	MMU_PAGESIZE /* XXXQ? */
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate  * Maximum number of contexts
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate #define	MAX_NCTXS	(1 << 13)
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate uint_t root_phys_addr_lo_mask = 0xffffffffU;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate #ifdef NIAGARA_ERRATUM_39
69*7c478bd9Sstevel@tonic-gate extern int	niagara_erratum_39;
70*7c478bd9Sstevel@tonic-gate static uint64_t	cpu_ver;			/* Niagara CPU version reg */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /* Niagara CPU version register */
73*7c478bd9Sstevel@tonic-gate #define	VER_MASK_MAJOR_SHIFT	28
74*7c478bd9Sstevel@tonic-gate #define	VER_MASK_MAJOR_MASK	0xf
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate extern uint64_t	va_to_pa(void *);
77*7c478bd9Sstevel@tonic-gate extern uint64_t	ni_getver();			/* HV code to get %hver */
78*7c478bd9Sstevel@tonic-gate extern uint64_t	niagara_getver(uint64_t ni_getver_ra, uint64_t *cpu_version);
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate #endif	/* NIAGARA_ERRATUM_39 */
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate void
83*7c478bd9Sstevel@tonic-gate cpu_setup(void)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	extern int at_flags;
86*7c478bd9Sstevel@tonic-gate 	extern int disable_delay_tlb_flush, delay_tlb_flush;
87*7c478bd9Sstevel@tonic-gate 	extern int mmu_exported_pagesize_mask;
88*7c478bd9Sstevel@tonic-gate 	extern int get_cpu_pagesizes(void);
89*7c478bd9Sstevel@tonic-gate 	extern int cpc_has_overflow_intr;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate #ifdef NIAGARA_ERRATUM_39
92*7c478bd9Sstevel@tonic-gate 	/*
93*7c478bd9Sstevel@tonic-gate 	 * Get CPU version and enable Niagara erratum 39 workaround only
94*7c478bd9Sstevel@tonic-gate 	 * on Niagara 1.x part. This workaround can also be enabled via
95*7c478bd9Sstevel@tonic-gate 	 * /etc/system.
96*7c478bd9Sstevel@tonic-gate 	 */
97*7c478bd9Sstevel@tonic-gate 	if (niagara_getver(va_to_pa((void *)ni_getver), &cpu_ver) == H_EOK &&
98*7c478bd9Sstevel@tonic-gate 	    ((cpu_ver >> VER_MASK_MAJOR_SHIFT) & VER_MASK_MAJOR_MASK) <= 1)
99*7c478bd9Sstevel@tonic-gate 		niagara_erratum_39 = 1;
100*7c478bd9Sstevel@tonic-gate #endif
101*7c478bd9Sstevel@tonic-gate 	cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	/* XXXQ */
104*7c478bd9Sstevel@tonic-gate 	at_flags = EF_SPARC_SUN_US3 | EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	/*
107*7c478bd9Sstevel@tonic-gate 	 * Use the maximum number of contexts available for Spitfire unless
108*7c478bd9Sstevel@tonic-gate 	 * it has been tuned for debugging.
109*7c478bd9Sstevel@tonic-gate 	 * We are checking against 0 here since this value can be patched
110*7c478bd9Sstevel@tonic-gate 	 * while booting.  It can not be patched via /etc/system since it
111*7c478bd9Sstevel@tonic-gate 	 * will be patched too late and thus cause the system to panic.
112*7c478bd9Sstevel@tonic-gate 	 */
113*7c478bd9Sstevel@tonic-gate 	if (nctxs == 0)
114*7c478bd9Sstevel@tonic-gate 		nctxs = MAX_NCTXS;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	if (use_page_coloring) {
117*7c478bd9Sstevel@tonic-gate 		do_pg_coloring = 1;
118*7c478bd9Sstevel@tonic-gate 		if (use_virtual_coloring)
119*7c478bd9Sstevel@tonic-gate 			do_virtual_coloring = 1;
120*7c478bd9Sstevel@tonic-gate 	}
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * Initalize supported page sizes information before the PD.
123*7c478bd9Sstevel@tonic-gate 	 * If no information is available, then initialize the
124*7c478bd9Sstevel@tonic-gate 	 * mmu_exported_pagesize_mask to a reasonable value for that processor.
125*7c478bd9Sstevel@tonic-gate 	 */
126*7c478bd9Sstevel@tonic-gate 	mmu_exported_pagesize_mask = get_cpu_pagesizes();
127*7c478bd9Sstevel@tonic-gate 	if (mmu_exported_pagesize_mask <= 0) {
128*7c478bd9Sstevel@tonic-gate 		mmu_exported_pagesize_mask = (1 << TTE8K) | (1 << TTE64K) |
129*7c478bd9Sstevel@tonic-gate 		    (1 << TTE4M) | (1 << TTE256M);
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	/*
133*7c478bd9Sstevel@tonic-gate 	 * Tune pp_slots to use up to 1/8th of the tlb entries.
134*7c478bd9Sstevel@tonic-gate 	 */
135*7c478bd9Sstevel@tonic-gate 	pp_slots = MIN(8, MAXPP_SLOTS);
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	/*
138*7c478bd9Sstevel@tonic-gate 	 * Block stores invalidate all pages of the d$ so pagecopy
139*7c478bd9Sstevel@tonic-gate 	 * et. al. do not need virtual translations with virtual
140*7c478bd9Sstevel@tonic-gate 	 * coloring taken into consideration.
141*7c478bd9Sstevel@tonic-gate 	 */
142*7c478bd9Sstevel@tonic-gate 	pp_consistent_coloring = 0;
143*7c478bd9Sstevel@tonic-gate 	isa_list =
144*7c478bd9Sstevel@tonic-gate 	    "sparcv9 sparcv8plus sparcv8 sparcv8-fsmuld sparcv7 "
145*7c478bd9Sstevel@tonic-gate 	    "sparc sparcv9+vis sparcv9+vis2 sparcv8plus+vis sparcv8plus+vis2";
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	cpu_hwcap_flags |= AV_SPARC_ASI_BLK_INIT;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	/*
150*7c478bd9Sstevel@tonic-gate 	 * On Spitfire, there's a hole in the address space
151*7c478bd9Sstevel@tonic-gate 	 * that we must never map (the hardware only support 44-bits of
152*7c478bd9Sstevel@tonic-gate 	 * virtual address).  Later CPUs are expected to have wider
153*7c478bd9Sstevel@tonic-gate 	 * supported address ranges.
154*7c478bd9Sstevel@tonic-gate 	 *
155*7c478bd9Sstevel@tonic-gate 	 * See address map on p23 of the UltraSPARC 1 user's manual.
156*7c478bd9Sstevel@tonic-gate 	 */
157*7c478bd9Sstevel@tonic-gate /* XXXQ get from machine description */
158*7c478bd9Sstevel@tonic-gate 	hole_start = (caddr_t)0x80000000000ull;
159*7c478bd9Sstevel@tonic-gate 	hole_end = (caddr_t)0xfffff80000000000ull;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	/*
162*7c478bd9Sstevel@tonic-gate 	 * The kpm mapping window.
163*7c478bd9Sstevel@tonic-gate 	 * kpm_size:
164*7c478bd9Sstevel@tonic-gate 	 *	The size of a single kpm range.
165*7c478bd9Sstevel@tonic-gate 	 *	The overall size will be: kpm_size * vac_colors.
166*7c478bd9Sstevel@tonic-gate 	 * kpm_vbase:
167*7c478bd9Sstevel@tonic-gate 	 *	The virtual start address of the kpm range within the kernel
168*7c478bd9Sstevel@tonic-gate 	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
169*7c478bd9Sstevel@tonic-gate 	 */
170*7c478bd9Sstevel@tonic-gate 	kpm_size = (size_t)(2ull * 1024 * 1024 * 1024 * 1024); /* 2TB */
171*7c478bd9Sstevel@tonic-gate 	kpm_size_shift = 41;
172*7c478bd9Sstevel@tonic-gate 	kpm_vbase = (caddr_t)0xfffffa0000000000ull; /* 16EB - 6TB */
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	/*
175*7c478bd9Sstevel@tonic-gate 	 * The traptrace code uses either %tick or %stick for
176*7c478bd9Sstevel@tonic-gate 	 * timestamping.  We have %stick so we can use it.
177*7c478bd9Sstevel@tonic-gate 	 */
178*7c478bd9Sstevel@tonic-gate 	traptrace_use_stick = 1;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	/*
181*7c478bd9Sstevel@tonic-gate 	 * sun4v provides demap_all
182*7c478bd9Sstevel@tonic-gate 	 */
183*7c478bd9Sstevel@tonic-gate 	if (!disable_delay_tlb_flush)
184*7c478bd9Sstevel@tonic-gate 		delay_tlb_flush = 1;
185*7c478bd9Sstevel@tonic-gate 	/*
186*7c478bd9Sstevel@tonic-gate 	 * Niagara has a performance counter overflow interrupt
187*7c478bd9Sstevel@tonic-gate 	 */
188*7c478bd9Sstevel@tonic-gate 	cpc_has_overflow_intr = 1;
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate #define	MB	 * 1024 * 1024
192*7c478bd9Sstevel@tonic-gate /*
193*7c478bd9Sstevel@tonic-gate  * Set the magic constants of the implementation.
194*7c478bd9Sstevel@tonic-gate  */
195*7c478bd9Sstevel@tonic-gate void
196*7c478bd9Sstevel@tonic-gate cpu_fiximp(struct cpu_node *cpunode)
197*7c478bd9Sstevel@tonic-gate {
198*7c478bd9Sstevel@tonic-gate 	extern int vac_size, vac_shift;
199*7c478bd9Sstevel@tonic-gate 	extern uint_t vac_mask;
200*7c478bd9Sstevel@tonic-gate 	int i, a;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	/*
203*7c478bd9Sstevel@tonic-gate 	 * The assumption here is that fillsysinfo will eventually
204*7c478bd9Sstevel@tonic-gate 	 * have code to fill this info in from the PD.
205*7c478bd9Sstevel@tonic-gate 	 * We hard code this for niagara now.
206*7c478bd9Sstevel@tonic-gate 	 * Once the PD access library is done this code
207*7c478bd9Sstevel@tonic-gate 	 * might need to be changed to get the info from the PD
208*7c478bd9Sstevel@tonic-gate 	 */
209*7c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_size == 0)
210*7c478bd9Sstevel@tonic-gate 		cpunode->ecache_size = 3 MB;
211*7c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_linesize == 0)
212*7c478bd9Sstevel@tonic-gate 		cpunode->ecache_linesize = 64;
213*7c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_associativity == 0)
214*7c478bd9Sstevel@tonic-gate 		cpunode->ecache_associativity = 12;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	cpunode->ecache_setsize =
217*7c478bd9Sstevel@tonic-gate 	    cpunode->ecache_size / cpunode->ecache_associativity;
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	if (ecache_setsize == 0)
220*7c478bd9Sstevel@tonic-gate 		ecache_setsize = cpunode->ecache_setsize;
221*7c478bd9Sstevel@tonic-gate 	if (ecache_alignsize == 0)
222*7c478bd9Sstevel@tonic-gate 		ecache_alignsize = cpunode->ecache_linesize;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	vac_size = S_VAC_SIZE;
225*7c478bd9Sstevel@tonic-gate 	vac_mask = MMU_PAGEMASK & (vac_size - 1);
226*7c478bd9Sstevel@tonic-gate 	i = 0; a = vac_size;
227*7c478bd9Sstevel@tonic-gate 	while (a >>= 1)
228*7c478bd9Sstevel@tonic-gate 		++i;
229*7c478bd9Sstevel@tonic-gate 	vac_shift = i;
230*7c478bd9Sstevel@tonic-gate 	shm_alignment = vac_size;
231*7c478bd9Sstevel@tonic-gate 	vac = 0;
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate static int niagara_cpucnt;
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate void
237*7c478bd9Sstevel@tonic-gate cpu_init_private(struct cpu *cp)
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate 	extern int niagara_kstat_init(void);
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
242*7c478bd9Sstevel@tonic-gate 	if (niagara_cpucnt++ == 0) {
243*7c478bd9Sstevel@tonic-gate 		(void) niagara_kstat_init();
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate void
248*7c478bd9Sstevel@tonic-gate cpu_uninit_private(struct cpu *cp)
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 	extern int niagara_kstat_fini(void);
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
253*7c478bd9Sstevel@tonic-gate 	if (--niagara_cpucnt == 0) {
254*7c478bd9Sstevel@tonic-gate 		(void) niagara_kstat_fini();
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate }
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate /*
259*7c478bd9Sstevel@tonic-gate  * On Niagara, any flush will cause all preceding stores to be
260*7c478bd9Sstevel@tonic-gate  * synchronized wrt the i$, regardless of address or ASI.  In fact,
261*7c478bd9Sstevel@tonic-gate  * the address is ignored, so we always flush address 0.
262*7c478bd9Sstevel@tonic-gate  */
263*7c478bd9Sstevel@tonic-gate void
264*7c478bd9Sstevel@tonic-gate dtrace_flush_sec(uintptr_t addr)
265*7c478bd9Sstevel@tonic-gate {
266*7c478bd9Sstevel@tonic-gate 	doflush(0);
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate #define	IS_FLOAT(i) (((i) & 0x1000000) != 0)
270*7c478bd9Sstevel@tonic-gate #define	IS_IBIT_SET(x)	(x & 0x2000)
271*7c478bd9Sstevel@tonic-gate #define	IS_VIS1(op, op3)(op == 2 && op3 == 0x36)
272*7c478bd9Sstevel@tonic-gate #define	IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(op, op3, asi)		\
273*7c478bd9Sstevel@tonic-gate 		(op == 3 && (op3 == IOP_V8_LDDFA ||		\
274*7c478bd9Sstevel@tonic-gate 		op3 == IOP_V8_STDFA) &&	asi > ASI_SNFL)
275*7c478bd9Sstevel@tonic-gate int
276*7c478bd9Sstevel@tonic-gate vis1_partial_support(struct regs *rp, k_siginfo_t *siginfo, uint_t *fault)
277*7c478bd9Sstevel@tonic-gate {
278*7c478bd9Sstevel@tonic-gate 	char *badaddr;
279*7c478bd9Sstevel@tonic-gate 	int instr;
280*7c478bd9Sstevel@tonic-gate 	uint_t	optype, op3, asi;
281*7c478bd9Sstevel@tonic-gate 	uint_t	rd, ignor;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	ASSERT(USERMODE(rp->r_tstate));
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	instr = fetch_user_instr((caddr_t)rp->r_pc);
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	rd = (instr >> 25) & 0x1f;
288*7c478bd9Sstevel@tonic-gate 	optype = (instr >> 30) & 0x3;
289*7c478bd9Sstevel@tonic-gate 	op3 = (instr >> 19) & 0x3f;
290*7c478bd9Sstevel@tonic-gate 	ignor = (instr >> 5) & 0xff;
291*7c478bd9Sstevel@tonic-gate 	if (IS_IBIT_SET(instr)) {
292*7c478bd9Sstevel@tonic-gate 		asi = (uint32_t)((rp->r_tstate >> TSTATE_ASI_SHIFT) &
293*7c478bd9Sstevel@tonic-gate 		    TSTATE_ASI_MASK);
294*7c478bd9Sstevel@tonic-gate 	} else {
295*7c478bd9Sstevel@tonic-gate 		asi = ignor;
296*7c478bd9Sstevel@tonic-gate 	}
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	if (!IS_VIS1(optype, op3) &&
299*7c478bd9Sstevel@tonic-gate 	    !IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(optype, op3, asi)) {
300*7c478bd9Sstevel@tonic-gate 		return (-1);
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 	switch (simulate_unimp(rp, &badaddr)) {
303*7c478bd9Sstevel@tonic-gate 	case SIMU_RETRY:
304*7c478bd9Sstevel@tonic-gate 		break;	/* regs are already set up */
305*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	case SIMU_SUCCESS:
308*7c478bd9Sstevel@tonic-gate 		/*
309*7c478bd9Sstevel@tonic-gate 		 * skip the successfully
310*7c478bd9Sstevel@tonic-gate 		 * simulated instruction
311*7c478bd9Sstevel@tonic-gate 		 */
312*7c478bd9Sstevel@tonic-gate 		rp->r_pc = rp->r_npc;
313*7c478bd9Sstevel@tonic-gate 		rp->r_npc += 4;
314*7c478bd9Sstevel@tonic-gate 		break;
315*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	case SIMU_FAULT:
318*7c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGSEGV;
319*7c478bd9Sstevel@tonic-gate 		siginfo->si_code = SEGV_MAPERR;
320*7c478bd9Sstevel@tonic-gate 		siginfo->si_addr = badaddr;
321*7c478bd9Sstevel@tonic-gate 		*fault = FLTBOUNDS;
322*7c478bd9Sstevel@tonic-gate 		break;
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	case SIMU_DZERO:
325*7c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGFPE;
326*7c478bd9Sstevel@tonic-gate 		siginfo->si_code = FPE_INTDIV;
327*7c478bd9Sstevel@tonic-gate 		siginfo->si_addr = (caddr_t)rp->r_pc;
328*7c478bd9Sstevel@tonic-gate 		*fault = FLTIZDIV;
329*7c478bd9Sstevel@tonic-gate 		break;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	case SIMU_UNALIGN:
332*7c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGBUS;
333*7c478bd9Sstevel@tonic-gate 		siginfo->si_code = BUS_ADRALN;
334*7c478bd9Sstevel@tonic-gate 		siginfo->si_addr = badaddr;
335*7c478bd9Sstevel@tonic-gate 		*fault = FLTACCESS;
336*7c478bd9Sstevel@tonic-gate 		break;
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	case SIMU_ILLEGAL:
339*7c478bd9Sstevel@tonic-gate 	default:
340*7c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGILL;
341*7c478bd9Sstevel@tonic-gate 		op3 = (instr >> 19) & 0x3F;
342*7c478bd9Sstevel@tonic-gate 		if ((IS_FLOAT(instr) && (op3 == IOP_V8_STQFA) ||
343*7c478bd9Sstevel@tonic-gate 		    (op3 == IOP_V8_STDFA)))
344*7c478bd9Sstevel@tonic-gate 			siginfo->si_code = ILL_ILLADR;
345*7c478bd9Sstevel@tonic-gate 		else
346*7c478bd9Sstevel@tonic-gate 			siginfo->si_code = ILL_ILLOPC;
347*7c478bd9Sstevel@tonic-gate 		siginfo->si_addr = (caddr_t)rp->r_pc;
348*7c478bd9Sstevel@tonic-gate 		*fault = FLTILL;
349*7c478bd9Sstevel@tonic-gate 		break;
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate 	return (0);
352*7c478bd9Sstevel@tonic-gate }
353