xref: /onnv-gate/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * User Process Target Intel 32-bit component
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  * This file provides the ISA-dependent portion of the user process target.
33*0Sstevel@tonic-gate  * For more details on the implementation refer to mdb_proc.c.
34*0Sstevel@tonic-gate  */
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <mdb/mdb_proc.h>
37*0Sstevel@tonic-gate #include <mdb/mdb_kreg.h>
38*0Sstevel@tonic-gate #include <mdb/mdb_err.h>
39*0Sstevel@tonic-gate #include <mdb/mdb_ia32util.h>
40*0Sstevel@tonic-gate #include <mdb/mdb.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include <sys/frame.h>
43*0Sstevel@tonic-gate #include <libproc.h>
44*0Sstevel@tonic-gate #include <sys/fp.h>
45*0Sstevel@tonic-gate #include <ieeefp.h>
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate const mdb_tgt_regdesc_t pt_regdesc[] = {
48*0Sstevel@tonic-gate 	{ "gs", GS, MDB_TGT_R_EXPORT },
49*0Sstevel@tonic-gate 	{ "fs", FS, MDB_TGT_R_EXPORT },
50*0Sstevel@tonic-gate 	{ "es", ES, MDB_TGT_R_EXPORT },
51*0Sstevel@tonic-gate 	{ "ds", DS, MDB_TGT_R_EXPORT },
52*0Sstevel@tonic-gate 	{ "edi", EDI, MDB_TGT_R_EXPORT },
53*0Sstevel@tonic-gate 	{ "esi", ESI, MDB_TGT_R_EXPORT },
54*0Sstevel@tonic-gate 	{ "ebp", EBP, MDB_TGT_R_EXPORT },
55*0Sstevel@tonic-gate 	{ "kesp", ESP, MDB_TGT_R_EXPORT },
56*0Sstevel@tonic-gate 	{ "ebx", EBX, MDB_TGT_R_EXPORT },
57*0Sstevel@tonic-gate 	{ "edx", EDX, MDB_TGT_R_EXPORT },
58*0Sstevel@tonic-gate 	{ "ecx", ECX, MDB_TGT_R_EXPORT },
59*0Sstevel@tonic-gate 	{ "eax", EAX, MDB_TGT_R_EXPORT },
60*0Sstevel@tonic-gate 	{ "trapno", TRAPNO, MDB_TGT_R_EXPORT },
61*0Sstevel@tonic-gate 	{ "err", ERR, MDB_TGT_R_EXPORT },
62*0Sstevel@tonic-gate 	{ "eip", EIP, MDB_TGT_R_EXPORT },
63*0Sstevel@tonic-gate 	{ "cs", CS, MDB_TGT_R_EXPORT },
64*0Sstevel@tonic-gate 	{ "eflags", EFL, MDB_TGT_R_EXPORT },
65*0Sstevel@tonic-gate 	{ "esp", UESP, MDB_TGT_R_EXPORT },
66*0Sstevel@tonic-gate 	{ "ss", SS, MDB_TGT_R_EXPORT },
67*0Sstevel@tonic-gate 	{ NULL, 0, 0 }
68*0Sstevel@tonic-gate };
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate  * We cannot rely on pr_instr, because if we hit a breakpoint or the user has
72*0Sstevel@tonic-gate  * artifically modified memory, it will no longer be correct.
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate static uint8_t
pt_read_instr(mdb_tgt_t * t)75*0Sstevel@tonic-gate pt_read_instr(mdb_tgt_t *t)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
78*0Sstevel@tonic-gate 	uint8_t ret = 0;
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 	(void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[EIP]);
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	return (ret);
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate /*ARGSUSED*/
86*0Sstevel@tonic-gate int
pt_regs(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)87*0Sstevel@tonic-gate pt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate 	mdb_tgt_t *t = mdb.m_target;
90*0Sstevel@tonic-gate 	mdb_tgt_tid_t tid;
91*0Sstevel@tonic-gate 	prgregset_t grs;
92*0Sstevel@tonic-gate 	prgreg_t eflags;
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	if (argc != 0)
95*0Sstevel@tonic-gate 		return (DCMD_USAGE);
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
98*0Sstevel@tonic-gate 		mdb_warn("no process active\n");
99*0Sstevel@tonic-gate 		return (DCMD_ERR);
100*0Sstevel@tonic-gate 	}
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	if (Pstate(t->t_pshandle) == PS_LOST) {
103*0Sstevel@tonic-gate 		mdb_warn("debugger has lost control of process\n");
104*0Sstevel@tonic-gate 		return (DCMD_ERR);
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
108*0Sstevel@tonic-gate 		tid = (mdb_tgt_tid_t)addr;
109*0Sstevel@tonic-gate 	else
110*0Sstevel@tonic-gate 		tid = PTL_TID(t);
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	if (PTL_GETREGS(t, tid, grs) != 0) {
113*0Sstevel@tonic-gate 		mdb_warn("failed to get current register set");
114*0Sstevel@tonic-gate 		return (DCMD_ERR);
115*0Sstevel@tonic-gate 	}
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 	eflags = grs[EFL];
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%0?p %A\n",
120*0Sstevel@tonic-gate 	    grs[CS], grs[EAX], grs[EAX]);
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%0?p %A\n",
123*0Sstevel@tonic-gate 	    grs[DS], grs[EBX], grs[EBX]);
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%0?p %A\n",
126*0Sstevel@tonic-gate 	    grs[SS], grs[ECX], grs[ECX]);
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 	mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%0?p %A\n",
129*0Sstevel@tonic-gate 	    grs[ES], grs[EDX], grs[EDX]);
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 	mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%0?p %A\n",
132*0Sstevel@tonic-gate 	    grs[FS], grs[ESI], grs[ESI]);
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%0?p %A\n\n",
135*0Sstevel@tonic-gate 	    grs[GS], grs[EDI], grs[EDI]);
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	mdb_printf(" %%eip = 0x%0?p %A\n", grs[EIP], grs[EIP]);
138*0Sstevel@tonic-gate 	mdb_printf(" %%ebp = 0x%0?p\n", grs[EBP]);
139*0Sstevel@tonic-gate 	mdb_printf("%%kesp = 0x%0?p\n\n", grs[ESP]);
140*0Sstevel@tonic-gate 	mdb_printf("%%eflags = 0x%08x\n", eflags);
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	mdb_printf("  id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
143*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_ID_MASK) >> KREG_EFLAGS_ID_SHIFT,
144*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_VIP_MASK) >> KREG_EFLAGS_VIP_SHIFT,
145*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_VIF_MASK) >> KREG_EFLAGS_VIF_SHIFT,
146*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_AC_MASK) >> KREG_EFLAGS_AC_SHIFT,
147*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_VM_MASK) >> KREG_EFLAGS_VM_SHIFT,
148*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_RF_MASK) >> KREG_EFLAGS_RF_SHIFT,
149*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_NT_MASK) >> KREG_EFLAGS_NT_SHIFT,
150*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_IOPL_MASK) >> KREG_EFLAGS_IOPL_SHIFT);
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	mdb_printf("  status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n\n",
153*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_OF_MASK) ? "OF" : "of",
154*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_DF_MASK) ? "DF" : "df",
155*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_IF_MASK) ? "IF" : "if",
156*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_TF_MASK) ? "TF" : "tf",
157*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_SF_MASK) ? "SF" : "sf",
158*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_ZF_MASK) ? "ZF" : "zf",
159*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_AF_MASK) ? "AF" : "af",
160*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf",
161*0Sstevel@tonic-gate 	    (eflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf");
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 	mdb_printf("   %%esp = 0x%0?x\n", grs[UESP]);
164*0Sstevel@tonic-gate 	mdb_printf("%%trapno = 0x%x\n", grs[TRAPNO]);
165*0Sstevel@tonic-gate 	mdb_printf("   %%err = 0x%x\n", grs[ERR]);
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	return (DCMD_OK);
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate static const char *
fpcw2str(uint32_t cw,char * buf,size_t nbytes)171*0Sstevel@tonic-gate fpcw2str(uint32_t cw, char *buf, size_t nbytes)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate 	char *end = buf + nbytes;
174*0Sstevel@tonic-gate 	char *p = buf;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	buf[0] = '\0';
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	/*
179*0Sstevel@tonic-gate 	 * Decode all masks in the 80387 control word.
180*0Sstevel@tonic-gate 	 */
181*0Sstevel@tonic-gate 	if (cw & FPIM)
182*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|IM");
183*0Sstevel@tonic-gate 	if (cw & FPDM)
184*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|DM");
185*0Sstevel@tonic-gate 	if (cw & FPZM)
186*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
187*0Sstevel@tonic-gate 	if (cw & FPOM)
188*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|OM");
189*0Sstevel@tonic-gate 	if (cw & FPUM)
190*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|UM");
191*0Sstevel@tonic-gate 	if (cw & FPPM)
192*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|PM");
193*0Sstevel@tonic-gate 	if (cw & FPPC)
194*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|PC");
195*0Sstevel@tonic-gate 	if (cw & FPRC)
196*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RC");
197*0Sstevel@tonic-gate 	if (cw & FPIC)
198*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|IC");
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	/*
201*0Sstevel@tonic-gate 	 * Decode precision, rounding, and infinity options in control word.
202*0Sstevel@tonic-gate 	 */
203*0Sstevel@tonic-gate 	if (cw & FPSIG24)
204*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG24");
205*0Sstevel@tonic-gate 	if (cw & FPSIG53)
206*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG53");
207*0Sstevel@tonic-gate 	if (cw & FPSIG64)
208*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG64");
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if ((cw & FPRC) == (FPRD|FPRU))
211*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
212*0Sstevel@tonic-gate 	else if (cw & FPRD)
213*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RD");
214*0Sstevel@tonic-gate 	else if (cw & FPRU)
215*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RU");
216*0Sstevel@tonic-gate 	else
217*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	if (cw & FPA)
220*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|A");
221*0Sstevel@tonic-gate 	else
222*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|P");
223*0Sstevel@tonic-gate 	if (cw & WFPB17)
224*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|WFPB17");
225*0Sstevel@tonic-gate 	if (cw & WFPB24)
226*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|WFPB24");
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	if (buf[0] == '|')
229*0Sstevel@tonic-gate 		return (buf + 1);
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	return ("0");
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate static const char *
fpsw2str(uint32_t cw,char * buf,size_t nbytes)235*0Sstevel@tonic-gate fpsw2str(uint32_t cw, char *buf, size_t nbytes)
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate 	char *end = buf + nbytes;
238*0Sstevel@tonic-gate 	char *p = buf;
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 	buf[0] = '\0';
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	/*
243*0Sstevel@tonic-gate 	 * Decode all masks in the 80387 status word.
244*0Sstevel@tonic-gate 	 */
245*0Sstevel@tonic-gate 	if (cw & FPS_IE)
246*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|IE");
247*0Sstevel@tonic-gate 	if (cw & FPS_DE)
248*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|DE");
249*0Sstevel@tonic-gate 	if (cw & FPS_ZE)
250*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
251*0Sstevel@tonic-gate 	if (cw & FPS_OE)
252*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|OE");
253*0Sstevel@tonic-gate 	if (cw & FPS_UE)
254*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|UE");
255*0Sstevel@tonic-gate 	if (cw & FPS_PE)
256*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|PE");
257*0Sstevel@tonic-gate 	if (cw & FPS_SF)
258*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|SF");
259*0Sstevel@tonic-gate 	if (cw & FPS_ES)
260*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|ES");
261*0Sstevel@tonic-gate 	if (cw & FPS_C0)
262*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|C0");
263*0Sstevel@tonic-gate 	if (cw & FPS_C1)
264*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|C1");
265*0Sstevel@tonic-gate 	if (cw & FPS_C2)
266*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|C2");
267*0Sstevel@tonic-gate 	if (cw & FPS_C3)
268*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|C3");
269*0Sstevel@tonic-gate 	if (cw & FPS_B)
270*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|B");
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	if (buf[0] == '|')
273*0Sstevel@tonic-gate 		return (buf + 1);
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	return ("0");
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate static const char *
fpmxcsr2str(uint32_t mxcsr,char * buf,size_t nbytes)279*0Sstevel@tonic-gate fpmxcsr2str(uint32_t mxcsr, char *buf, size_t nbytes)
280*0Sstevel@tonic-gate {
281*0Sstevel@tonic-gate 	char *end = buf + nbytes;
282*0Sstevel@tonic-gate 	char *p = buf;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	buf[0] = '\0';
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	/*
287*0Sstevel@tonic-gate 	 * Decode the MXCSR word
288*0Sstevel@tonic-gate 	 */
289*0Sstevel@tonic-gate 	if (mxcsr & SSE_IE)
290*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|IE");
291*0Sstevel@tonic-gate 	if (mxcsr & SSE_DE)
292*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|DE");
293*0Sstevel@tonic-gate 	if (mxcsr & SSE_ZE)
294*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
295*0Sstevel@tonic-gate 	if (mxcsr & SSE_OE)
296*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|OE");
297*0Sstevel@tonic-gate 	if (mxcsr & SSE_UE)
298*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|UE");
299*0Sstevel@tonic-gate 	if (mxcsr & SSE_PE)
300*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|PE");
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	if (mxcsr & SSE_DAZ)
303*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|DAZ");
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	if (mxcsr & SSE_IM)
306*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|IM");
307*0Sstevel@tonic-gate 	if (mxcsr & SSE_DM)
308*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|DM");
309*0Sstevel@tonic-gate 	if (mxcsr & SSE_ZM)
310*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
311*0Sstevel@tonic-gate 	if (mxcsr & SSE_OM)
312*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|OM");
313*0Sstevel@tonic-gate 	if (mxcsr & SSE_UM)
314*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|UM");
315*0Sstevel@tonic-gate 	if (mxcsr & SSE_PM)
316*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|PM");
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	if ((mxcsr & SSE_RC) == (SSE_RD|SSE_RU))
319*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
320*0Sstevel@tonic-gate 	else if (mxcsr & SSE_RD)
321*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RD");
322*0Sstevel@tonic-gate 	else if (mxcsr & SSE_RU)
323*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RU");
324*0Sstevel@tonic-gate 	else
325*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 	if (mxcsr & SSE_FZ)
328*0Sstevel@tonic-gate 		p += mdb_snprintf(p, (size_t)(end - p), "|FZ");
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	if (buf[0] == '|')
331*0Sstevel@tonic-gate 		return (buf + 1);
332*0Sstevel@tonic-gate 	return ("0");
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate /*ARGSUSED*/
336*0Sstevel@tonic-gate int
pt_fpregs(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)337*0Sstevel@tonic-gate pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
338*0Sstevel@tonic-gate {
339*0Sstevel@tonic-gate 	mdb_tgt_t *t = mdb.m_target;
340*0Sstevel@tonic-gate 	mdb_tgt_tid_t tid;
341*0Sstevel@tonic-gate 	uint32_t hw = FP_NO;
342*0Sstevel@tonic-gate 	uint_t sse = 0;
343*0Sstevel@tonic-gate 	prfpregset_t fprs;
344*0Sstevel@tonic-gate 	struct _fpstate fps;
345*0Sstevel@tonic-gate 	char buf[256];
346*0Sstevel@tonic-gate 	uint_t top;
347*0Sstevel@tonic-gate 	int i;
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	/*
350*0Sstevel@tonic-gate 	 * Union for overlaying _fpreg structure on to quad-precision
351*0Sstevel@tonic-gate 	 * floating-point value (long double).
352*0Sstevel@tonic-gate 	 */
353*0Sstevel@tonic-gate 	union {
354*0Sstevel@tonic-gate 		struct _fpreg reg;
355*0Sstevel@tonic-gate 		long double ld;
356*0Sstevel@tonic-gate 	} fpru;
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 	/*
359*0Sstevel@tonic-gate 	 * Array of strings corresponding to FPU tag word values (see
360*0Sstevel@tonic-gate 	 * section 7.3.6 of the Intel Programmer's Reference Manual).
361*0Sstevel@tonic-gate 	 */
362*0Sstevel@tonic-gate 	const char *tag_strings[] = { "valid", "zero", "special", "empty" };
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	if (argc != 0)
365*0Sstevel@tonic-gate 		return (DCMD_USAGE);
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
368*0Sstevel@tonic-gate 		mdb_warn("no process active\n");
369*0Sstevel@tonic-gate 		return (DCMD_ERR);
370*0Sstevel@tonic-gate 	}
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 	if (Pstate(t->t_pshandle) == PS_LOST) {
373*0Sstevel@tonic-gate 		mdb_warn("debugger has lost control of process\n");
374*0Sstevel@tonic-gate 		return (DCMD_ERR);
375*0Sstevel@tonic-gate 	}
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
378*0Sstevel@tonic-gate 		tid = (mdb_tgt_tid_t)addr;
379*0Sstevel@tonic-gate 	else
380*0Sstevel@tonic-gate 		tid = PTL_TID(t);
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 	if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw,
383*0Sstevel@tonic-gate 	    sizeof (hw), "libc.so", "_fp_hw") < 0 &&
384*0Sstevel@tonic-gate 	    mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw,
385*0Sstevel@tonic-gate 	    sizeof (hw), MDB_TGT_OBJ_EXEC, "_fp_hw") < 0)
386*0Sstevel@tonic-gate 		mdb_warn("failed to read _fp_hw value");
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 	if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse,
389*0Sstevel@tonic-gate 	    sizeof (sse), "libc.so", "_sse_hw") < 0 &&
390*0Sstevel@tonic-gate 	    mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse,
391*0Sstevel@tonic-gate 	    sizeof (sse), MDB_TGT_OBJ_EXEC, "_sse_hw") < 0)
392*0Sstevel@tonic-gate 		mdb_warn("failed to read _sse_hw value");
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	mdb_printf("_fp_hw 0x%02x (", hw);
395*0Sstevel@tonic-gate 	switch (hw) {
396*0Sstevel@tonic-gate 	case FP_SW:
397*0Sstevel@tonic-gate 		mdb_printf("80387 software emulator");
398*0Sstevel@tonic-gate 		break;
399*0Sstevel@tonic-gate 	case FP_287:
400*0Sstevel@tonic-gate 		mdb_printf("80287 chip");
401*0Sstevel@tonic-gate 		break;
402*0Sstevel@tonic-gate 	case FP_387:
403*0Sstevel@tonic-gate 		mdb_printf("80387 chip");
404*0Sstevel@tonic-gate 		break;
405*0Sstevel@tonic-gate 	case FP_486:
406*0Sstevel@tonic-gate 		mdb_printf("80486 chip");
407*0Sstevel@tonic-gate 		break;
408*0Sstevel@tonic-gate 	default:
409*0Sstevel@tonic-gate 		mdb_printf("no floating point support");
410*0Sstevel@tonic-gate 		break;
411*0Sstevel@tonic-gate 	}
412*0Sstevel@tonic-gate 	if (sse)
413*0Sstevel@tonic-gate 		mdb_printf(" with SSE");
414*0Sstevel@tonic-gate 	mdb_printf(")\n");
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	if (!(hw & FP_HW))
417*0Sstevel@tonic-gate 		return (DCMD_OK); /* just abort if no hardware present */
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	if (PTL_GETFPREGS(t, tid, &fprs) != 0) {
420*0Sstevel@tonic-gate 		mdb_warn("failed to get floating point registers");
421*0Sstevel@tonic-gate 		return (DCMD_ERR);
422*0Sstevel@tonic-gate 	}
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 	bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps));
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	fps.cw &= 0xffff;	/* control word is really 16 bits */
427*0Sstevel@tonic-gate 	fps.sw &= 0xffff;	/* status word is really 16 bits */
428*0Sstevel@tonic-gate 	fps.status &= 0xffff;	/* saved status word is really 16 bits */
429*0Sstevel@tonic-gate 	fps.cssel &= 0xffff;	/* %cs is really 16-bits */
430*0Sstevel@tonic-gate 	fps.datasel &= 0xffff;	/* %ds is really 16-bits too */
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate 	mdb_printf("cw     0x%04x (%s)\n", fps.cw,
433*0Sstevel@tonic-gate 	    fpcw2str(fps.cw, buf, sizeof (buf)));
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	top = (fps.sw & FPS_TOP) >> 11;
436*0Sstevel@tonic-gate 	mdb_printf("sw     0x%04x (TOP=0t%u) (%s)\n", fps.sw,
437*0Sstevel@tonic-gate 	    top, fpsw2str(fps.sw, buf, sizeof (buf)));
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	mdb_printf("xcp sw 0x%04x (%s)\n\n", fps.status,
440*0Sstevel@tonic-gate 	    fpsw2str(fps.status, buf, sizeof (buf)));
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	mdb_printf("ipoff  %a\n", fps.ipoff);
443*0Sstevel@tonic-gate 	mdb_printf("cssel  0x%x\n", fps.cssel);
444*0Sstevel@tonic-gate 	mdb_printf("dtoff  %a\n", fps.dataoff);
445*0Sstevel@tonic-gate 	mdb_printf("dtsel  0x%x\n\n", fps.datasel);
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	for (i = 0; i < 8; i++) {
448*0Sstevel@tonic-gate 		/*
449*0Sstevel@tonic-gate 		 * Recall that we need to use the current TOP-of-stack value to
450*0Sstevel@tonic-gate 		 * associate the _st[] index back to a physical register number,
451*0Sstevel@tonic-gate 		 * since tag word indices are physical register numbers.  Then
452*0Sstevel@tonic-gate 		 * to get the tag value, we shift over two bits for each tag
453*0Sstevel@tonic-gate 		 * index, and then grab the bottom two bits.
454*0Sstevel@tonic-gate 		 */
455*0Sstevel@tonic-gate 		uint_t tag_index = (i + top) & 7;
456*0Sstevel@tonic-gate 		uint_t tag_value = (fps.tag >> (tag_index * 2)) & 3;
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 		fpru.reg = fps._st[i];
459*0Sstevel@tonic-gate 		mdb_printf("%%st%d   0x%04x.%04x%04x%04x%04x = %lg %s\n",
460*0Sstevel@tonic-gate 		    i, fpru.reg.exponent,
461*0Sstevel@tonic-gate 		    fpru.reg.significand[3], fpru.reg.significand[2],
462*0Sstevel@tonic-gate 		    fpru.reg.significand[1], fpru.reg.significand[0],
463*0Sstevel@tonic-gate 		    fpru.ld, tag_strings[tag_value]);
464*0Sstevel@tonic-gate 	}
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	if (!sse)
467*0Sstevel@tonic-gate 		return (DCMD_OK);
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	mdb_printf("\nmxcsr  0x%04x (%s)\n", fps.mxcsr,
470*0Sstevel@tonic-gate 	    fpmxcsr2str(fps.mxcsr, buf, sizeof (buf)));
471*0Sstevel@tonic-gate 	mdb_printf("xcp    0x%04x (%s)\n\n", fps.xstatus,
472*0Sstevel@tonic-gate 	    fpmxcsr2str(fps.xstatus, buf, sizeof (buf)));
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate 	for (i = 0; i < 8; i++)
475*0Sstevel@tonic-gate 		mdb_printf("%%xmm%d  0x%08x%08x%08x%08x\n", i,
476*0Sstevel@tonic-gate 		    fps.xmm[i][3], fps.xmm[i][2],
477*0Sstevel@tonic-gate 		    fps.xmm[i][1], fps.xmm[i][0]);
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	return (DCMD_OK);
480*0Sstevel@tonic-gate }
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate /*ARGSUSED*/
483*0Sstevel@tonic-gate int
pt_getfpreg(mdb_tgt_t * t,mdb_tgt_tid_t tid,ushort_t rd_num,ushort_t rd_flags,mdb_tgt_reg_t * rp)484*0Sstevel@tonic-gate pt_getfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
485*0Sstevel@tonic-gate     ushort_t rd_flags, mdb_tgt_reg_t *rp)
486*0Sstevel@tonic-gate {
487*0Sstevel@tonic-gate 	return (set_errno(ENOTSUP));
488*0Sstevel@tonic-gate }
489*0Sstevel@tonic-gate 
490*0Sstevel@tonic-gate /*ARGSUSED*/
491*0Sstevel@tonic-gate int
pt_putfpreg(mdb_tgt_t * t,mdb_tgt_tid_t tid,ushort_t rd_num,ushort_t rd_flags,mdb_tgt_reg_t rval)492*0Sstevel@tonic-gate pt_putfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
493*0Sstevel@tonic-gate     ushort_t rd_flags, mdb_tgt_reg_t rval)
494*0Sstevel@tonic-gate {
495*0Sstevel@tonic-gate 	return (set_errno(ENOTSUP));
496*0Sstevel@tonic-gate }
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate /*ARGSUSED*/
499*0Sstevel@tonic-gate void
pt_addfpregs(mdb_tgt_t * t)500*0Sstevel@tonic-gate pt_addfpregs(mdb_tgt_t *t)
501*0Sstevel@tonic-gate {
502*0Sstevel@tonic-gate 	/* not implemented */
503*0Sstevel@tonic-gate }
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate /*ARGSUSED*/
506*0Sstevel@tonic-gate int
pt_frameregs(void * arglim,uintptr_t pc,uint_t argc,const long * argv,const mdb_tgt_gregset_t * gregs,boolean_t pc_faked)507*0Sstevel@tonic-gate pt_frameregs(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
508*0Sstevel@tonic-gate     const mdb_tgt_gregset_t *gregs, boolean_t pc_faked)
509*0Sstevel@tonic-gate {
510*0Sstevel@tonic-gate 	return (set_errno(ENOTSUP));
511*0Sstevel@tonic-gate }
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate /*ARGSUSED*/
514*0Sstevel@tonic-gate const char *
pt_disasm(const GElf_Ehdr * ehp)515*0Sstevel@tonic-gate pt_disasm(const GElf_Ehdr *ehp)
516*0Sstevel@tonic-gate {
517*0Sstevel@tonic-gate 	return ("ia32");
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate /*
521*0Sstevel@tonic-gate  * Determine the return address for the current frame.
522*0Sstevel@tonic-gate  */
523*0Sstevel@tonic-gate int
pt_step_out(mdb_tgt_t * t,uintptr_t * p)524*0Sstevel@tonic-gate pt_step_out(mdb_tgt_t *t, uintptr_t *p)
525*0Sstevel@tonic-gate {
526*0Sstevel@tonic-gate 	const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate 	if (Pstate(t->t_pshandle) != PS_STOP)
529*0Sstevel@tonic-gate 		return (set_errno(EMDB_TGTBUSY));
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	return (mdb_ia32_step_out(t, p, psp->pr_reg[EIP], psp->pr_reg[EBP],
532*0Sstevel@tonic-gate 	    psp->pr_reg[UESP], pt_read_instr(t)));
533*0Sstevel@tonic-gate }
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate /*
536*0Sstevel@tonic-gate  * Return the address of the next instruction following a call, or return -1
537*0Sstevel@tonic-gate  * and set errno to EAGAIN if the target should just single-step.
538*0Sstevel@tonic-gate  */
539*0Sstevel@tonic-gate int
pt_next(mdb_tgt_t * t,uintptr_t * p)540*0Sstevel@tonic-gate pt_next(mdb_tgt_t *t, uintptr_t *p)
541*0Sstevel@tonic-gate {
542*0Sstevel@tonic-gate 	const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate 	if (Pstate(t->t_pshandle) != PS_STOP)
545*0Sstevel@tonic-gate 		return (set_errno(EMDB_TGTBUSY));
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 	return (mdb_ia32_next(t, p, psp->pr_reg[EIP], pt_read_instr(t)));
548*0Sstevel@tonic-gate }
549