xref: /titanic_54/usr/src/uts/sun4v/cpu/niagara.c (revision 70f54ead78cbbb40e97bd3ff9f175c5c71783c3c)
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 /*
237c478bd9Sstevel@tonic-gate  * 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 #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/systm.h>
317c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
327c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
337c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
347c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
357c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h>
367c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
377c478bd9Sstevel@tonic-gate #include <vm/page.h>
387c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
397c478bd9Sstevel@tonic-gate #include <sys/async.h>
407c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
417c478bd9Sstevel@tonic-gate #include <sys/debug.h>
427c478bd9Sstevel@tonic-gate #include <sys/dditypes.h>
437c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
447c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
457c478bd9Sstevel@tonic-gate #include <sys/prom_debug.h>
467c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
477c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h>
487c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
497c478bd9Sstevel@tonic-gate #include <sys/intreg.h>
507c478bd9Sstevel@tonic-gate #include <sys/machtrap.h>
517c478bd9Sstevel@tonic-gate #include <sys/ontrap.h>
527c478bd9Sstevel@tonic-gate #include <sys/ivintr.h>
537c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
547c478bd9Sstevel@tonic-gate #include <sys/panic.h>
557c478bd9Sstevel@tonic-gate #include <sys/dtrace.h>
567c478bd9Sstevel@tonic-gate #include <sys/simulate.h>
577c478bd9Sstevel@tonic-gate #include <sys/fault.h>
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define	S_VAC_SIZE	MMU_PAGESIZE /* XXXQ? */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Maximum number of contexts
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate #define	MAX_NCTXS	(1 << 13)
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate uint_t root_phys_addr_lo_mask = 0xffffffffU;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate #ifdef NIAGARA_ERRATUM_39
697c478bd9Sstevel@tonic-gate extern int	niagara_erratum_39;
707c478bd9Sstevel@tonic-gate static uint64_t	cpu_ver;			/* Niagara CPU version reg */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /* Niagara CPU version register */
737c478bd9Sstevel@tonic-gate #define	VER_MASK_MAJOR_SHIFT	28
747c478bd9Sstevel@tonic-gate #define	VER_MASK_MAJOR_MASK	0xf
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate extern uint64_t	va_to_pa(void *);
777c478bd9Sstevel@tonic-gate extern uint64_t	ni_getver();			/* HV code to get %hver */
787c478bd9Sstevel@tonic-gate extern uint64_t	niagara_getver(uint64_t ni_getver_ra, uint64_t *cpu_version);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #endif	/* NIAGARA_ERRATUM_39 */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void
837c478bd9Sstevel@tonic-gate cpu_setup(void)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	extern int at_flags;
867c478bd9Sstevel@tonic-gate 	extern int disable_delay_tlb_flush, delay_tlb_flush;
877c478bd9Sstevel@tonic-gate 	extern int mmu_exported_pagesize_mask;
887c478bd9Sstevel@tonic-gate 	extern int get_cpu_pagesizes(void);
897c478bd9Sstevel@tonic-gate 	extern int cpc_has_overflow_intr;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #ifdef NIAGARA_ERRATUM_39
927c478bd9Sstevel@tonic-gate 	/*
937c478bd9Sstevel@tonic-gate 	 * Get CPU version and enable Niagara erratum 39 workaround only
947c478bd9Sstevel@tonic-gate 	 * on Niagara 1.x part. This workaround can also be enabled via
957c478bd9Sstevel@tonic-gate 	 * /etc/system.
967c478bd9Sstevel@tonic-gate 	 */
977c478bd9Sstevel@tonic-gate 	if (niagara_getver(va_to_pa((void *)ni_getver), &cpu_ver) == H_EOK &&
987c478bd9Sstevel@tonic-gate 	    ((cpu_ver >> VER_MASK_MAJOR_SHIFT) & VER_MASK_MAJOR_MASK) <= 1)
997c478bd9Sstevel@tonic-gate 		niagara_erratum_39 = 1;
1007c478bd9Sstevel@tonic-gate #endif
1017c478bd9Sstevel@tonic-gate 	cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* XXXQ */
1047c478bd9Sstevel@tonic-gate 	at_flags = EF_SPARC_SUN_US3 | EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/*
1077c478bd9Sstevel@tonic-gate 	 * Use the maximum number of contexts available for Spitfire unless
1087c478bd9Sstevel@tonic-gate 	 * it has been tuned for debugging.
1097c478bd9Sstevel@tonic-gate 	 * We are checking against 0 here since this value can be patched
1107c478bd9Sstevel@tonic-gate 	 * while booting.  It can not be patched via /etc/system since it
1117c478bd9Sstevel@tonic-gate 	 * will be patched too late and thus cause the system to panic.
1127c478bd9Sstevel@tonic-gate 	 */
1137c478bd9Sstevel@tonic-gate 	if (nctxs == 0)
1147c478bd9Sstevel@tonic-gate 		nctxs = MAX_NCTXS;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (use_page_coloring) {
1177c478bd9Sstevel@tonic-gate 		do_pg_coloring = 1;
1187c478bd9Sstevel@tonic-gate 		if (use_virtual_coloring)
1197c478bd9Sstevel@tonic-gate 			do_virtual_coloring = 1;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 	/*
1227c478bd9Sstevel@tonic-gate 	 * Initalize supported page sizes information before the PD.
1237c478bd9Sstevel@tonic-gate 	 * If no information is available, then initialize the
1247c478bd9Sstevel@tonic-gate 	 * mmu_exported_pagesize_mask to a reasonable value for that processor.
1257c478bd9Sstevel@tonic-gate 	 */
1267c478bd9Sstevel@tonic-gate 	mmu_exported_pagesize_mask = get_cpu_pagesizes();
1277c478bd9Sstevel@tonic-gate 	if (mmu_exported_pagesize_mask <= 0) {
1287c478bd9Sstevel@tonic-gate 		mmu_exported_pagesize_mask = (1 << TTE8K) | (1 << TTE64K) |
1297c478bd9Sstevel@tonic-gate 		    (1 << TTE4M) | (1 << TTE256M);
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/*
1337c478bd9Sstevel@tonic-gate 	 * Tune pp_slots to use up to 1/8th of the tlb entries.
1347c478bd9Sstevel@tonic-gate 	 */
1357c478bd9Sstevel@tonic-gate 	pp_slots = MIN(8, MAXPP_SLOTS);
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/*
1387c478bd9Sstevel@tonic-gate 	 * Block stores invalidate all pages of the d$ so pagecopy
1397c478bd9Sstevel@tonic-gate 	 * et. al. do not need virtual translations with virtual
1407c478bd9Sstevel@tonic-gate 	 * coloring taken into consideration.
1417c478bd9Sstevel@tonic-gate 	 */
1427c478bd9Sstevel@tonic-gate 	pp_consistent_coloring = 0;
1437c478bd9Sstevel@tonic-gate 	isa_list =
1447c478bd9Sstevel@tonic-gate 	    "sparcv9 sparcv8plus sparcv8 sparcv8-fsmuld sparcv7 "
1457c478bd9Sstevel@tonic-gate 	    "sparc sparcv9+vis sparcv9+vis2 sparcv8plus+vis sparcv8plus+vis2";
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	cpu_hwcap_flags |= AV_SPARC_ASI_BLK_INIT;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/*
1507c478bd9Sstevel@tonic-gate 	 * On Spitfire, there's a hole in the address space
1517c478bd9Sstevel@tonic-gate 	 * that we must never map (the hardware only support 44-bits of
1527c478bd9Sstevel@tonic-gate 	 * virtual address).  Later CPUs are expected to have wider
1537c478bd9Sstevel@tonic-gate 	 * supported address ranges.
1547c478bd9Sstevel@tonic-gate 	 *
1557c478bd9Sstevel@tonic-gate 	 * See address map on p23 of the UltraSPARC 1 user's manual.
1567c478bd9Sstevel@tonic-gate 	 */
1577c478bd9Sstevel@tonic-gate /* XXXQ get from machine description */
1587c478bd9Sstevel@tonic-gate 	hole_start = (caddr_t)0x80000000000ull;
1597c478bd9Sstevel@tonic-gate 	hole_end = (caddr_t)0xfffff80000000000ull;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/*
1627c478bd9Sstevel@tonic-gate 	 * The kpm mapping window.
1637c478bd9Sstevel@tonic-gate 	 * kpm_size:
1647c478bd9Sstevel@tonic-gate 	 *	The size of a single kpm range.
1657c478bd9Sstevel@tonic-gate 	 *	The overall size will be: kpm_size * vac_colors.
1667c478bd9Sstevel@tonic-gate 	 * kpm_vbase:
1677c478bd9Sstevel@tonic-gate 	 *	The virtual start address of the kpm range within the kernel
1687c478bd9Sstevel@tonic-gate 	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
1697c478bd9Sstevel@tonic-gate 	 */
1707c478bd9Sstevel@tonic-gate 	kpm_size = (size_t)(2ull * 1024 * 1024 * 1024 * 1024); /* 2TB */
1717c478bd9Sstevel@tonic-gate 	kpm_size_shift = 41;
1727c478bd9Sstevel@tonic-gate 	kpm_vbase = (caddr_t)0xfffffa0000000000ull; /* 16EB - 6TB */
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	/*
1757c478bd9Sstevel@tonic-gate 	 * The traptrace code uses either %tick or %stick for
1767c478bd9Sstevel@tonic-gate 	 * timestamping.  We have %stick so we can use it.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	traptrace_use_stick = 1;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/*
1817c478bd9Sstevel@tonic-gate 	 * sun4v provides demap_all
1827c478bd9Sstevel@tonic-gate 	 */
1837c478bd9Sstevel@tonic-gate 	if (!disable_delay_tlb_flush)
1847c478bd9Sstevel@tonic-gate 		delay_tlb_flush = 1;
1857c478bd9Sstevel@tonic-gate 	/*
1867c478bd9Sstevel@tonic-gate 	 * Niagara has a performance counter overflow interrupt
1877c478bd9Sstevel@tonic-gate 	 */
1887c478bd9Sstevel@tonic-gate 	cpc_has_overflow_intr = 1;
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate #define	MB	 * 1024 * 1024
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * Set the magic constants of the implementation.
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate void
1967c478bd9Sstevel@tonic-gate cpu_fiximp(struct cpu_node *cpunode)
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate 	extern int vac_size, vac_shift;
1997c478bd9Sstevel@tonic-gate 	extern uint_t vac_mask;
2007c478bd9Sstevel@tonic-gate 	int i, a;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/*
2037c478bd9Sstevel@tonic-gate 	 * The assumption here is that fillsysinfo will eventually
2047c478bd9Sstevel@tonic-gate 	 * have code to fill this info in from the PD.
2057c478bd9Sstevel@tonic-gate 	 * We hard code this for niagara now.
2067c478bd9Sstevel@tonic-gate 	 * Once the PD access library is done this code
2077c478bd9Sstevel@tonic-gate 	 * might need to be changed to get the info from the PD
2087c478bd9Sstevel@tonic-gate 	 */
2097c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_size == 0)
2107c478bd9Sstevel@tonic-gate 		cpunode->ecache_size = 3 MB;
2117c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_linesize == 0)
2127c478bd9Sstevel@tonic-gate 		cpunode->ecache_linesize = 64;
2137c478bd9Sstevel@tonic-gate 	if (cpunode->ecache_associativity == 0)
2147c478bd9Sstevel@tonic-gate 		cpunode->ecache_associativity = 12;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	cpunode->ecache_setsize =
2177c478bd9Sstevel@tonic-gate 	    cpunode->ecache_size / cpunode->ecache_associativity;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (ecache_setsize == 0)
2207c478bd9Sstevel@tonic-gate 		ecache_setsize = cpunode->ecache_setsize;
2217c478bd9Sstevel@tonic-gate 	if (ecache_alignsize == 0)
2227c478bd9Sstevel@tonic-gate 		ecache_alignsize = cpunode->ecache_linesize;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	vac_size = S_VAC_SIZE;
2257c478bd9Sstevel@tonic-gate 	vac_mask = MMU_PAGEMASK & (vac_size - 1);
2267c478bd9Sstevel@tonic-gate 	i = 0; a = vac_size;
2277c478bd9Sstevel@tonic-gate 	while (a >>= 1)
2287c478bd9Sstevel@tonic-gate 		++i;
2297c478bd9Sstevel@tonic-gate 	vac_shift = i;
2307c478bd9Sstevel@tonic-gate 	shm_alignment = vac_size;
2317c478bd9Sstevel@tonic-gate 	vac = 0;
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate static int niagara_cpucnt;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate void
2377c478bd9Sstevel@tonic-gate cpu_init_private(struct cpu *cp)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	extern int niagara_kstat_init(void);
2407c478bd9Sstevel@tonic-gate 
241*70f54eadSesaxe 	/*
242*70f54eadSesaxe 	 * This code change assumes that the virtual cpu ids are identical
243*70f54eadSesaxe 	 * to the physical cpu ids which is true for ontario but not for
244*70f54eadSesaxe 	 * niagara in general.
245*70f54eadSesaxe 	 * This is a temporary fix which will later be modified to obtain
246*70f54eadSesaxe 	 * the execution unit sharing information from MD table.
247*70f54eadSesaxe 	 */
248*70f54eadSesaxe 	cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id / 4);
249*70f54eadSesaxe 
2507c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
2517c478bd9Sstevel@tonic-gate 	if (niagara_cpucnt++ == 0) {
2527c478bd9Sstevel@tonic-gate 		(void) niagara_kstat_init();
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate void
2577c478bd9Sstevel@tonic-gate cpu_uninit_private(struct cpu *cp)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	extern int niagara_kstat_fini(void);
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
2627c478bd9Sstevel@tonic-gate 	if (--niagara_cpucnt == 0) {
2637c478bd9Sstevel@tonic-gate 		(void) niagara_kstat_fini();
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate  * On Niagara, any flush will cause all preceding stores to be
2697c478bd9Sstevel@tonic-gate  * synchronized wrt the i$, regardless of address or ASI.  In fact,
2707c478bd9Sstevel@tonic-gate  * the address is ignored, so we always flush address 0.
2717c478bd9Sstevel@tonic-gate  */
2727c478bd9Sstevel@tonic-gate void
2737c478bd9Sstevel@tonic-gate dtrace_flush_sec(uintptr_t addr)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	doflush(0);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate #define	IS_FLOAT(i) (((i) & 0x1000000) != 0)
2797c478bd9Sstevel@tonic-gate #define	IS_IBIT_SET(x)	(x & 0x2000)
2807c478bd9Sstevel@tonic-gate #define	IS_VIS1(op, op3)(op == 2 && op3 == 0x36)
2817c478bd9Sstevel@tonic-gate #define	IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(op, op3, asi)		\
2827c478bd9Sstevel@tonic-gate 		(op == 3 && (op3 == IOP_V8_LDDFA ||		\
2837c478bd9Sstevel@tonic-gate 		op3 == IOP_V8_STDFA) &&	asi > ASI_SNFL)
2847c478bd9Sstevel@tonic-gate int
2857c478bd9Sstevel@tonic-gate vis1_partial_support(struct regs *rp, k_siginfo_t *siginfo, uint_t *fault)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	char *badaddr;
2887c478bd9Sstevel@tonic-gate 	int instr;
2897c478bd9Sstevel@tonic-gate 	uint_t	optype, op3, asi;
2907c478bd9Sstevel@tonic-gate 	uint_t	rd, ignor;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	ASSERT(USERMODE(rp->r_tstate));
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	instr = fetch_user_instr((caddr_t)rp->r_pc);
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	rd = (instr >> 25) & 0x1f;
2977c478bd9Sstevel@tonic-gate 	optype = (instr >> 30) & 0x3;
2987c478bd9Sstevel@tonic-gate 	op3 = (instr >> 19) & 0x3f;
2997c478bd9Sstevel@tonic-gate 	ignor = (instr >> 5) & 0xff;
3007c478bd9Sstevel@tonic-gate 	if (IS_IBIT_SET(instr)) {
3017c478bd9Sstevel@tonic-gate 		asi = (uint32_t)((rp->r_tstate >> TSTATE_ASI_SHIFT) &
3027c478bd9Sstevel@tonic-gate 		    TSTATE_ASI_MASK);
3037c478bd9Sstevel@tonic-gate 	} else {
3047c478bd9Sstevel@tonic-gate 		asi = ignor;
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	if (!IS_VIS1(optype, op3) &&
3087c478bd9Sstevel@tonic-gate 	    !IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(optype, op3, asi)) {
3097c478bd9Sstevel@tonic-gate 		return (-1);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 	switch (simulate_unimp(rp, &badaddr)) {
3127c478bd9Sstevel@tonic-gate 	case SIMU_RETRY:
3137c478bd9Sstevel@tonic-gate 		break;	/* regs are already set up */
3147c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	case SIMU_SUCCESS:
3177c478bd9Sstevel@tonic-gate 		/*
3187c478bd9Sstevel@tonic-gate 		 * skip the successfully
3197c478bd9Sstevel@tonic-gate 		 * simulated instruction
3207c478bd9Sstevel@tonic-gate 		 */
3217c478bd9Sstevel@tonic-gate 		rp->r_pc = rp->r_npc;
3227c478bd9Sstevel@tonic-gate 		rp->r_npc += 4;
3237c478bd9Sstevel@tonic-gate 		break;
3247c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	case SIMU_FAULT:
3277c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGSEGV;
3287c478bd9Sstevel@tonic-gate 		siginfo->si_code = SEGV_MAPERR;
3297c478bd9Sstevel@tonic-gate 		siginfo->si_addr = badaddr;
3307c478bd9Sstevel@tonic-gate 		*fault = FLTBOUNDS;
3317c478bd9Sstevel@tonic-gate 		break;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	case SIMU_DZERO:
3347c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGFPE;
3357c478bd9Sstevel@tonic-gate 		siginfo->si_code = FPE_INTDIV;
3367c478bd9Sstevel@tonic-gate 		siginfo->si_addr = (caddr_t)rp->r_pc;
3377c478bd9Sstevel@tonic-gate 		*fault = FLTIZDIV;
3387c478bd9Sstevel@tonic-gate 		break;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	case SIMU_UNALIGN:
3417c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGBUS;
3427c478bd9Sstevel@tonic-gate 		siginfo->si_code = BUS_ADRALN;
3437c478bd9Sstevel@tonic-gate 		siginfo->si_addr = badaddr;
3447c478bd9Sstevel@tonic-gate 		*fault = FLTACCESS;
3457c478bd9Sstevel@tonic-gate 		break;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	case SIMU_ILLEGAL:
3487c478bd9Sstevel@tonic-gate 	default:
3497c478bd9Sstevel@tonic-gate 		siginfo->si_signo = SIGILL;
3507c478bd9Sstevel@tonic-gate 		op3 = (instr >> 19) & 0x3F;
3517c478bd9Sstevel@tonic-gate 		if ((IS_FLOAT(instr) && (op3 == IOP_V8_STQFA) ||
3527c478bd9Sstevel@tonic-gate 		    (op3 == IOP_V8_STDFA)))
3537c478bd9Sstevel@tonic-gate 			siginfo->si_code = ILL_ILLADR;
3547c478bd9Sstevel@tonic-gate 		else
3557c478bd9Sstevel@tonic-gate 			siginfo->si_code = ILL_ILLOPC;
3567c478bd9Sstevel@tonic-gate 		siginfo->si_addr = (caddr_t)rp->r_pc;
3577c478bd9Sstevel@tonic-gate 		*fault = FLTILL;
3587c478bd9Sstevel@tonic-gate 		break;
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 	return (0);
3617c478bd9Sstevel@tonic-gate }
362