xref: /titanic_44/usr/src/uts/sparc/v9/fpu/v9instr.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 /* Integer Unit simulator for Sparc FPU simulator. */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpu_simulator.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/fpu/globals.h>
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/vis_simulator.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/asi.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/simulate.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/model.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #define	FPU_REG_FIELD uint32_reg	/* Coordinate with FPU_REGS_TYPE. */
41*7c478bd9Sstevel@tonic-gate #define	FPU_DREG_FIELD uint64_reg	/* Coordinate with FPU_DREGS_TYPE. */
42*7c478bd9Sstevel@tonic-gate #define	FPU_FSR_FIELD uint64_reg	/* Coordinate with V9_FPU_FSR_TYPE. */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * Simulator for loads and stores between floating-point unit and memory.
46*7c478bd9Sstevel@tonic-gate  */
47*7c478bd9Sstevel@tonic-gate enum ftt_type
fldst(fp_simd_type * pfpsd,fp_inst_type pinst,struct regs * pregs,void * prw)48*7c478bd9Sstevel@tonic-gate fldst(
49*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,	/* FPU simulator data. */
50*7c478bd9Sstevel@tonic-gate 	fp_inst_type	pinst,	/* FPU instruction to simulate. */
51*7c478bd9Sstevel@tonic-gate 	struct regs	*pregs,	/* Pointer to PCB image of registers. */
52*7c478bd9Sstevel@tonic-gate 	void		*prw)	/* Pointer to locals and ins. */
53*7c478bd9Sstevel@tonic-gate {
54*7c478bd9Sstevel@tonic-gate 	uint32_t sz_bits, asi = 0;
55*7c478bd9Sstevel@tonic-gate 	uint64_t fea, tea;
56*7c478bd9Sstevel@tonic-gate 	uint64_t *ea;
57*7c478bd9Sstevel@tonic-gate 	enum ftt_type   ftt;
58*7c478bd9Sstevel@tonic-gate 	char *badaddr = (caddr_t)(-1);
59*7c478bd9Sstevel@tonic-gate 	union {
60*7c478bd9Sstevel@tonic-gate 		fp_inst_type	inst;
61*7c478bd9Sstevel@tonic-gate 		int32_t		i;
62*7c478bd9Sstevel@tonic-gate 	} fp;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	fp.inst = pinst;
65*7c478bd9Sstevel@tonic-gate 	if ((pinst.op3 >> 4) & 1) {
66*7c478bd9Sstevel@tonic-gate 		if (pinst.ibit) {
67*7c478bd9Sstevel@tonic-gate 			asi = (uint32_t)((pregs->r_tstate >> TSTATE_ASI_SHIFT) &
68*7c478bd9Sstevel@tonic-gate 			    TSTATE_ASI_MASK);
69*7c478bd9Sstevel@tonic-gate 		} else {
70*7c478bd9Sstevel@tonic-gate 			asi = (fp.i >> 5) & 0xff;
71*7c478bd9Sstevel@tonic-gate 		}
72*7c478bd9Sstevel@tonic-gate 		/* check for ld/st alternate and highest defined V9 asi */
73*7c478bd9Sstevel@tonic-gate 		if (((pinst.op3 & 0x30) == 0x30) && (asi > ASI_SNFL))
74*7c478bd9Sstevel@tonic-gate 			return (vis_fldst(pfpsd, pinst, pregs, prw, asi));
75*7c478bd9Sstevel@tonic-gate 	}
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	if (pinst.ibit == 0) {	/* effective address = rs1 + rs2 */
78*7c478bd9Sstevel@tonic-gate 		ftt = read_iureg(pfpsd, pinst.rs1, pregs, prw, &fea);
79*7c478bd9Sstevel@tonic-gate 		if (ftt != ftt_none)
80*7c478bd9Sstevel@tonic-gate 			return (ftt);
81*7c478bd9Sstevel@tonic-gate 		ftt = read_iureg(pfpsd, pinst.rs2, pregs, prw, &tea);
82*7c478bd9Sstevel@tonic-gate 		if (ftt != ftt_none)
83*7c478bd9Sstevel@tonic-gate 			return (ftt);
84*7c478bd9Sstevel@tonic-gate 		ea = (uint64_t *)(fea + tea);
85*7c478bd9Sstevel@tonic-gate 	} else {		/* effective address = rs1 + imm13 */
86*7c478bd9Sstevel@tonic-gate 				/* Extract simm13 field. */
87*7c478bd9Sstevel@tonic-gate 		fea = (uint64_t)((fp.i << 19) >> 19);
88*7c478bd9Sstevel@tonic-gate 		ftt = read_iureg(pfpsd, pinst.rs1, pregs, prw, &tea);
89*7c478bd9Sstevel@tonic-gate 		if (ftt != ftt_none)
90*7c478bd9Sstevel@tonic-gate 			return (ftt);
91*7c478bd9Sstevel@tonic-gate 		ea = (uint64_t *)(fea + tea);
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 	sz_bits = pinst.op3 & 0x3;
94*7c478bd9Sstevel@tonic-gate 	switch (sz_bits) {		/* map size bits to a number */
95*7c478bd9Sstevel@tonic-gate 	case 0:					/* ldf{a}/stf{a} */
96*7c478bd9Sstevel@tonic-gate 		/* Must be word-aligned. */
97*7c478bd9Sstevel@tonic-gate 		if (((uintptr_t)ea & 0x3) != 0)
98*7c478bd9Sstevel@tonic-gate 			return (ftt_alignment);
99*7c478bd9Sstevel@tonic-gate 		break;
100*7c478bd9Sstevel@tonic-gate 	case 1: if (pinst.rd == 0) {		/* ldfsr/stfsr */
101*7c478bd9Sstevel@tonic-gate 			/* Must be word-aligned. */
102*7c478bd9Sstevel@tonic-gate 			if (((uintptr_t)ea & 0x3) != 0)
103*7c478bd9Sstevel@tonic-gate 				return (ftt_alignment);
104*7c478bd9Sstevel@tonic-gate 		} else {			/* ldxfsr/stxfsr */
105*7c478bd9Sstevel@tonic-gate 			/* Must be extword-aligned. */
106*7c478bd9Sstevel@tonic-gate 			if (((uintptr_t)ea & 0x7) != 0)
107*7c478bd9Sstevel@tonic-gate 				return (ftt_alignment);
108*7c478bd9Sstevel@tonic-gate 		}
109*7c478bd9Sstevel@tonic-gate 		break;
110*7c478bd9Sstevel@tonic-gate 	case 2:					/* ldqf{a}/stqf{a} */
111*7c478bd9Sstevel@tonic-gate 		/* Require only word alignment. */
112*7c478bd9Sstevel@tonic-gate 		if (((uintptr_t)ea & 0x3) != 0)
113*7c478bd9Sstevel@tonic-gate 			return (ftt_alignment);
114*7c478bd9Sstevel@tonic-gate 		break;
115*7c478bd9Sstevel@tonic-gate 	case 3:					/* lddf{a}/stdf{a} */
116*7c478bd9Sstevel@tonic-gate 		if (get_udatamodel() == DATAMODEL_ILP32) {
117*7c478bd9Sstevel@tonic-gate 			/* Require 64 bit-alignment. */
118*7c478bd9Sstevel@tonic-gate 			if (((uintptr_t)ea & 0x7) != 0)
119*7c478bd9Sstevel@tonic-gate 				return (ftt_alignment);
120*7c478bd9Sstevel@tonic-gate 		} else {
121*7c478bd9Sstevel@tonic-gate 			if (((uintptr_t)ea & 0x3) != 0)
122*7c478bd9Sstevel@tonic-gate 				return (ftt_alignment);
123*7c478bd9Sstevel@tonic-gate 		}
124*7c478bd9Sstevel@tonic-gate 	}
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	pfpsd->fp_trapaddr = (caddr_t)ea; /* setup bad addr in case we trap */
127*7c478bd9Sstevel@tonic-gate 	if ((pinst.op3 >> 2) & 1)	/* store */
128*7c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_READ;
129*7c478bd9Sstevel@tonic-gate 	else
130*7c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_WRITE;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	switch (do_unaligned(pregs, &badaddr)) {
133*7c478bd9Sstevel@tonic-gate 	case SIMU_FAULT:
134*7c478bd9Sstevel@tonic-gate 		return (ftt_fault);
135*7c478bd9Sstevel@tonic-gate 	case SIMU_ILLEGAL:
136*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
137*7c478bd9Sstevel@tonic-gate 	case SIMU_SUCCESS:
138*7c478bd9Sstevel@tonic-gate 		break;
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 	pregs->r_pc = pregs->r_npc;	/* Do not retry emulated instruction. */
141*7c478bd9Sstevel@tonic-gate 	pregs->r_npc += 4;
142*7c478bd9Sstevel@tonic-gate 	return (ftt_none);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate  * Floating-point conditional moves between floating point unit registers.
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate static enum ftt_type
fmovcc_fcc(fp_simd_type * pfpsd,fp_inst_type inst,fsr_type * pfsr,enum cc_type cc)149*7c478bd9Sstevel@tonic-gate fmovcc_fcc(
150*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,	/* Pointer to fpu simulator data */
151*7c478bd9Sstevel@tonic-gate 	fp_inst_type	inst,	/* FPU instruction to simulate. */
152*7c478bd9Sstevel@tonic-gate 	fsr_type	*pfsr,	/* Pointer to image of FSR to read and write. */
153*7c478bd9Sstevel@tonic-gate 	enum cc_type	cc)	/* FSR condition code field from fcc[0-3] */
154*7c478bd9Sstevel@tonic-gate {
155*7c478bd9Sstevel@tonic-gate 	uint32_t	moveit;
156*7c478bd9Sstevel@tonic-gate 	fsr_type	fsr;
157*7c478bd9Sstevel@tonic-gate 	enum fcc_type	fcc;
158*7c478bd9Sstevel@tonic-gate 	enum icc_type {
159*7c478bd9Sstevel@tonic-gate 		fmovn, fmovne, fmovlg, fmovul, fmovl, fmovug, fmovg, fmovu,
160*7c478bd9Sstevel@tonic-gate 		fmova, fmove, fmovue, fmovge, fmovuge, fmovle, fmovule, fmovo
161*7c478bd9Sstevel@tonic-gate 	} cond;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	fsr = *pfsr;
164*7c478bd9Sstevel@tonic-gate 	switch (cc) {
165*7c478bd9Sstevel@tonic-gate 	case fcc_0:
166*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc0;
167*7c478bd9Sstevel@tonic-gate 		break;
168*7c478bd9Sstevel@tonic-gate 	case fcc_1:
169*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc1;
170*7c478bd9Sstevel@tonic-gate 		break;
171*7c478bd9Sstevel@tonic-gate 	case fcc_2:
172*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc2;
173*7c478bd9Sstevel@tonic-gate 		break;
174*7c478bd9Sstevel@tonic-gate 	case fcc_3:
175*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc3;
176*7c478bd9Sstevel@tonic-gate 		break;
177*7c478bd9Sstevel@tonic-gate 	default:
178*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	cond = (enum icc_type) (inst.rs1 & 0xf);
182*7c478bd9Sstevel@tonic-gate 	switch (cond) {
183*7c478bd9Sstevel@tonic-gate 	case fmovn:
184*7c478bd9Sstevel@tonic-gate 		moveit = 0;
185*7c478bd9Sstevel@tonic-gate 		break;
186*7c478bd9Sstevel@tonic-gate 	case fmovl:
187*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_less;
188*7c478bd9Sstevel@tonic-gate 		break;
189*7c478bd9Sstevel@tonic-gate 	case fmovg:
190*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_greater;
191*7c478bd9Sstevel@tonic-gate 		break;
192*7c478bd9Sstevel@tonic-gate 	case fmovu:
193*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_unordered;
194*7c478bd9Sstevel@tonic-gate 		break;
195*7c478bd9Sstevel@tonic-gate 	case fmove:
196*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_equal;
197*7c478bd9Sstevel@tonic-gate 		break;
198*7c478bd9Sstevel@tonic-gate 	case fmovlg:
199*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_less) || (fcc == fcc_greater);
200*7c478bd9Sstevel@tonic-gate 		break;
201*7c478bd9Sstevel@tonic-gate 	case fmovul:
202*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_less);
203*7c478bd9Sstevel@tonic-gate 		break;
204*7c478bd9Sstevel@tonic-gate 	case fmovug:
205*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_greater);
206*7c478bd9Sstevel@tonic-gate 		break;
207*7c478bd9Sstevel@tonic-gate 	case fmovue:
208*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_equal);
209*7c478bd9Sstevel@tonic-gate 		break;
210*7c478bd9Sstevel@tonic-gate 	case fmovge:
211*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_greater) || (fcc == fcc_equal);
212*7c478bd9Sstevel@tonic-gate 		break;
213*7c478bd9Sstevel@tonic-gate 	case fmovle:
214*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_less) || (fcc == fcc_equal);
215*7c478bd9Sstevel@tonic-gate 		break;
216*7c478bd9Sstevel@tonic-gate 	case fmovne:
217*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_equal;
218*7c478bd9Sstevel@tonic-gate 		break;
219*7c478bd9Sstevel@tonic-gate 	case fmovuge:
220*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_less;
221*7c478bd9Sstevel@tonic-gate 		break;
222*7c478bd9Sstevel@tonic-gate 	case fmovule:
223*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_greater;
224*7c478bd9Sstevel@tonic-gate 		break;
225*7c478bd9Sstevel@tonic-gate 	case fmovo:
226*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_unordered;
227*7c478bd9Sstevel@tonic-gate 		break;
228*7c478bd9Sstevel@tonic-gate 	case fmova:
229*7c478bd9Sstevel@tonic-gate 		moveit = 1;
230*7c478bd9Sstevel@tonic-gate 		break;
231*7c478bd9Sstevel@tonic-gate 	default:
232*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 	if (moveit) {		/* Move fpu register. */
235*7c478bd9Sstevel@tonic-gate 		uint32_t nrs2, nrd;
236*7c478bd9Sstevel@tonic-gate 		uint32_t usr;
237*7c478bd9Sstevel@tonic-gate 		uint64_t lusr;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		nrs2 = inst.rs2;
240*7c478bd9Sstevel@tonic-gate 		nrd = inst.rd;
241*7c478bd9Sstevel@tonic-gate 		if (inst.prec < 2) {	/* fmovs */
242*7c478bd9Sstevel@tonic-gate 			_fp_unpack_word(pfpsd, &usr, nrs2);
243*7c478bd9Sstevel@tonic-gate 			_fp_pack_word(pfpsd, &usr, nrd);
244*7c478bd9Sstevel@tonic-gate 		} else {		/* fmovd */
245*7c478bd9Sstevel@tonic-gate 			/* fix register encoding */
246*7c478bd9Sstevel@tonic-gate 			if ((nrs2 & 1) == 1)
247*7c478bd9Sstevel@tonic-gate 				nrs2 = (nrs2 & 0x1e) | 0x20;
248*7c478bd9Sstevel@tonic-gate 			_fp_unpack_extword(pfpsd, &lusr, nrs2);
249*7c478bd9Sstevel@tonic-gate 			if ((nrd & 1) == 1)
250*7c478bd9Sstevel@tonic-gate 				nrd = (nrd & 0x1e) | 0x20;
251*7c478bd9Sstevel@tonic-gate 			_fp_pack_extword(pfpsd, &lusr, nrd);
252*7c478bd9Sstevel@tonic-gate 			if (inst.prec > 2) {		/* fmovq */
253*7c478bd9Sstevel@tonic-gate 				_fp_unpack_extword(pfpsd, &lusr, nrs2+2);
254*7c478bd9Sstevel@tonic-gate 				_fp_pack_extword(pfpsd, &lusr, nrd+2);
255*7c478bd9Sstevel@tonic-gate 			}
256*7c478bd9Sstevel@tonic-gate 		}
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 	return (ftt_none);
259*7c478bd9Sstevel@tonic-gate }
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate /*
262*7c478bd9Sstevel@tonic-gate  * Integer conditional moves between floating point unit registers.
263*7c478bd9Sstevel@tonic-gate  */
264*7c478bd9Sstevel@tonic-gate static enum ftt_type
fmovcc_icc(fp_simd_type * pfpsd,fp_inst_type inst,enum cc_type cc)265*7c478bd9Sstevel@tonic-gate fmovcc_icc(
266*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,	/* Pointer to fpu simulator data */
267*7c478bd9Sstevel@tonic-gate 	fp_inst_type	inst,	/* FPU instruction to simulate. */
268*7c478bd9Sstevel@tonic-gate 	enum cc_type	cc)	/* CCR condition code field from tstate */
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate 	int 	moveit;
271*7c478bd9Sstevel@tonic-gate 	enum icc_type {
272*7c478bd9Sstevel@tonic-gate 		fmovn, fmove, fmovle, fmovl, fmovleu, fmovcs, fmovneg, fmovvs,
273*7c478bd9Sstevel@tonic-gate 		fmova, fmovne, fmovg, fmovge, fmovgu, fmovcc, fmovpos, fmovvc
274*7c478bd9Sstevel@tonic-gate 	} cond;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	struct regs *pregs;
277*7c478bd9Sstevel@tonic-gate 	uint64_t tstate;
278*7c478bd9Sstevel@tonic-gate 	union {
279*7c478bd9Sstevel@tonic-gate 		uint32_t	i;
280*7c478bd9Sstevel@tonic-gate 		ccr_type	cc;
281*7c478bd9Sstevel@tonic-gate 	} ccr;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	pregs = lwptoregs(curthread->t_lwp);
284*7c478bd9Sstevel@tonic-gate 	tstate = pregs->r_tstate;
285*7c478bd9Sstevel@tonic-gate 	switch (cc) {
286*7c478bd9Sstevel@tonic-gate 	case icc:
287*7c478bd9Sstevel@tonic-gate 		ccr.i = (uint32_t)((tstate >> TSTATE_CCR_SHIFT) & 0xf);
288*7c478bd9Sstevel@tonic-gate 		break;
289*7c478bd9Sstevel@tonic-gate 	case xcc:
290*7c478bd9Sstevel@tonic-gate 		ccr.i = (uint32_t)(((tstate >> TSTATE_CCR_SHIFT) & 0xf0) >> 4);
291*7c478bd9Sstevel@tonic-gate 		break;
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	cond = (enum icc_type) (inst.rs1 & 0xf);
295*7c478bd9Sstevel@tonic-gate 	switch (cond) {
296*7c478bd9Sstevel@tonic-gate 	case fmovn:
297*7c478bd9Sstevel@tonic-gate 		moveit = 0;
298*7c478bd9Sstevel@tonic-gate 		break;
299*7c478bd9Sstevel@tonic-gate 	case fmove:
300*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.z);
301*7c478bd9Sstevel@tonic-gate 		break;
302*7c478bd9Sstevel@tonic-gate 	case fmovle:
303*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.z | (ccr.cc.n ^ ccr.cc.v));
304*7c478bd9Sstevel@tonic-gate 		break;
305*7c478bd9Sstevel@tonic-gate 	case fmovl:
306*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.n ^ ccr.cc.v);
307*7c478bd9Sstevel@tonic-gate 		break;
308*7c478bd9Sstevel@tonic-gate 	case fmovleu:
309*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.c | ccr.cc.z);
310*7c478bd9Sstevel@tonic-gate 		break;
311*7c478bd9Sstevel@tonic-gate 	case fmovcs:
312*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.c);
313*7c478bd9Sstevel@tonic-gate 		break;
314*7c478bd9Sstevel@tonic-gate 	case fmovneg:
315*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.n);
316*7c478bd9Sstevel@tonic-gate 		break;
317*7c478bd9Sstevel@tonic-gate 	case fmovvs:
318*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.v);
319*7c478bd9Sstevel@tonic-gate 		break;
320*7c478bd9Sstevel@tonic-gate 	case fmova:
321*7c478bd9Sstevel@tonic-gate 		moveit = 1;
322*7c478bd9Sstevel@tonic-gate 		break;
323*7c478bd9Sstevel@tonic-gate 	case fmovne:
324*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.z == 0);
325*7c478bd9Sstevel@tonic-gate 		break;
326*7c478bd9Sstevel@tonic-gate 	case fmovg:
327*7c478bd9Sstevel@tonic-gate 		moveit = (int)((ccr.cc.z | (ccr.cc.n ^ ccr.cc.v)) == 0);
328*7c478bd9Sstevel@tonic-gate 		break;
329*7c478bd9Sstevel@tonic-gate 	case fmovge:
330*7c478bd9Sstevel@tonic-gate 		moveit = (int)((ccr.cc.n ^ ccr.cc.v) == 0);
331*7c478bd9Sstevel@tonic-gate 		break;
332*7c478bd9Sstevel@tonic-gate 	case fmovgu:
333*7c478bd9Sstevel@tonic-gate 		moveit = (int)((ccr.cc.c | ccr.cc.z) == 0);
334*7c478bd9Sstevel@tonic-gate 		break;
335*7c478bd9Sstevel@tonic-gate 	case fmovcc:
336*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.c == 0);
337*7c478bd9Sstevel@tonic-gate 		break;
338*7c478bd9Sstevel@tonic-gate 	case fmovpos:
339*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.n == 0);
340*7c478bd9Sstevel@tonic-gate 		break;
341*7c478bd9Sstevel@tonic-gate 	case fmovvc:
342*7c478bd9Sstevel@tonic-gate 		moveit = (int)(ccr.cc.v == 0);
343*7c478bd9Sstevel@tonic-gate 		break;
344*7c478bd9Sstevel@tonic-gate 	default:
345*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
346*7c478bd9Sstevel@tonic-gate 	}
347*7c478bd9Sstevel@tonic-gate 	if (moveit) {		/* Move fpu register. */
348*7c478bd9Sstevel@tonic-gate 		uint32_t nrs2, nrd;
349*7c478bd9Sstevel@tonic-gate 		uint32_t usr;
350*7c478bd9Sstevel@tonic-gate 		uint64_t lusr;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 		nrs2 = inst.rs2;
353*7c478bd9Sstevel@tonic-gate 		nrd = inst.rd;
354*7c478bd9Sstevel@tonic-gate 		if (inst.prec < 2) {	/* fmovs */
355*7c478bd9Sstevel@tonic-gate 			_fp_unpack_word(pfpsd, &usr, nrs2);
356*7c478bd9Sstevel@tonic-gate 			_fp_pack_word(pfpsd, &usr, nrd);
357*7c478bd9Sstevel@tonic-gate 		} else {		/* fmovd */
358*7c478bd9Sstevel@tonic-gate 			/* fix register encoding */
359*7c478bd9Sstevel@tonic-gate 			if ((nrs2 & 1) == 1)
360*7c478bd9Sstevel@tonic-gate 				nrs2 = (nrs2 & 0x1e) | 0x20;
361*7c478bd9Sstevel@tonic-gate 			_fp_unpack_extword(pfpsd, &lusr, nrs2);
362*7c478bd9Sstevel@tonic-gate 			if ((nrd & 1) == 1)
363*7c478bd9Sstevel@tonic-gate 				nrd = (nrd & 0x1e) | 0x20;
364*7c478bd9Sstevel@tonic-gate 			_fp_pack_extword(pfpsd, &lusr, nrd);
365*7c478bd9Sstevel@tonic-gate 			if (inst.prec > 2) {		/* fmovq */
366*7c478bd9Sstevel@tonic-gate 				_fp_unpack_extword(pfpsd, &lusr, nrs2+2);
367*7c478bd9Sstevel@tonic-gate 				_fp_pack_extword(pfpsd, &lusr, nrd+2);
368*7c478bd9Sstevel@tonic-gate 			}
369*7c478bd9Sstevel@tonic-gate 		}
370*7c478bd9Sstevel@tonic-gate 	}
371*7c478bd9Sstevel@tonic-gate 	return (ftt_none);
372*7c478bd9Sstevel@tonic-gate }
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate /*
375*7c478bd9Sstevel@tonic-gate  * Simulator for moving fp register on condition (FMOVcc).
376*7c478bd9Sstevel@tonic-gate  * FMOVccq (Quad version of instruction) not supported by Ultra-1, so this
377*7c478bd9Sstevel@tonic-gate  * code must always be present.
378*7c478bd9Sstevel@tonic-gate  */
379*7c478bd9Sstevel@tonic-gate enum ftt_type
fmovcc(fp_simd_type * pfpsd,fp_inst_type inst,fsr_type * pfsr)380*7c478bd9Sstevel@tonic-gate fmovcc(
381*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,	/* Pointer to fpu simulator data */
382*7c478bd9Sstevel@tonic-gate 	fp_inst_type	inst,	/* FPU instruction to simulate. */
383*7c478bd9Sstevel@tonic-gate 	fsr_type	*pfsr)	/* Pointer to image of FSR to read and write. */
384*7c478bd9Sstevel@tonic-gate {
385*7c478bd9Sstevel@tonic-gate 	enum cc_type	opf_cc;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	opf_cc = (enum cc_type) ((inst.ibit << 2) | (inst.opcode >> 4));
388*7c478bd9Sstevel@tonic-gate 	if ((opf_cc == icc) || (opf_cc == xcc)) {
389*7c478bd9Sstevel@tonic-gate 		return (fmovcc_icc(pfpsd, inst, opf_cc));
390*7c478bd9Sstevel@tonic-gate 	} else {
391*7c478bd9Sstevel@tonic-gate 		return (fmovcc_fcc(pfpsd, inst, pfsr, opf_cc));
392*7c478bd9Sstevel@tonic-gate 	}
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate /*
396*7c478bd9Sstevel@tonic-gate  * Simulator for moving fp register on integer register condition (FMOVr).
397*7c478bd9Sstevel@tonic-gate  * FMOVrq (Quad version of instruction) not supported by Ultra-1, so this
398*7c478bd9Sstevel@tonic-gate  * code must always be present.
399*7c478bd9Sstevel@tonic-gate  */
400*7c478bd9Sstevel@tonic-gate enum ftt_type
fmovr(fp_simd_type * pfpsd,fp_inst_type inst)401*7c478bd9Sstevel@tonic-gate fmovr(
402*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,	/* Pointer to fpu simulator data */
403*7c478bd9Sstevel@tonic-gate 	fp_inst_type	inst)	/* FPU instruction to simulate. */
404*7c478bd9Sstevel@tonic-gate {
405*7c478bd9Sstevel@tonic-gate 	struct regs	*pregs;
406*7c478bd9Sstevel@tonic-gate 	ulong_t		*prw;
407*7c478bd9Sstevel@tonic-gate 	uint32_t	nrs1;
408*7c478bd9Sstevel@tonic-gate 	enum ftt_type	ftt;
409*7c478bd9Sstevel@tonic-gate 	enum rcond_type {
410*7c478bd9Sstevel@tonic-gate 		none, fmovre, fmovrlez, fmovrlz,
411*7c478bd9Sstevel@tonic-gate 		nnone, fmovrne, fmovrgz, fmovrgez
412*7c478bd9Sstevel@tonic-gate 	} rcond;
413*7c478bd9Sstevel@tonic-gate 	int64_t moveit, r;
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	nrs1 = inst.rs1;
416*7c478bd9Sstevel@tonic-gate 	if (nrs1 > 15)		/* rs1 must be a global register */
417*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
418*7c478bd9Sstevel@tonic-gate 	if (inst.ibit)		/* ibit must be unused */
419*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
420*7c478bd9Sstevel@tonic-gate 	pregs = lwptoregs(curthread->t_lwp);
421*7c478bd9Sstevel@tonic-gate 	prw = (ulong_t *)pregs->r_sp;
422*7c478bd9Sstevel@tonic-gate 	ftt = read_iureg(pfpsd, nrs1, pregs, prw, (uint64_t *)&r);
423*7c478bd9Sstevel@tonic-gate 	if (ftt != ftt_none)
424*7c478bd9Sstevel@tonic-gate 		return (ftt);
425*7c478bd9Sstevel@tonic-gate 	rcond = (enum rcond_type) (inst.opcode >> 3) & 7;
426*7c478bd9Sstevel@tonic-gate 	switch (rcond) {
427*7c478bd9Sstevel@tonic-gate 	case fmovre:
428*7c478bd9Sstevel@tonic-gate 		moveit = r == 0;
429*7c478bd9Sstevel@tonic-gate 		break;
430*7c478bd9Sstevel@tonic-gate 	case fmovrlez:
431*7c478bd9Sstevel@tonic-gate 		moveit = r <= 0;
432*7c478bd9Sstevel@tonic-gate 		break;
433*7c478bd9Sstevel@tonic-gate 	case fmovrlz:
434*7c478bd9Sstevel@tonic-gate 		moveit = r < 0;
435*7c478bd9Sstevel@tonic-gate 		break;
436*7c478bd9Sstevel@tonic-gate 	case fmovrne:
437*7c478bd9Sstevel@tonic-gate 		moveit = r != 0;
438*7c478bd9Sstevel@tonic-gate 		break;
439*7c478bd9Sstevel@tonic-gate 	case fmovrgz:
440*7c478bd9Sstevel@tonic-gate 		moveit = r > 0;
441*7c478bd9Sstevel@tonic-gate 		break;
442*7c478bd9Sstevel@tonic-gate 	case fmovrgez:
443*7c478bd9Sstevel@tonic-gate 		moveit = r >= 0;
444*7c478bd9Sstevel@tonic-gate 		break;
445*7c478bd9Sstevel@tonic-gate 	default:
446*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate 	if (moveit) {		/* Move fpu register. */
449*7c478bd9Sstevel@tonic-gate 		uint32_t nrs2, nrd;
450*7c478bd9Sstevel@tonic-gate 		uint32_t usr;
451*7c478bd9Sstevel@tonic-gate 		uint64_t lusr;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		nrs2 = inst.rs2;
454*7c478bd9Sstevel@tonic-gate 		nrd = inst.rd;
455*7c478bd9Sstevel@tonic-gate 		if (inst.prec < 2) {	/* fmovs */
456*7c478bd9Sstevel@tonic-gate 			_fp_unpack_word(pfpsd, &usr, nrs2);
457*7c478bd9Sstevel@tonic-gate 			_fp_pack_word(pfpsd, &usr, nrd);
458*7c478bd9Sstevel@tonic-gate 		} else {		/* fmovd */
459*7c478bd9Sstevel@tonic-gate 			_fp_unpack_extword(pfpsd, &lusr, nrs2);
460*7c478bd9Sstevel@tonic-gate 			_fp_pack_extword(pfpsd, &lusr, nrd);
461*7c478bd9Sstevel@tonic-gate 			if (inst.prec > 2) {		/* fmovq */
462*7c478bd9Sstevel@tonic-gate 				_fp_unpack_extword(pfpsd, &lusr, nrs2+2);
463*7c478bd9Sstevel@tonic-gate 				_fp_pack_extword(pfpsd, &lusr, nrd+2);
464*7c478bd9Sstevel@tonic-gate 			}
465*7c478bd9Sstevel@tonic-gate 		}
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	return (ftt_none);
468*7c478bd9Sstevel@tonic-gate }
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate /*
471*7c478bd9Sstevel@tonic-gate  * Move integer register on condition (MOVcc).
472*7c478bd9Sstevel@tonic-gate  */
473*7c478bd9Sstevel@tonic-gate enum ftt_type
movcc(fp_simd_type * pfpsd,fp_inst_type pinst,struct regs * pregs,void * prw,kfpu_t * pfpu)474*7c478bd9Sstevel@tonic-gate movcc(
475*7c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd, /* Pointer to fpu simulator data */
476*7c478bd9Sstevel@tonic-gate 	fp_inst_type    pinst,	/* FPU instruction to simulate. */
477*7c478bd9Sstevel@tonic-gate 	struct regs	*pregs,	/* Pointer to PCB image of registers. */
478*7c478bd9Sstevel@tonic-gate 	void		*prw,	/* Pointer to locals and ins. */
479*7c478bd9Sstevel@tonic-gate 	kfpu_t		*pfpu)	/* Pointer to FPU register block. */
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate {
482*7c478bd9Sstevel@tonic-gate 	fsr_type	fsr;
483*7c478bd9Sstevel@tonic-gate 	enum cc_type	cc;
484*7c478bd9Sstevel@tonic-gate 	enum fcc_type	fcc;
485*7c478bd9Sstevel@tonic-gate 	enum icc_type {
486*7c478bd9Sstevel@tonic-gate 		fmovn, fmovne, fmovlg, fmovul, fmovl, fmovug, fmovg, fmovu,
487*7c478bd9Sstevel@tonic-gate 		fmova, fmove, fmovue, fmovge, fmovuge, fmovle, fmovule, fmovo
488*7c478bd9Sstevel@tonic-gate 	} cond;
489*7c478bd9Sstevel@tonic-gate 	uint32_t moveit;
490*7c478bd9Sstevel@tonic-gate 	enum ftt_type ftt = ftt_none;
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	cc = (enum cc_type) (pinst.opcode >> 0x4) & 3;
493*7c478bd9Sstevel@tonic-gate 	fsr.ll = pfpu->fpu_fsr;
494*7c478bd9Sstevel@tonic-gate 	cond = (enum icc_type) (pinst.rs1 & 0xf);
495*7c478bd9Sstevel@tonic-gate 	switch (cc) {
496*7c478bd9Sstevel@tonic-gate 	case fcc_0:
497*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc0;
498*7c478bd9Sstevel@tonic-gate 		break;
499*7c478bd9Sstevel@tonic-gate 	case fcc_1:
500*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc1;
501*7c478bd9Sstevel@tonic-gate 		break;
502*7c478bd9Sstevel@tonic-gate 	case fcc_2:
503*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc2;
504*7c478bd9Sstevel@tonic-gate 		break;
505*7c478bd9Sstevel@tonic-gate 	case fcc_3:
506*7c478bd9Sstevel@tonic-gate 		fcc = fsr.fcc3;
507*7c478bd9Sstevel@tonic-gate 		break;
508*7c478bd9Sstevel@tonic-gate 	default:
509*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	switch (cond) {
513*7c478bd9Sstevel@tonic-gate 	case fmovn:
514*7c478bd9Sstevel@tonic-gate 		moveit = 0;
515*7c478bd9Sstevel@tonic-gate 		break;
516*7c478bd9Sstevel@tonic-gate 	case fmovl:
517*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_less;
518*7c478bd9Sstevel@tonic-gate 		break;
519*7c478bd9Sstevel@tonic-gate 	case fmovg:
520*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_greater;
521*7c478bd9Sstevel@tonic-gate 		break;
522*7c478bd9Sstevel@tonic-gate 	case fmovu:
523*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_unordered;
524*7c478bd9Sstevel@tonic-gate 		break;
525*7c478bd9Sstevel@tonic-gate 	case fmove:
526*7c478bd9Sstevel@tonic-gate 		moveit = fcc == fcc_equal;
527*7c478bd9Sstevel@tonic-gate 		break;
528*7c478bd9Sstevel@tonic-gate 	case fmovlg:
529*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_less) || (fcc == fcc_greater);
530*7c478bd9Sstevel@tonic-gate 		break;
531*7c478bd9Sstevel@tonic-gate 	case fmovul:
532*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_less);
533*7c478bd9Sstevel@tonic-gate 		break;
534*7c478bd9Sstevel@tonic-gate 	case fmovug:
535*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_greater);
536*7c478bd9Sstevel@tonic-gate 		break;
537*7c478bd9Sstevel@tonic-gate 	case fmovue:
538*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_unordered) || (fcc == fcc_equal);
539*7c478bd9Sstevel@tonic-gate 		break;
540*7c478bd9Sstevel@tonic-gate 	case fmovge:
541*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_greater) || (fcc == fcc_equal);
542*7c478bd9Sstevel@tonic-gate 		break;
543*7c478bd9Sstevel@tonic-gate 	case fmovle:
544*7c478bd9Sstevel@tonic-gate 		moveit = (fcc == fcc_less) || (fcc == fcc_equal);
545*7c478bd9Sstevel@tonic-gate 		break;
546*7c478bd9Sstevel@tonic-gate 	case fmovne:
547*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_equal;
548*7c478bd9Sstevel@tonic-gate 		break;
549*7c478bd9Sstevel@tonic-gate 	case fmovuge:
550*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_less;
551*7c478bd9Sstevel@tonic-gate 		break;
552*7c478bd9Sstevel@tonic-gate 	case fmovule:
553*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_greater;
554*7c478bd9Sstevel@tonic-gate 		break;
555*7c478bd9Sstevel@tonic-gate 	case fmovo:
556*7c478bd9Sstevel@tonic-gate 		moveit = fcc != fcc_unordered;
557*7c478bd9Sstevel@tonic-gate 		break;
558*7c478bd9Sstevel@tonic-gate 	case fmova:
559*7c478bd9Sstevel@tonic-gate 		moveit = 1;
560*7c478bd9Sstevel@tonic-gate 		break;
561*7c478bd9Sstevel@tonic-gate 	default:
562*7c478bd9Sstevel@tonic-gate 		return (ftt_unimplemented);
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 	if (moveit) {		/* Move fpu register. */
565*7c478bd9Sstevel@tonic-gate 		uint32_t nrd;
566*7c478bd9Sstevel@tonic-gate 		uint64_t r;
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 		nrd = pinst.rd;
569*7c478bd9Sstevel@tonic-gate 		if (pinst.ibit == 0) {	/* copy the value in r[rs2] */
570*7c478bd9Sstevel@tonic-gate 			uint32_t nrs2;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 			nrs2 = pinst.rs2;
573*7c478bd9Sstevel@tonic-gate 			ftt = read_iureg(pfpsd, nrs2, pregs, prw, &r);
574*7c478bd9Sstevel@tonic-gate 			if (ftt != ftt_none)
575*7c478bd9Sstevel@tonic-gate 				return (ftt);
576*7c478bd9Sstevel@tonic-gate 			ftt = write_iureg(pfpsd, nrd, pregs, prw, &r);
577*7c478bd9Sstevel@tonic-gate 		} else {		/* use sign_ext(simm11) */
578*7c478bd9Sstevel@tonic-gate 			union {
579*7c478bd9Sstevel@tonic-gate 				fp_inst_type	inst;
580*7c478bd9Sstevel@tonic-gate 				int32_t		i;
581*7c478bd9Sstevel@tonic-gate 			} fp;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 			fp.inst = pinst;	/* Extract simm11 field */
584*7c478bd9Sstevel@tonic-gate 			r = (fp.i << 21) >> 21;
585*7c478bd9Sstevel@tonic-gate 			ftt = write_iureg(pfpsd, nrd, pregs, prw, &r);
586*7c478bd9Sstevel@tonic-gate 		}
587*7c478bd9Sstevel@tonic-gate 	}
588*7c478bd9Sstevel@tonic-gate 	pregs->r_pc = pregs->r_npc;	/* Do not retry emulated instruction. */
589*7c478bd9Sstevel@tonic-gate 	pregs->r_npc += 4;
590*7c478bd9Sstevel@tonic-gate 	return (ftt);
591*7c478bd9Sstevel@tonic-gate }
592