xref: /onnv-gate/usr/src/lib/libdisasm/sparc/dis_sparc_fmt.c (revision 10271:7c80b70bb8de)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright 2009 Jason King.  All rights reserved.
29  * Use is subject to license terms.
30  */
31 
32 
33 #include <sys/byteorder.h>
34 #include <stdarg.h>
35 
36 #if !defined(DIS_STANDALONE)
37 #include <stdio.h>
38 #endif /* DIS_STANDALONE */
39 
40 #include "libdisasm.h"
41 #include "libdisasm_impl.h"
42 #include "dis_sparc.h"
43 #include "dis_sparc_fmt.h"
44 
45 extern char *strncpy(char *, const char *, size_t);
46 extern size_t strlen(const char *);
47 extern int strcmp(const char *, const char *);
48 extern int strncmp(const char *, const char *, size_t);
49 extern size_t strlcat(char *, const char *, size_t);
50 extern size_t strlcpy(char *, const char *, size_t);
51 extern int snprintf(char *, size_t, const char *, ...);
52 extern int vsnprintf(char *, size_t, const char *, va_list);
53 
54 /*
55  * This file has the functions that do all the dirty work of outputting the
56  * disassembled instruction
57  *
58  * All the non-static functions follow the format_fcn (in dis_sparc.h):
59  * Input:
60  *	disassembler handle/context
61  *	instruction to disassemble
62  *	instruction definition pointer (inst_t *)
63  *	index in the table of the instruction
64  * Return:
65  *	0 Success
66  *    !0 Invalid instruction
67  *
68  * Generally, instructions found in the same table use the same output format
69  * or have a few minor differences (which are described in the 'flags' field
70  * of the instruction definition. In some cases, certain instructions differ
71  * radically enough from those in the same table, that their own format
72  * function is used.
73  *
74  * Typically each table has a unique format function defined in this file.  In
75  * some cases (such as branches) a common one for all the tables is used.
76  *
77  * When adding support for new instructions, it is largely a judgement call
78  * as to when a new format function is defined.
79  */
80 
81 /* The various instruction formats of a sparc instruction */
82 
83 #if defined(_BIT_FIELDS_HTOL)
84 typedef struct format1 {
85 	uint32_t op:2;
86 	uint32_t disp30:30;
87 } format1_t;
88 #elif defined(_BIT_FIELDS_LTOH)
89 typedef struct format1 {
90 	uint32_t disp30:30;
91 	uint32_t op:2;
92 } format1_t;
93 #else
94 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
95 #endif
96 
97 #if defined(_BIT_FIELDS_HTOL)
98 typedef struct format2 {
99 	uint32_t op:2;
100 	uint32_t rd:5;
101 	uint32_t op2:3;
102 	uint32_t imm22:22;
103 } format2_t;
104 #elif defined(_BIT_FIELDS_LTOH)
105 typedef struct format2 {
106 	uint32_t imm22:22;
107 	uint32_t op2:3;
108 	uint32_t rd:5;
109 	uint32_t op:2;
110 } format2_t;
111 #else
112 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
113 #endif
114 
115 #if defined(_BIT_FIELDS_HTOL)
116 typedef struct format2a {
117 	uint32_t op:2;
118 	uint32_t a:1;
119 	uint32_t cond:4;
120 	uint32_t op2:3;
121 	uint32_t disp22:22;
122 } format2a_t;
123 #elif defined(_BIT_FIELDS_LTOH)
124 typedef struct format2a {
125 	uint32_t disp22:22;
126 	uint32_t op2:3;
127 	uint32_t cond:4;
128 	uint32_t a:1;
129 	uint32_t op:2;
130 } format2a_t;
131 #else
132 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
133 #endif
134 
135 #if defined(_BIT_FIELDS_HTOL)
136 typedef struct format2b {
137 	uint32_t op:2;
138 	uint32_t a:1;
139 	uint32_t cond:4;
140 	uint32_t op2:3;
141 	uint32_t cc:2;
142 	uint32_t p:1;
143 	uint32_t disp19:19;
144 } format2b_t;
145 #elif defined(_BIT_FIELDS_LTOH)
146 typedef struct format2b {
147 	uint32_t disp19:19;
148 	uint32_t p:1;
149 	uint32_t cc:2;
150 	uint32_t op2:3;
151 	uint32_t cond:4;
152 	uint32_t a:1;
153 	uint32_t op:2;
154 } format2b_t;
155 #else
156 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
157 #endif
158 
159 #if defined(_BIT_FIELDS_HTOL)
160 typedef struct format2c {
161 	uint32_t op:2;
162 	uint32_t a:1;
163 	uint32_t cond:4;
164 	uint32_t op2:3;
165 	uint32_t d16hi:2;
166 	uint32_t p:1;
167 	uint32_t rs1:5;
168 	uint32_t d16lo:14;
169 } format2c_t;
170 #elif defined(_BIT_FIELDS_LTOH)
171 typedef struct format2c {
172 	uint32_t d16lo:14;
173 	uint32_t rs1:5;
174 	uint32_t p:1;
175 	uint32_t d16hi:2;
176 	uint32_t op2:3;
177 	uint32_t cond:4;
178 	uint32_t a:1;
179 	uint32_t op:2;
180 } format2c_t;
181 #else
182 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
183 #endif
184 
185 #if defined(_BIT_FIELDS_HTOL)
186 typedef struct format3 {
187 	uint32_t op:2;
188 	uint32_t rd:5;
189 	uint32_t op3:6;
190 	uint32_t rs1:5;
191 	uint32_t i:1;
192 	uint32_t asi:8;
193 	uint32_t rs2:5;
194 } format3_t;
195 #elif defined(_BIT_FIELDS_LTOH)
196 typedef struct format3 {
197 	uint32_t rs2:5;
198 	uint32_t asi:8;
199 	uint32_t i:1;
200 	uint32_t rs1:5;
201 	uint32_t op3:6;
202 	uint32_t rd:5;
203 	uint32_t op:2;
204 } format3_t;
205 #else
206 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
207 #endif
208 
209 #if defined(_BIT_FIELDS_HTOL)
210 typedef struct format3a {
211 	uint32_t op:2;
212 	uint32_t rd:5;
213 	uint32_t op3:6;
214 	uint32_t rs1:5;
215 	uint32_t i:1;
216 	uint32_t simm13:13;
217 } format3a_t;
218 #elif defined(_BIT_FIELDS_LTOH)
219 typedef struct format3a {
220 	uint32_t simm13:13;
221 	uint32_t i:1;
222 	uint32_t rs1:5;
223 	uint32_t op3:6;
224 	uint32_t rd:5;
225 	uint32_t op:2;
226 } format3a_t;
227 #else
228 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
229 #endif
230 
231 #if defined(_BIT_FIELDS_HTOL)
232 typedef struct format3b {
233 	uint32_t op:2;
234 	uint32_t rd:5;
235 	uint32_t op3:6;
236 	uint32_t rs1:5;
237 	uint32_t i:1;
238 	uint32_t x:1;
239 	uint32_t undef:6;
240 	uint32_t shcnt:6;
241 } format3b_t;
242 #elif defined(_BIT_FIELDS_LTOH)
243 typedef struct format3b {
244 	uint32_t shcnt:6;
245 	uint32_t undef:6;
246 	uint32_t x:1;
247 	uint32_t i:1;
248 	uint32_t rs1:5;
249 	uint32_t op3:6;
250 	uint32_t rd:5;
251 	uint32_t op:2;
252 } format3b_t;
253 #else
254 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
255 #endif
256 
257 #if defined(_BIT_FIELDS_HTOL)
258 typedef struct format3c {
259 	uint32_t op:2;
260 	uint32_t rd:5;
261 	uint32_t op3:6;
262 	uint32_t cc2:1;
263 	uint32_t cond:4;
264 	uint32_t i:1;
265 	uint32_t cc:2;
266 	uint32_t simm11:11;
267 } format3c_t;
268 #elif defined(_BIT_FIELDS_LTOH)
269 typedef struct format3c {
270 	uint32_t simm11:11;
271 	uint32_t cc:2;
272 	uint32_t i:1;
273 	uint32_t cond:4;
274 	uint32_t cc2:1;
275 	uint32_t op3:6;
276 	uint32_t rd:5;
277 	uint32_t op:2;
278 } format3c_t;
279 #else
280 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
281 #endif
282 
283 #if defined(_BIT_FIELDS_HTOL)
284 typedef struct format3d {
285 	uint32_t op:2;
286 	uint32_t rd:5;
287 	uint32_t op3:6;
288 	uint32_t rs1:5;
289 	uint32_t i:1;
290 	uint32_t rcond:3;
291 	uint32_t simm10:10;
292 } format3d_t;
293 #elif defined(_BIT_FIELDS_LTOH)
294 typedef struct format3d {
295 	uint32_t simm10:10;
296 	uint32_t rcond:3;
297 	uint32_t i:1;
298 	uint32_t rs1:5;
299 	uint32_t op3:6;
300 	uint32_t rd:5;
301 	uint32_t op:2;
302 } format3d_t;
303 #else
304 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
305 #endif
306 
307 #if defined(_BIT_FIELDS_HTOL)
308 typedef struct formatcp {
309 	uint32_t op:2;
310 	uint32_t rd:5;
311 	uint32_t op3:6;
312 	uint32_t rs1:5;
313 	uint32_t opc:9;
314 	uint32_t rs2:5;
315 } formatcp_t;
316 #elif defined(_BIT_FIELDS_LTOH)
317 typedef struct formatcp {
318 	uint32_t rs2:5;
319 	uint32_t opc:9;
320 	uint32_t rs1:5;
321 	uint32_t op3:6;
322 	uint32_t rd:5;
323 	uint32_t op:2;
324 } formatcp_t;
325 #else
326 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
327 #endif
328 
329 #if defined(_BIT_FIELDS_HTOL)
330 typedef struct formattcc {
331 	uint32_t op:2;
332 	uint32_t undef:1;
333 	uint32_t cond:4;
334 	uint32_t op3:6;
335 	uint32_t rs1:5;
336 	uint32_t i:1;
337 	uint32_t cc:2;
338 	uint32_t undef2:3;
339 	uint32_t immtrap:8;
340 } formattcc_t;
341 #elif defined(_BIT_FIELDS_LTOH)
342 typedef struct formattcc {
343 	uint32_t immtrap:8;
344 	uint32_t undef2:3;
345 	uint32_t cc:2;
346 	uint32_t i:1;
347 	uint32_t rs1:5;
348 	uint32_t op3:6;
349 	uint32_t cond:4;
350 	uint32_t undef:1;
351 	uint32_t op:2;
352 } formattcc_t;
353 #else
354 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
355 #endif
356 
357 #if defined(_BIT_FIELDS_HTOL)
358 typedef struct formattcc2 {
359 	uint32_t op:2;
360 	uint32_t undef:1;
361 	uint32_t cond:4;
362 	uint32_t op3:6;
363 	uint32_t rs1:5;
364 	uint32_t i:1;
365 	uint32_t cc:2;
366 	uint32_t undef2:6;
367 	uint32_t rs2:5;
368 } formattcc2_t;
369 #elif defined(_BIT_FIELDS_LTOH)
370 typedef struct formattcc2 {
371 	uint32_t rs2:5;
372 	uint32_t undef2:6;
373 	uint32_t cc:2;
374 	uint32_t i:1;
375 	uint32_t rs1:5;
376 	uint32_t op3:6;
377 	uint32_t cond:4;
378 	uint32_t undef:1;
379 	uint32_t op:2;
380 } formattcc2_t;
381 #else
382 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
383 #endif
384 
385 #if defined(_BIT_FIELDS_HTOL)
386 typedef struct formatmbr {
387 	uint32_t op:2;
388 	uint32_t rd:5;
389 	uint32_t op3:6;
390 	uint32_t rs1:5;
391 	uint32_t i:1;
392 	uint32_t undef:6;
393 	uint32_t cmask:3;
394 	uint32_t mmask:4;
395 } formatmbr_t;
396 #elif defined(_BIT_FIELDS_LTOH)
397 typedef struct formatmbr {
398 	uint32_t mmask:4;
399 	uint32_t cmask:3;
400 	uint32_t undef:6;
401 	uint32_t i:1;
402 	uint32_t rs1:5;
403 	uint32_t op3:6;
404 	uint32_t rd:5;
405 	uint32_t op:2;
406 } formatmbr_t;
407 #else
408 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
409 #endif
410 
411 #if defined(_BIT_FIELDS_HTOL)
412 typedef struct formatfcmp {
413 	uint32_t op:2;
414 	uint32_t undef:3;
415 	uint32_t cc:2;
416 	uint32_t op3:6;
417 	uint32_t rs1:5;
418 	uint32_t opf:9;
419 	uint32_t rs2:5;
420 } formatfcmp_t;
421 #elif defined(_BIT_FIELDS_LTOH)
422 typedef struct formatfcmp {
423 	uint32_t rs2:5;
424 	uint32_t opf:9;
425 	uint32_t rs1:5;
426 	uint32_t op3:6;
427 	uint32_t cc:2;
428 	uint32_t undef:3;
429 	uint32_t op:2;
430 } formatfcmp_t;
431 #else
432 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
433 #endif
434 
435 #if defined(_BIT_FIELDS_HTOL)
436 typedef struct formatfmov {
437 	uint32_t op:2;
438 	uint32_t rd:5;
439 	uint32_t op3:6;
440 	uint32_t undef:1;
441 	uint32_t cond:4;
442 	uint32_t cc:3;
443 	uint32_t opf:6;
444 	uint32_t rs2:5;
445 } formatfmov_t;
446 #elif defined(_BIT_FIELDS_LTOH)
447 typedef struct formatfmov {
448 	uint32_t rs2:5;
449 	uint32_t opf:6;
450 	uint32_t cc:3;
451 	uint32_t cond:4;
452 	uint32_t undef:1;
453 	uint32_t op3:6;
454 	uint32_t rd:5;
455 	uint32_t op:2;
456 } formatfmov_t;
457 #else
458 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
459 #endif
460 
461 #if defined(_BIT_FIELDS_HTOL)
462 typedef struct formatfused {
463 	uint32_t op:2;
464 	uint32_t rd:5;
465 	uint32_t op3:6;
466 	uint32_t rs1:5;
467 	uint32_t rs3:5;
468 	uint32_t op5:4;
469 	uint32_t rs2:5;
470 } formatfused_t;
471 #elif defined(_BIT_FIELDS_LTOH)
472 typedef struct formatfused {
473 	uint32_t rs2:5;
474 	uint32_t op5:4;
475 	uint32_t rs3:5;
476 	uint32_t rs1:5;
477 	uint32_t op3:6;
478 	uint32_t rd:5;
479 	uint32_t op:2;
480 } formatfused_t;
481 #else
482 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
483 #endif
484 
485 typedef union ifmt {
486 	uint32_t	i;
487 	format1_t	f1;
488 	format2_t	f2;
489 	format2a_t	f2a;
490 	format2b_t	f2b;
491 	format2c_t	f2c;
492 	format3_t	f3;
493 	format3a_t	f3a;
494 	format3b_t	f3b;
495 	format3c_t	f3c;
496 	format3d_t	f3d;
497 	formatcp_t	fcp;
498 	formattcc_t	ftcc;
499 	formattcc2_t	ftcc2;
500 	formatfcmp_t	fcmp;
501 	formatmbr_t	fmb;
502 	formatfmov_t	fmv;
503 	formatfused_t	fused;
504 } ifmt_t;
505 
506 /* integer register names */
507 static const char *reg_names[32] = {
508 	"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
509 	"%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
510 	"%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
511 	"%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7"
512 };
513 
514 /* floating point register names */
515 static const char *freg_names[32] = {
516 	"%f0",  "%f1",  "%f2",  "%f3",  "%f4",  "%f5",  "%f6",  "%f7",
517 	"%f8",  "%f9",  "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
518 	"%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
519 	"%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"
520 };
521 
522 /* double precision register names */
523 static const char *fdreg_names[32] = {
524 	"%d0",  "%d32", "%d2",  "%d34", "%d4",  "%d36", "%d6",  "%d38",
525 	"%d8",  "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46",
526 	"%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54",
527 	"%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62"
528 };
529 
530 static const char *compat_fdreg_names[32] = {
531 	"%f0",  "%f32", "%f2",  "%f34", "%f4",  "%f36", "%f6",  "%f38",
532 	"%f8",  "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46",
533 	"%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54",
534 	"%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62"
535 };
536 
537 
538 static const char *fqreg_names[32] = {
539 	"%q0",  "%q32", "%f2",  "%f3",  "%f4",  "%q4",  "%q36", "%f6",
540 	"%f7",  "%q8",  "%q40", "%f10", "%f11", "%q12", "%q44", "%f14",
541 	"%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22",
542 	"%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30",
543 };
544 
545 
546 /* coprocessor register names -- sparcv8 only */
547 static const char *cpreg_names[32] = {
548 	"%c0",  "%c1",  "%c2",  "%c3",  "%c4",  "%c5",  "%c6",  "%c7",
549 	"%c8",  "%c9",  "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
550 	"%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23",
551 	"%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31",
552 };
553 
554 /* floating point condition code names */
555 static const char *fcc_names[4] = {
556 	"%fcc0", "%fcc1", "%fcc2", "%fcc3"
557 };
558 
559 /* condition code names */
560 static const char *icc_names[4] = {
561 	"%icc", NULL, "%xcc", NULL
562 };
563 
564 /* bitmask values for membar */
565 static const char *membar_mmask[4] = {
566 	"#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore"
567 };
568 
569 static const char *membar_cmask[3] = {
570 	"#Lookaside", "#MemIssue", "#Sync"
571 };
572 
573 /* v8 ancillary state register names */
574 static const char *asr_names[32] = {
575 	"%y",	"%asr1",  "%asr2",  "%asr3",
576 	"%asr4",  "%asr5",  "%asr6",  "%asr7",
577 	"%asr8",  "%asr9",  "%asr10", "%asr11",
578 	"%asr12", "%asr13", "%asr14", "%asr15",
579 	NULL,	NULL,	NULL,	NULL,
580 	NULL,	NULL,	NULL,	NULL,
581 	NULL,	NULL,	NULL,	NULL,
582 	NULL,	NULL,	NULL,	NULL
583 };
584 static const uint32_t asr_rdmask = 0x0000ffffL;
585 static const uint32_t asr_wrmask = 0x0000ffffL;
586 
587 static const char *v9_asr_names[32] = {
588 	"%y",		NULL,		"%ccr",	"%asi",
589 	"%tick",	"%pc",		"%fprs",	NULL,
590 	NULL,		NULL,		NULL,	NULL,
591 	NULL,		NULL,		NULL,	NULL,
592 	"%pcr",		"%pic",		"%dcr",	"%gsr",
593 	"%softint_set",	"%softint_clr",	"%softint",	"%tick_cmpr",
594 	"%stick",	"%stick_cmpr",	NULL,	NULL,
595 	NULL,		NULL,		NULL,	NULL
596 };
597 /*
598  * on v9, only certain registers are valid for read or writing
599  * these are bitmasks corresponding to which registers are valid in which
600  * case. Any access to %dcr is illegal.
601  */
602 static const uint32_t v9_asr_rdmask = 0x03cb007d;
603 static const uint32_t v9_asr_wrmask = 0x03fb004d;
604 
605 /* privledged register names on v9 */
606 /* TODO: compat - NULL to %priv_nn */
607 static const char *v9_privreg_names[32] = {
608 	"%tpc",	 "%tnpc",	"%tstate",  "%tt",
609 	"%tick",	"%tba",	 "%pstate",  "%tl",
610 	"%pil",	 "%cwp",	 "%cansave", "%canrestore",
611 	"%cleanwin", "%otherwin", "%wstate",  "%fq",
612 	"%gl",	NULL,	NULL,	NULL,
613 	NULL,	NULL,	NULL,	NULL,
614 	NULL,	NULL,	NULL,	NULL,
615 	NULL,	NULL,	NULL,	"%ver"
616 };
617 
618 /* hyper privileged register names on v9 */
619 static const char *v9_hprivreg_names[32] = {
620 	"%hpstate",	 "%htstate",	NULL,  "%hintp",
621 	NULL,	"%htba",	 "%hver",  NULL,
622 	NULL,	NULL,	NULL,	NULL,
623 	NULL,	NULL,	NULL,	NULL,
624 	NULL,	NULL,	NULL,	NULL,
625 	NULL,	NULL,	NULL,	NULL,
626 	NULL,	NULL,	NULL,	NULL,
627 	NULL,	NULL,	NULL,	"%hstick_cmpr"
628 };
629 
630 static const uint32_t v9_pr_rdmask = 0x80017fff;
631 static const uint32_t v9_pr_wrmask = 0x00017fff;
632 static const uint32_t v9_hpr_rdmask = 0x8000006b;
633 static const uint32_t v9_hpr_wrmask = 0x8000006b;
634 
635 static const char *prefetch_str[32] = {
636 	"#n_reads", "#one_read",
637 	"#n_writes", "#one_write",
638 	"#page",    NULL, NULL, NULL,
639 	NULL, NULL, NULL, NULL,
640 	NULL, NULL, NULL, NULL,
641 	NULL, "#unified", NULL, NULL,
642 	"#n_reads_strong", "#one_read_strong",
643 	"#n_writes_strong", "#one_write_strong",
644 	NULL, NULL, NULL, NULL,
645 	NULL, NULL, NULL, NULL
646 };
647 
648 static void prt_field(const char *, uint32_t, int);
649 
650 static const char *get_regname(dis_handle_t *, int, uint32_t);
651 static int32_t sign_extend(int32_t, int32_t);
652 
653 static void prt_name(dis_handle_t *, const char *, int);
654 
655 #define	IMM_SIGNED 0x01  /* Is immediate value signed		*/
656 #define	IMM_ADDR   0x02  /* Is immediate value part of an address */
657 static void prt_imm(dis_handle_t *, uint32_t, int);
658 
659 static void prt_asi(dis_handle_t *, uint32_t);
660 static const char *get_asi_name(uint8_t);
661 static void prt_address(dis_handle_t *, uint32_t, int);
662 static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t);
663 static void bprintf(dis_handle_t *, const char *, ...);
664 
665 /*
666  * print out val (which is 'bitlen' bits long) in binary
667  */
668 #if defined(DIS_STANDALONE)
669 /* ARGSUSED */
670 void
prt_binary(uint32_t val,int bitlen)671 prt_binary(uint32_t val, int bitlen)
672 {
673 
674 }
675 
676 #else
677 
678 void
prt_binary(uint32_t val,int bitlen)679 prt_binary(uint32_t val, int bitlen)
680 {
681 	int i;
682 
683 	for (i = bitlen - 1; i >= 0; --i) {
684 		(void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
685 
686 		if (i % 4 == 0 && i != 0)
687 			(void) fprintf(stderr, " ");
688 	}
689 }
690 #endif /* DIS_STANDALONE */
691 
692 
693 /*
694  * print out a call instruction
695  * format: call address  <name>
696  */
697 /* ARGSUSED1 */
698 int
fmt_call(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)699 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
700 {
701 	ifmt_t *f = (ifmt_t *)&instr;
702 
703 	int32_t disp;
704 	size_t curlen;
705 
706 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
707 
708 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
709 		prt_field("op", f->f1.op, 2);
710 		prt_field("disp30", f->f1.disp30, 30);
711 	}
712 
713 	disp = sign_extend(f->f1.disp30, 30) * 4;
714 
715 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
716 
717 	bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
718 	    (disp < 0) ? "-" : "+",
719 	    (disp < 0) ? (-disp) : disp);
720 
721 	(void) strlcat(dhp->dh_buf, " <", dhp->dh_buflen);
722 
723 	curlen = strlen(dhp->dh_buf);
724 	dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
725 	    dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL,
726 	    NULL);
727 	(void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen);
728 
729 
730 	return (0);
731 }
732 
733 int
fmt_sethi(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)734 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
735 {
736 	ifmt_t *f = (ifmt_t *)&instr;
737 
738 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
739 		prt_field("op", f->f2.op, 2);
740 		prt_field("op2", f->f2.op2, 3);
741 		prt_field("rd", f->f2.rd, 5);
742 		prt_field("imm22", f->f2.imm22, 22);
743 	}
744 
745 	if (idx == 0) {
746 		/* unimp / illtrap */
747 		prt_name(dhp, inp->in_data.in_def.in_name, 1);
748 		prt_imm(dhp, f->f2.imm22, 0);
749 		return (0);
750 	}
751 
752 	if (f->f2.imm22 == 0 && f->f2.rd == 0) {
753 		prt_name(dhp, "nop", 0);
754 		return (0);
755 	}
756 
757 	/* ?? Should we return -1 if rd == 0 && disp != 0 */
758 
759 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
760 
761 	bprintf(dhp,
762 	    ((dhp->dh_flags & DIS_OCTAL) != 0) ?
763 	    "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
764 	    f->f2.imm22 << 10,
765 	    reg_names[f->f2.rd]);
766 
767 	return (0);
768 }
769 
770 /* ARGSUSED3 */
771 int
fmt_branch(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)772 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
773 {
774 	const char *name = inp->in_data.in_def.in_name;
775 	const char *r = NULL;
776 	const char *annul = "";
777 	const char *pred  = "";
778 
779 	char buf[15];
780 
781 	ifmt_t *f = (ifmt_t *)&instr;
782 
783 	size_t curlen;
784 	int32_t disp;
785 	uint32_t flags = inp->in_data.in_def.in_flags;
786 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
787 
788 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
789 		prt_field("op", f->f2.op, 2);
790 		prt_field("op2", f->f2.op2, 3);
791 
792 		switch (FLG_DISP_VAL(flags)) {
793 		case DISP22:
794 			prt_field("cond", f->f2a.cond, 4);
795 			prt_field("a", f->f2a.a, 1);
796 			prt_field("disp22", f->f2a.disp22, 22);
797 			break;
798 
799 		case DISP19:
800 			prt_field("cond", f->f2a.cond, 4);
801 			prt_field("a", f->f2a.a, 1);
802 			prt_field("p", f->f2b.p, 1);
803 			prt_field("cc", f->f2b.cc, 2);
804 			prt_field("disp19", f->f2b.disp19, 19);
805 			break;
806 
807 		case DISP16:
808 			prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
809 			prt_field("rcond", f->f2c.cond, 3);
810 			prt_field("p", f->f2c.p, 1);
811 			prt_field("rs1", f->f2c.rs1, 5);
812 			prt_field("d16hi", f->f2c.d16hi, 2);
813 			prt_field("d16lo", f->f2c.d16lo, 14);
814 			break;
815 		}
816 	}
817 
818 	if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
819 	    f->f2b.cc == 0x02 && ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0)) {
820 		name = "iprefetch";
821 		flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
822 	}
823 
824 
825 	switch (FLG_DISP_VAL(flags)) {
826 	case DISP22:
827 		disp = sign_extend(f->f2a.disp22, 22);
828 		break;
829 
830 	case DISP19:
831 		disp = sign_extend(f->f2b.disp19, 19);
832 		break;
833 
834 	case DISP16:
835 		disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
836 		break;
837 
838 	}
839 
840 	disp *= 4;
841 
842 	if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
843 		r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
844 	else
845 		r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
846 
847 	if (r == NULL)
848 		return (-1);
849 
850 	if (f->f2a.a == 1)
851 		annul = ",a";
852 
853 	if ((flags & FLG_PRED) != 0) {
854 		if (f->f2b.p == 0) {
855 			pred = ",pn";
856 		} else {
857 			if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)
858 				pred = ",pt";
859 		}
860 	}
861 
862 	(void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
863 	prt_name(dhp, buf, 1);
864 
865 
866 	switch (FLG_DISP_VAL(flags)) {
867 	case DISP22:
868 		bprintf(dhp,
869 		    (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
870 		    (disp < 0) ? "-" : "+",
871 		    (disp < 0) ? (-disp) : disp);
872 		break;
873 
874 	case DISP19:
875 		bprintf(dhp,
876 		    (octal != 0) ? "%s, %s0%-5lo <" :
877 		    "%s, %s0x%-04lx <", r,
878 		    (disp < 0) ? "-" : "+",
879 		    (disp < 0) ? (-disp) : disp);
880 		break;
881 
882 	case DISP16:
883 		bprintf(dhp,
884 		    (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
885 		    r,
886 		    (disp < 0) ? "-" : "+",
887 		    (disp < 0) ? (-disp) : disp);
888 		break;
889 	}
890 
891 	curlen = strlen(dhp->dh_buf);
892 	dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
893 	    dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL, NULL);
894 
895 	(void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen);
896 
897 	return (0);
898 }
899 
900 
901 
902 /*
903  * print out the compare and swap instructions (casa/casxa)
904  * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
905  *	    casa/casxa [%rs1] %asi, %rs2, %rd
906  *
907  * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
908  * when an immediate ASI value is given as follows:
909  *
910  * casa  [%rs1]#ASI_P, %rs2, %rd    -> cas   [%rs1], %rs2, %rd
911  * casa  [%rs1]#ASI_P_L, %rs2, %rd  -> casl  [%rs1], %rs2, %rd
912  * casxa [%rs1]#ASI_P, %rs2, %rd    -> casx  [%rs1], %rs2, %rd
913  * casxa [%rs1]#ASI_P_L, %rs2, %rd  -> casxl [%rs1], %rs2, %rd
914  */
915 static int
fmt_cas(dis_handle_t * dhp,uint32_t instr,const char * name)916 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
917 {
918 	ifmt_t *f = (ifmt_t *)&instr;
919 	const char *asistr = NULL;
920 	int noasi = 0;
921 
922 	asistr = get_asi_name(f->f3.asi);
923 
924 	if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
925 		if (f->f3.op3 == 0x3c && f->f3.i == 0) {
926 			if (f->f3.asi == 0x80) {
927 				noasi = 1;
928 				name = "cas";
929 			}
930 
931 			if (f->f3.asi == 0x88) {
932 				noasi = 1;
933 				name = "casl";
934 			}
935 		}
936 
937 		if (f->f3.op3 == 0x3e && f->f3.i == 0) {
938 			if (f->f3.asi == 0x80) {
939 				noasi = 1;
940 				name = "casx";
941 			}
942 
943 			if (f->f3.asi == 0x88) {
944 				noasi = 1;
945 				name = "casxl";
946 			}
947 		}
948 	}
949 
950 	prt_name(dhp, name, 1);
951 
952 	bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
953 
954 	if (noasi == 0) {
955 		(void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
956 		prt_asi(dhp, instr);
957 	}
958 
959 	bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
960 
961 	if (noasi == 0 && asistr != NULL)
962 		bprintf(dhp, "\t<%s>", asistr);
963 
964 	return (0);
965 }
966 
967 /*
968  * format a load/store instruction
969  * format: ldXX [%rs1 + %rs2], %rd	  load, i==0
970  *	    ldXX [%rs1 +/- nn], %rd	  load, i==1
971  *	    ldXX [%rs1 + %rs2] #XX, %rd   load w/ imm_asi, i==0
972  *	    ldXX [%rs1 +/- nn] %asi, %rd  load from asi[%asi], i==1
973  *
974  *	    stXX %rd, [%rs1 + %rs2]	  store, i==0
975  *	    stXX %rd, [%rs1 +/- nn]	  store, i==1
976  *	    stXX %rd, [%rs1 + %rs1] #XX   store to imm_asi, i==0
977  *	    stXX %rd, [%rs1 +/-nn] %asi   store to asi[%asi], i==1
978  *
979  * The register sets used for %rd are set in the instructions flags field
980  * The asi variants are used if FLG_ASI is set in the instructions flags field
981  *
982  * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set,
983  * When %rs1, %rs2 or nn are 0, they are not printed, i.e.
984  * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example
985  *
986  * The following synthetic instructions are also implemented:
987  *
988  * stb %g0, [addr] -> clrb [addr]    DIS_DEBUG_SYNTH_ALL
989  * sth %g0, [addr] -> crlh [addr]    DIS_DEBUG_SYNTH_ALL
990  * stw %g0, [addr] -> clr  [addr]    DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT
991  * stx %g0, [addr] -> clrx [addr]    DIS_DEBUG_SYNTH_ALL
992  *
993  * If DIS_DEBUG_COMPAT is set, the following substitutions also take place
994  *	lduw -> ld
995  *	ldtw -> ld
996  *	stuw -> st
997  *	sttw -> st
998  */
999 int
fmt_ls(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1000 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1001 {
1002 	ifmt_t *f = (ifmt_t *)&instr;
1003 	const char *regstr = NULL;
1004 	const char *asistr = NULL;
1005 
1006 	const char *iname = inp->in_data.in_def.in_name;
1007 	uint32_t flags = inp->in_data.in_def.in_flags;
1008 
1009 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1010 		prt_field("op", f->f3.op, 2);
1011 		prt_field("op3", f->f3.op3, 6);
1012 		prt_field("rs1", f->f3.rs1, 5);
1013 		prt_field("i", f->f3.i, 1);
1014 		if (f->f3.i != 0) {
1015 			prt_field("simm13", f->f3a.simm13, 13);
1016 		} else {
1017 			if ((flags & FLG_ASI) != 0)
1018 				prt_field("imm_asi", f->f3.asi, 8);
1019 			prt_field("rs2", f->f3.rs2, 5);
1020 		}
1021 		prt_field("rd", f->f3.rd, 5);
1022 	}
1023 
1024 	if (idx == 0x2d || idx == 0x3d) {
1025 		/* prefetch / prefetcha */
1026 
1027 		prt_name(dhp, iname, 1);
1028 
1029 		prt_address(dhp, instr, 0);
1030 
1031 		if (idx == 0x3d) {
1032 			(void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1033 			prt_asi(dhp, instr);
1034 		}
1035 
1036 		(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1037 
1038 		/* fcn field is the same as rd */
1039 		if (prefetch_str[f->f3.rd] != NULL)
1040 			(void) strlcat(dhp->dh_buf, prefetch_str[f->f3.rd],
1041 			    dhp->dh_buflen);
1042 		else
1043 			prt_imm(dhp, f->f3.rd, 0);
1044 
1045 		if (idx == 0x3d && f->f3.i == 0) {
1046 			asistr = get_asi_name(f->f3.asi);
1047 			if (asistr != NULL)
1048 				bprintf(dhp, "\t<%s>", asistr);
1049 		}
1050 
1051 		return (0);
1052 	}
1053 
1054 	/* casa / casxa */
1055 	if (idx == 0x3c || idx == 0x3e)
1056 		return (fmt_cas(dhp, instr, iname));
1057 
1058 	/* synthetic instructions & special cases */
1059 	switch (idx) {
1060 	case 0x00:
1061 		/* ld */
1062 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1063 			iname = "lduw";
1064 		break;
1065 
1066 	case 0x03:
1067 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1068 			iname = "ldtw";
1069 		break;
1070 
1071 	case 0x04:
1072 		/* stw */
1073 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1074 			iname = "stuw";
1075 
1076 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1077 		    == 0)
1078 			break;
1079 
1080 		if (f->f3.rd == 0) {
1081 			iname = "clr";
1082 			flags = FLG_RD(REG_NONE);
1083 		}
1084 		break;
1085 
1086 	case 0x05:
1087 		/* stb */
1088 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1089 		    == 0)
1090 			break;
1091 
1092 		if (f->f3.rd == 0) {
1093 			iname = "clrb";
1094 			flags = FLG_RD(REG_NONE);
1095 		}
1096 		break;
1097 
1098 	case 0x06:
1099 		/* sth */
1100 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1101 		    == 0)
1102 			break;
1103 
1104 		if (f->f3.rd == 0) {
1105 			iname = "clrh";
1106 			flags = FLG_RD(REG_NONE);
1107 		}
1108 		break;
1109 
1110 	case 0x07:
1111 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1112 			iname = "sttw";
1113 		break;
1114 
1115 	case 0x0e:
1116 		/* stx */
1117 
1118 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1119 		    == 0)
1120 			break;
1121 
1122 		if (f->f3.rd == 0) {
1123 			iname = "clrx";
1124 			flags = FLG_RD(REG_NONE);
1125 		}
1126 		break;
1127 
1128 	case 0x13:
1129 		/* ldtwa */
1130 		if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) &&
1131 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1132 			iname = "ldtwa";
1133 		break;
1134 
1135 	case 0x17:
1136 		/* sttwa */
1137 		if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) &&
1138 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1139 			iname = "sttwa";
1140 		break;
1141 
1142 	case 0x21:
1143 	case 0x25:
1144 		/*
1145 		 * on sparcv8 it merely says that rd != 1 should generate an
1146 		 * exception, on v9, it is illegal
1147 		 */
1148 		if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1149 			break;
1150 
1151 		iname = (idx == 0x21) ? "ldx" : "stx";
1152 
1153 		if (f->f3.rd > 1)
1154 			return (-1);
1155 
1156 		break;
1157 
1158 	case 0x31:
1159 		/* stda */
1160 		switch (f->f3.asi) {
1161 			case 0xc0:
1162 			case 0xc1:
1163 			case 0xc8:
1164 			case 0xc9:
1165 			case 0xc2:
1166 			case 0xc3:
1167 			case 0xca:
1168 			case 0xcb:
1169 			case 0xc4:
1170 			case 0xc5:
1171 			case 0xcc:
1172 			case 0xcd:
1173 				/*
1174 				 * store partial floating point, only valid w/
1175 				 * vis
1176 				 *
1177 				 * Somewhat confusingly, it uses the same op
1178 				 * code as 'stda' -- store double to alternate
1179 				 * space.  It is distinguised by specific
1180 				 * imm_asi values (as seen above), and
1181 				 * has a slightly different output syntax
1182 				 */
1183 
1184 				if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0)
1185 					break;
1186 				if (f->f3.i != 0)
1187 					break;
1188 				prt_name(dhp, iname, 1);
1189 				bprintf(dhp, "%s, %s, [%s] ",
1190 				    get_regname(dhp, REG_FPD, f->f3.rd),
1191 				    get_regname(dhp, REG_FPD, f->f3.rs2),
1192 				    get_regname(dhp, REG_FPD, f->f3.rs1));
1193 				prt_asi(dhp, instr);
1194 				asistr = get_asi_name(f->f3.asi);
1195 				if (asistr != NULL)
1196 					bprintf(dhp, "\t<%s>", asistr);
1197 
1198 				return (0);
1199 
1200 			default:
1201 				break;
1202 		}
1203 
1204 	}
1205 
1206 	regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1207 
1208 	if (f->f3.i == 0)
1209 		asistr = get_asi_name(f->f3.asi);
1210 
1211 	prt_name(dhp, iname, 1);
1212 
1213 	if ((flags & FLG_STORE) != 0) {
1214 		if (regstr[0] != '\0') {
1215 			(void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1216 			(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1217 		}
1218 
1219 		prt_address(dhp, instr, 0);
1220 		if ((flags & FLG_ASI) != 0) {
1221 			(void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1222 			prt_asi(dhp, instr);
1223 		}
1224 	} else {
1225 		prt_address(dhp, instr, 0);
1226 		if ((flags & FLG_ASI) != 0) {
1227 			(void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1228 			prt_asi(dhp, instr);
1229 		}
1230 
1231 		if (regstr[0] != '\0') {
1232 			(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1233 			(void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1234 		}
1235 	}
1236 
1237 	if ((flags & FLG_ASI) != 0 && asistr != NULL)
1238 		bprintf(dhp, "\t<%s>", asistr);
1239 
1240 	return (0);
1241 }
1242 
1243 static int
fmt_cpop(dis_handle_t * dhp,uint32_t instr,const inst_t * inp)1244 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1245 {
1246 	ifmt_t *f = (ifmt_t *)&instr;
1247 	int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1248 
1249 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1250 		prt_field("op", f->fcp.op, 2);
1251 		prt_field("op3", f->fcp.op3, 6);
1252 		prt_field("opc", f->fcp.opc, 9);
1253 		prt_field("rs1", f->fcp.rs1, 5);
1254 		prt_field("rs2", f->fcp.rs2, 5);
1255 		prt_field("rd", f->fcp.rd, 5);
1256 	}
1257 
1258 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1259 	prt_imm(dhp, f->fcp.opc, 0);
1260 
1261 	(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1262 	(void) prt_aluargs(dhp, instr, flags);
1263 
1264 	return (0);
1265 }
1266 
1267 static int
dis_fmt_rdwr(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1268 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1269 {
1270 	const char *psr_str = "%psr";
1271 	const char *wim_str = "%wim";
1272 	const char *tbr_str = "%tbr";
1273 
1274 	const char *name = inp->in_data.in_def.in_name;
1275 	const char *regstr = NULL;
1276 
1277 	ifmt_t *f = (ifmt_t *)&instr;
1278 
1279 	int rd = (idx < 0x30);
1280 	int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1281 	int ridx = f->f3.rs1;
1282 	int i, first;
1283 	int pr_rs1 = 1;
1284 	int pr_rs2 = 1;
1285 
1286 	int use_mask = 1;
1287 	uint32_t mask;
1288 
1289 	if (rd == 0)
1290 		ridx = f->f3.rd;
1291 
1292 	switch (idx) {
1293 	case 0x28:
1294 		/* rd */
1295 
1296 		/* stbar */
1297 		if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) {
1298 			prt_name(dhp, "stbar", 0);
1299 			return (0);
1300 		}
1301 
1302 		/* membar */
1303 		if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) &&
1304 		    (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) {
1305 
1306 			prt_name(dhp, "membar",
1307 			    ((f->fmb.cmask != 0) || (f->fmb.mmask != 0)));
1308 
1309 			first = 0;
1310 
1311 			for (i = 0; i < 4; ++i) {
1312 				if ((f->fmb.cmask & (1L << i)) != 0) {
1313 					bprintf(dhp, "%s%s",
1314 					    (first != 0) ? "|" : "",
1315 					    membar_cmask[i]);
1316 					first = 1;
1317 				}
1318 			}
1319 
1320 			for (i = 0; i < 5; ++i) {
1321 				if ((f->fmb.mmask & (1L << i)) != 0) {
1322 					bprintf(dhp, "%s%s",
1323 					    (first != 0) ? "|" : "",
1324 					    membar_mmask[i]);
1325 					first = 1;
1326 				}
1327 			}
1328 
1329 			return (0);
1330 		}
1331 
1332 		if (v9 != 0) {
1333 			regstr = v9_asr_names[ridx];
1334 			mask = v9_asr_rdmask;
1335 		} else {
1336 			regstr = asr_names[ridx];
1337 			mask = asr_rdmask;
1338 		}
1339 		break;
1340 
1341 	case 0x29:
1342 		if (v9 != 0) {
1343 			regstr = v9_hprivreg_names[ridx];
1344 			mask = v9_hpr_rdmask;
1345 		} else {
1346 			regstr = psr_str;
1347 			use_mask = 0;
1348 		}
1349 		break;
1350 
1351 	case 0x2a:
1352 		if (v9 != 0) {
1353 			regstr = v9_privreg_names[ridx];
1354 			mask = v9_pr_rdmask;
1355 		} else {
1356 			regstr = wim_str;
1357 			use_mask = 0;
1358 		}
1359 		break;
1360 
1361 	case 0x2b:
1362 		if (v9 != 0) {
1363 			/* flushw */
1364 			prt_name(dhp, name, 0);
1365 			return (0);
1366 		}
1367 
1368 		regstr = tbr_str;
1369 		use_mask = 0;
1370 		break;
1371 
1372 	case 0x30:
1373 		if (v9 != 0) {
1374 			regstr = v9_asr_names[ridx];
1375 			mask = v9_asr_wrmask;
1376 		} else {
1377 			regstr = asr_names[ridx];
1378 			mask = asr_wrmask;
1379 		}
1380 
1381 		/*
1382 		 * sir is shoehorned in here, per Ultrasparc 2007
1383 		 * hyperprivileged edition, section 7.88, all of
1384 		 * these must be true to distinguish from WRasr
1385 		 */
1386 		if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 &&
1387 		    f->f3.i == 1) {
1388 			prt_name(dhp, "sir", 1);
1389 			prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1390 			    IMM_SIGNED);
1391 			return (0);
1392 		}
1393 
1394 		/* synth: mov */
1395 		if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1396 		    == 0)
1397 			break;
1398 
1399 		if (v9 == 0) {
1400 			if (f->f3.rs1 == 0) {
1401 				name = "mov";
1402 				pr_rs1 = 0;
1403 			}
1404 
1405 			if ((f->f3.i == 0 && f->f3.rs2 == 0) ||
1406 			    (f->f3.i == 1 && f->f3a.simm13 == 0)) {
1407 				name = "mov";
1408 				pr_rs2 = 0;
1409 			}
1410 		}
1411 
1412 		if (pr_rs1 == 0)
1413 			pr_rs2 = 1;
1414 
1415 		break;
1416 
1417 	case 0x31:
1418 		/*
1419 		 * NOTE: due to the presence of an overlay entry for another
1420 		 * table, this case only happens when doing v8 instructions
1421 		 * only
1422 		 */
1423 		regstr = psr_str;
1424 		use_mask = 0;
1425 		break;
1426 
1427 	case 0x32:
1428 		if (v9 != 0) {
1429 			regstr = v9_privreg_names[ridx];
1430 			mask = v9_pr_wrmask;
1431 		} else {
1432 			regstr = wim_str;
1433 			use_mask = 0;
1434 		}
1435 		break;
1436 
1437 	case 0x33:
1438 		if (v9 != 0) {
1439 			regstr = v9_hprivreg_names[ridx];
1440 			mask = v9_hpr_wrmask;
1441 		} else {
1442 			regstr = tbr_str;
1443 			use_mask = 0;
1444 		}
1445 		break;
1446 	}
1447 
1448 	if (regstr == NULL)
1449 		return (-1);
1450 
1451 	if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1452 		return (-1);
1453 
1454 	prt_name(dhp, name, 1);
1455 
1456 	if (rd != 0) {
1457 		bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1458 	} else {
1459 		if (pr_rs1 == 1)
1460 			bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1461 
1462 		if (pr_rs2 != 0) {
1463 			if (f->f3.i == 1)
1464 				prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1465 				    IMM_SIGNED);
1466 			else
1467 				(void) strlcat(dhp->dh_buf,
1468 				    reg_names[f->f3.rs2], dhp->dh_buflen);
1469 			(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1470 		}
1471 
1472 		(void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1473 	}
1474 
1475 	return (0);
1476 }
1477 
1478 /* ARGSUSED3 */
1479 int
fmt_trap(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1480 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1481 {
1482 	ifmt_t *f = (ifmt_t *)&instr;
1483 
1484 	int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1485 	int p_rs1, p_t;
1486 
1487 	if (f->ftcc.undef != 0)
1488 		return (-1);
1489 
1490 	if (icc_names[f->ftcc.cc] == NULL)
1491 		return (-1);
1492 
1493 	if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1494 		return (-1);
1495 
1496 	if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1497 		return (-1);
1498 
1499 	p_rs1 = ((f->ftcc.rs1 != 0) ||
1500 	    ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1501 
1502 	if (f->ftcc.i == 0) {
1503 		p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1504 
1505 		bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1506 		    (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1507 		    (v9 != 0) ? ", " : "",
1508 		    (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1509 		    (p_rs1 != 0) ? " + " : "",
1510 		    (p_t != 0) ? reg_names[f->f3.rs2] : "");
1511 	} else {
1512 		bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name,
1513 		    (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1514 		    (v9 != 0) ? ", " : "",
1515 		    (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1516 		    (p_rs1 != 0) ? " + " : "",
1517 		    f->ftcc.immtrap);
1518 	}
1519 	return (0);
1520 }
1521 
1522 static int
prt_shift(dis_handle_t * dhp,uint32_t instr,const inst_t * inp)1523 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1524 {
1525 	char name[5];
1526 	uint32_t cnt;
1527 
1528 	ifmt_t *f = (ifmt_t *)&instr;
1529 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
1530 
1531 	name[0] = '\0';
1532 	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
1533 
1534 	if (f->f3b.i == 1)
1535 		cnt = f->f3.rs2;
1536 
1537 	if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) {
1538 		cnt = f->f3b.shcnt;
1539 		(void) strlcat(name, "x", sizeof (name));
1540 	}
1541 
1542 	prt_name(dhp, name, 1);
1543 
1544 	if (f->f3b.i == 1)
1545 		bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1546 		    reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1547 	else
1548 		bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1549 		    reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1550 
1551 	return (0);
1552 }
1553 
1554 /* ARGSUSED3 */
1555 static int
prt_jmpl(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1556 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1557 {
1558 	const char *name = inp->in_data.in_def.in_name;
1559 	ifmt_t *f = (ifmt_t *)&instr;
1560 
1561 	if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0))
1562 		name = "call";
1563 
1564 	if (f->f3.rd == 0) {
1565 		if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1566 			if (f->f3.rs1 == 15) {
1567 				prt_name(dhp, "retl", 0);
1568 				return (0);
1569 			}
1570 
1571 			if (f->f3.rs1 == 31) {
1572 				prt_name(dhp, "ret", 0);
1573 				return (0);
1574 			}
1575 		}
1576 
1577 		name = "jmp";
1578 	}
1579 
1580 	prt_name(dhp, name, 1);
1581 	prt_address(dhp, instr, 1);
1582 
1583 	if (f->f3.rd == 0)
1584 		return (0);
1585 
1586 	if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0))
1587 		return (0);
1588 
1589 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1590 
1591 	return (0);
1592 }
1593 
1594 int
fmt_alu(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1595 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1596 {
1597 	ifmt_t *f = (ifmt_t *)&instr;
1598 
1599 	const char *name = inp->in_data.in_def.in_name;
1600 	int flags = inp->in_data.in_def.in_flags;
1601 	int arg = 0;
1602 
1603 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1604 		prt_field("op", f->f3.op, 2);
1605 		prt_field("op3", f->f3.op3, 6);
1606 		prt_field("rs1", f->f3.rs1, 5);
1607 
1608 		switch (idx) {
1609 			/* TODO: more formats */
1610 
1611 		default:
1612 			if (f->f3.i == 0)
1613 				prt_field("rs2", f->f3.rs2, 5);
1614 			else
1615 				prt_field("simm13", f->f3a.simm13, 13);
1616 
1617 			prt_field("rd", f->f3.rd, 5);
1618 		}
1619 
1620 	}
1621 
1622 	switch (idx) {
1623 	case 0x00:
1624 		/* add */
1625 
1626 		if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1627 			break;
1628 
1629 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1630 		    f->f3a.simm13 == 1) {
1631 			name = "inc";
1632 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1633 			break;
1634 		}
1635 
1636 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1637 		    f->f3a.simm13 != 1) {
1638 			name = "inc";
1639 			flags = FLG_P1(REG_NONE);
1640 			break;
1641 		}
1642 		break;
1643 
1644 	case 0x02:
1645 		/* or */
1646 
1647 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1648 		    == 0)
1649 			break;
1650 
1651 		if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0) {
1652 			if (f->f3.rs1 == f->f3.rd) {
1653 				name = "bset";
1654 				flags = FLG_P1(REG_NONE);
1655 				break;
1656 			}
1657 		}
1658 
1659 		if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1660 		    (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1661 		    (f->f3.rs1 == 0)) {
1662 			name = "clr";
1663 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1664 			break;
1665 		}
1666 
1667 		if (f->f3.rs1 == 0) {
1668 			name = "mov";
1669 			flags = FLG_P1(REG_NONE);
1670 			break;
1671 		}
1672 		break;
1673 
1674 	case 0x04:
1675 		/* sub */
1676 
1677 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1678 		    == 0)
1679 			break;
1680 
1681 		if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1682 			name = "neg";
1683 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1684 			break;
1685 		}
1686 
1687 		if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1688 			name = "neg";
1689 			flags = FLG_P1(REG_NONE);
1690 			break;
1691 		}
1692 
1693 		if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1694 			break;
1695 
1696 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1697 		    f->f3a.simm13 == 1) {
1698 			name = "dec";
1699 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1700 			break;
1701 		}
1702 
1703 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1704 		    f->f3a.simm13 != 1) {
1705 			name = "dec";
1706 			flags = FLG_P1(REG_NONE);
1707 			break;
1708 		}
1709 		break;
1710 
1711 	case 0x07:
1712 		/* xnor */
1713 
1714 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1715 		    == 0)
1716 			break;
1717 
1718 		/*
1719 		 * xnor -> not when you have:
1720 		 *	 xnor %rs1, 0x0 or %g0, %rd
1721 		 */
1722 		if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1723 		    (f->f3.i == 1 && f->f3a.simm13 != 0))
1724 			break;
1725 
1726 		name = "not";
1727 
1728 		if (f->f3.rs1 == f->f3.rd)
1729 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1730 			    FLG_P3(REG_INT);
1731 		else
1732 			flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1733 			    FLG_P3(REG_INT);
1734 
1735 		break;
1736 
1737 	case 0x10:
1738 		/* addcc */
1739 
1740 		if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1741 			break;
1742 
1743 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1744 		    f->f3a.simm13 == 1) {
1745 			name = "inccc";
1746 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1747 			break;
1748 		}
1749 
1750 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1751 		    f->f3a.simm13 != 1) {
1752 			name = "inccc";
1753 			flags = FLG_P1(REG_NONE);
1754 			break;
1755 		}
1756 		break;
1757 
1758 	case 0x11:
1759 		/* andcc */
1760 
1761 		if (f->f3.rd != 0)
1762 			break;
1763 
1764 		if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1765 		    == 0)
1766 			break;
1767 
1768 		if (((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) &&
1769 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1770 			break;
1771 
1772 		name = "btst";
1773 		flags = FLG_P1(REG_NONE);
1774 		f->f3.rd = f->f3.rs1;
1775 		break;
1776 
1777 	case 0x12:
1778 		/* orcc */
1779 
1780 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1781 		    == 0)
1782 			break;
1783 
1784 		if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1785 			name = "tst";
1786 			flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1787 			break;
1788 		}
1789 
1790 		if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1791 			name = "tst";
1792 			flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1793 			break;
1794 		}
1795 
1796 		break;
1797 
1798 	case 0x14:
1799 		/* subcc */
1800 
1801 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1802 		    == 0)
1803 			break;
1804 
1805 		if (f->f3.rd == 0) {
1806 			name = "cmp";
1807 			flags = FLG_P3(REG_NONE);
1808 			break;
1809 		}
1810 
1811 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)
1812 			break;
1813 
1814 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1815 		    f->f3a.simm13 == 1) {
1816 			name = "deccc";
1817 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1818 			break;
1819 		}
1820 
1821 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1822 		    f->f3a.simm13 != 1) {
1823 			name = "deccc";
1824 			flags = FLG_P1(REG_NONE);
1825 			break;
1826 		}
1827 
1828 		break;
1829 
1830 	case 0x25:
1831 	case 0x26:
1832 	case 0x27:
1833 		return (prt_shift(dhp, instr, inp));
1834 
1835 	case 0x28:
1836 	case 0x29:
1837 	case 0x2a:
1838 	case 0x2b:
1839 	case 0x30:
1840 	case 0x31:
1841 	case 0x32:
1842 	case 0x33:
1843 		return (dis_fmt_rdwr(dhp, instr, inp, idx));
1844 
1845 	case 0x36:
1846 	case 0x37:
1847 		/* NOTE: overlayed on v9 */
1848 		if ((dhp->dh_flags & DIS_SPARC_V8) != 0)
1849 			return (fmt_cpop(dhp, instr, inp));
1850 		break;
1851 
1852 	case 0x38:
1853 		/* jmpl */
1854 		return (prt_jmpl(dhp, instr, inp, idx));
1855 
1856 	case 0x39:
1857 		/* rett / return */
1858 		prt_name(dhp, name, 1);
1859 		prt_address(dhp, instr, 1);
1860 		return (0);
1861 
1862 	case 0x3b:
1863 		/* flush */
1864 		prt_name(dhp, name, 1);
1865 		prt_address(dhp, instr, 0);
1866 		return (0);
1867 
1868 	case 0x3c:
1869 	case 0x3d:
1870 		/* save / restore */
1871 		if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1872 		    == 0)
1873 			break;
1874 
1875 		if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1876 			break;
1877 
1878 		if (f->f3.i != 0 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0))
1879 			break;
1880 
1881 		prt_name(dhp, name, 0);
1882 		return (0);
1883 	}
1884 
1885 	if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1886 	    FLG_P3_VAL(flags) != REG_NONE)
1887 		arg = 1;
1888 
1889 	prt_name(dhp, name, (arg != 0));
1890 	prt_aluargs(dhp, instr, flags);
1891 
1892 	return (0);
1893 }
1894 
1895 /* ARGSUSED1 */
1896 int
fmt_regwin(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1897 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1898 {
1899 	prt_name(dhp, inp->in_data.in_def.in_name, 0);
1900 	return (0);
1901 }
1902 
1903 /* ARGSUSED1 */
1904 int
fmt_trap_ret(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1905 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1906 {
1907 	ifmt_t *f = (ifmt_t *)&instr;
1908 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1909 
1910 	if (f->f3.rd == 0xf) {
1911 		/* jpriv */
1912 		prt_address(dhp, instr, 1);
1913 	}
1914 
1915 	return (0);
1916 }
1917 
1918 /* ARGSUSED3 */
1919 int
fmt_movcc(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1920 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1921 {
1922 	ifmt_t *f = (ifmt_t *)&instr;
1923 	const char **regs = NULL;
1924 
1925 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1926 		prt_field("op", f->f3c.op, 2);
1927 		prt_field("op3", f->f3c.op3, 6);
1928 		prt_field("cond", f->f3c.cond, 4);
1929 		prt_field("cc2", f->f3c.cc2, 1);
1930 		prt_field("cc", f->f3c.cc, 2);
1931 		prt_field("i", f->f3c.i, 1);
1932 
1933 		if (f->f3c.i == 0)
1934 			prt_field("rs2", f->f3.rs2, 5);
1935 		else
1936 			prt_field("simm11", f->f3c.simm11, 11);
1937 
1938 		prt_field("rd", f->f3.rd, 5);
1939 	}
1940 
1941 	if (f->f3c.cc2 == 0) {
1942 		regs = fcc_names;
1943 	} else {
1944 		regs = icc_names;
1945 		if (regs[f->f3c.cc] == NULL)
1946 			return (-1);
1947 	}
1948 
1949 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1950 
1951 	bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1952 
1953 	if (f->f3c.i == 1)
1954 		prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1955 	else
1956 		(void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2],
1957 		    dhp->dh_buflen);
1958 
1959 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1960 
1961 	return (0);
1962 }
1963 
1964 /* ARGSUSED3 */
1965 int
fmt_movr(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1966 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1967 {
1968 	ifmt_t *f = (ifmt_t *)&instr;
1969 
1970 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1971 
1972 	bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1973 
1974 	if (f->f3d.i == 1)
1975 		prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1976 	else
1977 		(void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2],
1978 		    dhp->dh_buflen);
1979 
1980 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1981 
1982 	return (0);
1983 }
1984 
1985 /* ARGSUSED3 */
1986 int
fmt_fpop1(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1987 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1988 {
1989 	ifmt_t *f = (ifmt_t *)&instr;
1990 	int flags = inp->in_data.in_def.in_flags;
1991 
1992 	flags |= FLG_NOIMM;
1993 
1994 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1995 		prt_field("op", f->f3.op, 2);
1996 		prt_field("op3", f->f3.op3, 6);
1997 		prt_field("opf", f->fcmp.opf, 9);
1998 		prt_field("rs1", f->f3.rs1, 5);
1999 		prt_field("rs2", f->f3.rs2, 5);
2000 		prt_field("rd", f->f3.rd, 5);
2001 	}
2002 
2003 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2004 	prt_aluargs(dhp, instr, flags);
2005 
2006 	return (0);
2007 }
2008 
2009 int
fmt_fpop2(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2010 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2011 {
2012 	static const char *condstr_icc[16] = {
2013 		"n", "e",  "le", "l",  "leu", "lu",  "neg", "vs",
2014 		"a", "nz", "g",  "ge", "gu",  "geu", "pos", "vc"
2015 	};
2016 
2017 	static const char *condstr_fcc[16] = {
2018 		"n", "nz", "lg", "ul", "l",   "ug", "g",   "u",
2019 		"a", "e",  "ue", "ge", "uge", "le", "ule", "o"
2020 	};
2021 
2022 	ifmt_t *f = (ifmt_t *)&instr;
2023 	const char *ccstr = "";
2024 	char name[15];
2025 
2026 	int flags = inp->in_data.in_def.in_flags;
2027 	int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2028 	    idx == 0x55 || idx == 0x56 || idx == 0x57);
2029 	int is_fmov = (idx & 0x3f);
2030 	int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2031 	int is_compat = ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0);
2032 
2033 	int p_cc = 0;
2034 
2035 	is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2036 
2037 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
2038 		prt_field("op", f->f3.op, 2);
2039 		prt_field("op3", f->f3.op3, 6);
2040 		prt_field("opf", f->fcmp.opf, 9);
2041 
2042 		switch (idx & 0x3f) {
2043 		case 0x51:
2044 		case 0x52:
2045 		case 0x53:
2046 		case 0x55:
2047 		case 0x56:
2048 		case 0x57:
2049 			prt_field("cc", f->fcmp.cc, 2);
2050 			prt_field("rs1", f->f3.rs1, 5);
2051 			prt_field("rs2", f->f3.rs2, 5);
2052 			break;
2053 
2054 		case 0x01:
2055 		case 0x02:
2056 		case 0x03:
2057 			prt_field("opf_low", f->fmv.opf, 6);
2058 			prt_field("cond", f->fmv.cond, 4);
2059 			prt_field("opf_cc", f->fmv.cc, 3);
2060 			prt_field("rs2", f->fmv.rs2, 5);
2061 			break;
2062 
2063 		default:
2064 			prt_field("rs1", f->f3.rs1, 5);
2065 			prt_field("rs2", f->f3.rs2, 5);
2066 			prt_field("rd", f->f3.rd, 5);
2067 		}
2068 	}
2069 
2070 	name[0] = '\0';
2071 	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
2072 
2073 	if (is_fmov != 0) {
2074 		(void) strlcat(name,
2075 		    (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond]
2076 		    : condstr_icc[f->fmv.cond],
2077 		    sizeof (name));
2078 	}
2079 
2080 	prt_name(dhp, name, 1);
2081 
2082 	if (is_cmp != 0)
2083 		ccstr = fcc_names[f->fcmp.cc];
2084 
2085 	if (is_fmov != 0)
2086 		ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3]
2087 		    : icc_names[f->fmv.cc & 0x3];
2088 
2089 	if (ccstr == NULL)
2090 		return (-1);
2091 
2092 	p_cc = (is_compat == 0 || is_v9 != 0 ||
2093 	    (is_cmp != 0 && f->fcmp.cc != 0) ||
2094 	    (is_fmov != 0 && f->fmv.cc != 0));
2095 
2096 	if (p_cc != 0)
2097 		bprintf(dhp, "%s, ", ccstr);
2098 
2099 	prt_aluargs(dhp, instr, flags);
2100 
2101 	return (0);
2102 }
2103 
2104 int
fmt_vis(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2105 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2106 {
2107 	ifmt_t *f = (ifmt_t *)&instr;
2108 	int flags = inp->in_data.in_def.in_flags;
2109 
2110 	if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
2111 		prt_field("op", f->f3.op, 2);
2112 		prt_field("op3", f->f3.op3, 6);
2113 		prt_field("opf", f->fcmp.opf, 9);
2114 
2115 		if (idx == 0x081) {
2116 			prt_field("mode", instr & 02L, 2);
2117 		} else {
2118 			prt_field("rs1", f->f3.rs1, 5);
2119 			prt_field("rs2", f->f3.rs2, 5);
2120 			prt_field("rd", f->f3.rd, 5);
2121 		}
2122 	}
2123 
2124 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2125 
2126 	if (idx == 0x081) {
2127 		/* siam */
2128 		bprintf(dhp, "%d", instr & 0x7L);
2129 		return (0);
2130 	}
2131 
2132 	prt_aluargs(dhp, instr, flags);
2133 
2134 	return (0);
2135 }
2136 
2137 /* ARGSUSED3 */
2138 int
fmt_fused(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2139 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2140 {
2141 	ifmt_t *f = (ifmt_t *)&instr;
2142 	int flags = inp->in_data.in_def.in_flags;
2143 
2144 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2145 	bprintf(dhp, "%s, %s, %s, %s",
2146 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1),
2147 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2),
2148 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3),
2149 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd));
2150 
2151 	return (0);
2152 }
2153 /*
2154  * put name into the output buffer
2155  * if add_space !=0, append a space after it
2156  */
2157 static void
prt_name(dis_handle_t * dhp,const char * name,int add_space)2158 prt_name(dis_handle_t *dhp, const char *name, int add_space)
2159 {
2160 	bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name);
2161 }
2162 
2163 /*
2164  * For debugging, print out a field of the instruction
2165  * field is the name of the field
2166  * val is the value of the field
2167  * len is the length of the field (in bits)
2168  */
2169 #if defined(DIS_STANDALONE)
2170 /* ARGSUSED */
2171 static void
prt_field(const char * field,uint32_t val,int len)2172 prt_field(const char *field, uint32_t val, int len)
2173 {
2174 
2175 }
2176 
2177 #else
2178 static void
prt_field(const char * field,uint32_t val,int len)2179 prt_field(const char *field, uint32_t val, int len)
2180 {
2181 	(void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val);
2182 	prt_binary(val, len);
2183 	(void) fprintf(stderr, ")\n");
2184 }
2185 #endif /* DIS_STANDALONE */
2186 
2187 /*
2188  * sign extend a val (that is 'bits' bits in length) to a 32-bit signed
2189  * integer
2190  */
2191 static int32_t
sign_extend(int32_t val,int32_t bits)2192 sign_extend(int32_t val, int32_t bits)
2193 {
2194 	if ((val & (1L << (bits - 1))) == 0)
2195 		return (val);
2196 
2197 	return ((-1L << bits) | val);
2198 }
2199 
2200 /*
2201  * print out an immediate (i.e. constant) value
2202  * val is the value
2203  * format indicates if it is:
2204  * 0		 Unsigned
2205  * IMM_SIGNED  A signed value (prepend +/- to the value)
2206  * IMM_ADDR    Part of an address expression (prepend +/- but with a space
2207  *		   between the sign and the value for things like [%i1 + 0x55]
2208  */
2209 static void
prt_imm(dis_handle_t * dhp,uint32_t val,int format)2210 prt_imm(dis_handle_t *dhp, uint32_t val, int format)
2211 {
2212 	const char *fmtstr = NULL;
2213 	int32_t sv = (int32_t)val;
2214 	int octal = dhp->dh_flags & DIS_OCTAL;
2215 
2216 	switch (format) {
2217 	case IMM_ADDR:
2218 		if (sv < 0) {
2219 			sv = -sv;
2220 			fmtstr = (octal != 0) ? "- 0%lo" : "- 0x%lx";
2221 		} else {
2222 			fmtstr = (octal != 0) ? "+ 0%lo" : "+ 0x%lx";
2223 		}
2224 		break;
2225 
2226 	case IMM_SIGNED:
2227 		if (sv < 0) {
2228 			sv = -sv;
2229 			fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx";
2230 			break;
2231 		}
2232 		/* fall through */
2233 
2234 	default:
2235 		fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2236 	}
2237 
2238 	bprintf(dhp, fmtstr, sv);
2239 }
2240 
2241 /*
2242  * return the symbolic name of a register
2243  * regset is one of the REG_* values indicating which type of register it is
2244  * such as integer, floating point, etc.
2245  * idx is the numeric value of the register
2246  *
2247  * If regset is REG_NONE, an empty, but non-NULL string is returned
2248  * NULL may be returned if the index indicates an invalid register value
2249  * such as with the %icc/%xcc sets
2250  */
2251 static const char *
get_regname(dis_handle_t * dhp,int regset,uint32_t idx)2252 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2253 {
2254 	const char *regname = NULL;
2255 
2256 	switch (regset) {
2257 	case REG_INT:
2258 		regname = reg_names[idx];
2259 		break;
2260 
2261 	case REG_FP:
2262 		regname = freg_names[idx];
2263 		break;
2264 
2265 	case REG_FPD:
2266 		if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) ||
2267 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
2268 			regname = fdreg_names[idx];
2269 		else
2270 			regname = compat_fdreg_names[idx];
2271 
2272 		break;
2273 
2274 	case REG_FPQ:
2275 		if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
2276 			regname = fqreg_names[idx];
2277 		else
2278 			regname = freg_names[idx];
2279 
2280 		break;
2281 
2282 	case REG_CP:
2283 		regname = cpreg_names[idx];
2284 		break;
2285 
2286 	case REG_ICC:
2287 		regname = icc_names[idx];
2288 		break;
2289 
2290 	case REG_FCC:
2291 		regname = fcc_names[idx];
2292 		break;
2293 
2294 	case REG_FSR:
2295 		regname = "%fsr";
2296 		break;
2297 
2298 	case REG_CSR:
2299 		regname = "%csr";
2300 		break;
2301 
2302 	case REG_CQ:
2303 		regname = "%cq";
2304 		break;
2305 
2306 	case REG_NONE:
2307 		regname = "";
2308 		break;
2309 	}
2310 
2311 	return (regname);
2312 }
2313 
2314 /*
2315  * output the asi value from the instruction
2316  *
2317  * TODO: investigate if this should perhaps have a mask -- are undefined ASI
2318  *	  values for an instruction still disassembled??
2319  */
2320 static void
prt_asi(dis_handle_t * dhp,uint32_t instr)2321 prt_asi(dis_handle_t *dhp, uint32_t instr)
2322 {
2323 	ifmt_t *f = (ifmt_t *)&instr;
2324 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2325 
2326 	if (f->f3.i != 0)
2327 		bprintf(dhp, "%%asi");
2328 	else
2329 		bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi);
2330 
2331 }
2332 
2333 /*
2334  * put an address expression into the output buffer
2335  *
2336  * instr is the instruction to use
2337  * if nobrackets != 0, [] are not added around the instruction
2338  *
2339  * Currently this option is set when printing out the address portion
2340  * of a jmpl instruction, but otherwise 0 for load/stores
2341  *
2342  * If no debug flags are set, the full expression is output, even when
2343  * %g0 or 0x0 appears in the address
2344  *
2345  * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0
2346  * appear in the address, they are not output.  If the wierd (and probably
2347  * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered,
2348  * [%g0] is output
2349  */
2350 static void
prt_address(dis_handle_t * dhp,uint32_t instr,int nobrackets)2351 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
2352 {
2353 	ifmt_t *f = (ifmt_t *)&instr;
2354 	int32_t simm13;
2355 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2356 	int p1 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2357 	int p2 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2358 
2359 	if (f->f3a.i == 0) {
2360 		p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2361 		p2 |= (f->f3.rs2 != 0);
2362 
2363 		bprintf(dhp, "%s%s%s%s%s",
2364 		    (nobrackets == 0) ? "[" : "",
2365 		    (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2366 		    (p1 != 0 && p2 != 0) ? " + " : "",
2367 		    (p2 != 0) ? reg_names[f->f3.rs2] : "",
2368 		    (nobrackets == 0) ? "]" : "");
2369 	} else {
2370 		const char *sign;
2371 
2372 		simm13 = sign_extend(f->f3a.simm13, 13);
2373 		sign = (simm13 < 0) ? "-" : "+";
2374 
2375 		p1 |= (f->f3a.rs1 != 0);
2376 		p2 |= (p1 == 0 || simm13 != 0);
2377 
2378 		if (p1 == 0 && simm13 == 0)
2379 			p2 = 1;
2380 
2381 		if (p1 == 0 && simm13 >= 0)
2382 			sign = "";
2383 
2384 		if (p2 != 0)
2385 			bprintf(dhp,
2386 			    (octal != 0) ? "%s%s%s%s%s0%lo%s" :
2387 			    "%s%s%s%s%s0x%lx%s",
2388 			    (nobrackets == 0) ? "[" : "",
2389 			    (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2390 			    (p1 != 0) ? " " : "",
2391 			    sign,
2392 			    (p1 != 0) ? " " : "",
2393 			    (simm13 < 0) ? -(simm13) : simm13,
2394 			    (nobrackets == 0) ? "]" : "");
2395 		else
2396 			bprintf(dhp, "%s%s%s",
2397 			    (nobrackets == 0) ? "[" : "",
2398 			    reg_names[f->f3a.rs1],
2399 			    (nobrackets == 0) ? "]" : "");
2400 	}
2401 }
2402 
2403 /*
2404  * print out the arguments to an alu operation (add, sub, etc.)
2405  * conatined in 'instr'
2406  *
2407  * alu instructions have the following format:
2408  *	 %rs1, %rs2, %rd    (i == 0)
2409  *	 %rs1, 0xnnn, %rd   (i == 1)
2410  *	   ^	^	^
2411  *	   |	|	|
2412  *	  p1    p2	p3
2413  *
2414  * flags indicates the register set to use for each position (p1, p2, p3)
2415  * as well as if immediate values (i == 1) are allowed
2416  *
2417  * if flags indicates a specific position has REG_NONE set as it's register
2418  * set, it is omitted from the output.  This is primarly used for certain
2419  * floating point operations
2420  */
2421 static void
prt_aluargs(dis_handle_t * dhp,uint32_t instr,uint32_t flags)2422 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
2423 {
2424 	ifmt_t *f = (ifmt_t *)&instr;
2425 	const char *r1, *r2, *r3;
2426 	int p1, p2, p3;
2427 	unsigned int opf = 0;
2428 
2429 	r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1);
2430 	r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2);
2431 	r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd);
2432 
2433 	p1 = (FLG_P1_VAL(flags) != REG_NONE);
2434 	p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE));
2435 	p3 = (FLG_RD_VAL(flags) != REG_NONE);
2436 
2437 	if (r1 == NULL || r1[0] == '\0')
2438 		p1 = 0;
2439 
2440 	if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2441 		p2 = 0;
2442 
2443 	if (r3 == NULL || r3[0] == '\0')
2444 		p3 = 0;
2445 
2446 	if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2447 		opf = f->fcmp.opf;
2448 
2449 	if ((opf == 0x151) || (opf == 0x152)) {
2450 		(void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen);
2451 		(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2452 		p3 = 0;
2453 	}
2454 
2455 	if (p1 != 0) {
2456 		(void) strlcat(dhp->dh_buf, r1, dhp->dh_buflen);
2457 		if (p2 != 0 || p3 != 0)
2458 			(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2459 	}
2460 
2461 	if (p2 != 0) {
2462 		if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0))
2463 			(void) strlcat(dhp->dh_buf, r2, dhp->dh_buflen);
2464 		else
2465 			prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
2466 			    IMM_SIGNED);
2467 
2468 		if (p3 != 0)
2469 			(void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2470 	}
2471 
2472 	if (p3 != 0)
2473 		(void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen);
2474 }
2475 
2476 static const char *
get_asi_name(uint8_t asi)2477 get_asi_name(uint8_t asi)
2478 {
2479 	switch (asi) {
2480 		case 0x04:
2481 			return ("ASI_N");
2482 
2483 		case 0x0c:
2484 			return ("ASI_NL");
2485 
2486 		case 0x10:
2487 			return ("ASI_AIUP");
2488 
2489 		case 0x11:
2490 			return ("ASI_AIUS");
2491 
2492 		case 0x14:
2493 			return ("ASI_REAL");
2494 
2495 		case 0x15:
2496 			return ("ASI_REAL_IO");
2497 
2498 		case 0x16:
2499 			return ("ASI_BLK_AIUP");
2500 
2501 		case 0x17:
2502 			return ("ASI_BLK_AIUS");
2503 
2504 		case 0x18:
2505 			return ("ASI_AIUPL");
2506 
2507 		case 0x19:
2508 			return ("ASI_AIUSL");
2509 
2510 		case 0x1c:
2511 			return ("ASI_REAL_L");
2512 
2513 		case 0x1d:
2514 			return ("ASI_REAL_IO_L");
2515 
2516 		case 0x1e:
2517 			return ("ASI_BLK_AIUPL");
2518 
2519 		case 0x1f:
2520 			return ("ASI_BLK_AIUS_L");
2521 
2522 		case 0x20:
2523 			return ("ASI_SCRATCHPAD");
2524 
2525 		case 0x21:
2526 			return ("ASI_MMU_CONTEXTID");
2527 
2528 		case 0x22:
2529 			return ("ASI_TWINX_AIUP");
2530 
2531 		case 0x23:
2532 			return ("ASI_TWINX_AIUS");
2533 
2534 		case 0x25:
2535 			return ("ASI_QUEUE");
2536 
2537 		case 0x26:
2538 			return ("ASI_TWINX_R");
2539 
2540 		case 0x27:
2541 			return ("ASI_TWINX_N");
2542 
2543 		case 0x2a:
2544 			return ("ASI_LDTX_AIUPL");
2545 
2546 		case 0x2b:
2547 			return ("ASI_TWINX_AIUS_L");
2548 
2549 		case 0x2e:
2550 			return ("ASI_TWINX_REAL_L");
2551 
2552 		case 0x2f:
2553 			return ("ASI_TWINX_NL");
2554 
2555 		case 0x30:
2556 			return ("ASI_AIPP");
2557 
2558 		case 0x31:
2559 			return ("ASI_AIPS");
2560 
2561 		case 0x36:
2562 			return ("ASI_AIPN");
2563 
2564 		case 0x38:
2565 			return ("ASI_AIPP_L");
2566 
2567 		case 0x39:
2568 			return ("ASI_AIPS_L");
2569 
2570 		case 0x3e:
2571 			return ("ASI_AIPN_L");
2572 
2573 		case 0x41:
2574 			return ("ASI_CMT_SHARED");
2575 
2576 		case 0x4f:
2577 			return ("ASI_HYP_SCRATCHPAD");
2578 
2579 		case 0x50:
2580 			return ("ASI_IMMU");
2581 
2582 		case 0x52:
2583 			return ("ASI_MMU_REAL");
2584 
2585 		case 0x54:
2586 			return ("ASI_MMU");
2587 
2588 		case 0x55:
2589 			return ("ASI_ITLB_DATA_ACCESS_REG");
2590 
2591 		case 0x56:
2592 			return ("ASI_ITLB_TAG_READ_REG");
2593 
2594 		case 0x57:
2595 			return ("ASI_IMMU_DEMAP");
2596 
2597 		case 0x58:
2598 			return ("ASI_DMMU / ASI_UMMU");
2599 
2600 		case 0x5c:
2601 			return ("ASI_DTLB_DATA_IN_REG");
2602 
2603 		case 0x5d:
2604 			return ("ASI_DTLB_DATA_ACCESS_REG");
2605 
2606 		case 0x5e:
2607 			return ("ASI_DTLB_TAG_READ_REG");
2608 
2609 		case 0x5f:
2610 			return ("ASI_DMMU_DEMAP");
2611 
2612 		case 0x63:
2613 			return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE");
2614 
2615 		case 0x80:
2616 			return ("ASI_P");
2617 
2618 		case 0x81:
2619 			return ("ASI_S");
2620 
2621 		case 0x82:
2622 			return ("ASI_PNF");
2623 
2624 		case 0x83:
2625 			return ("ASI_SNF");
2626 
2627 		case 0x88:
2628 			return ("ASI_PL");
2629 
2630 		case 0x89:
2631 			return ("ASI_SL");
2632 
2633 		case 0x8a:
2634 			return ("ASI_PNFL");
2635 
2636 		case 0x8b:
2637 			return ("ASI_SNFL");
2638 
2639 		case 0xc0:
2640 			return ("ASI_PST8_P");
2641 
2642 		case 0xc1:
2643 			return ("ASI_PST8_S");
2644 
2645 		case 0xc2:
2646 			return ("ASI_PST16_P");
2647 
2648 		case 0xc3:
2649 			return ("ASI_PST16_S");
2650 
2651 		case 0xc4:
2652 			return ("ASI_PST32_P");
2653 
2654 		case 0xc5:
2655 			return ("ASI_PST32_S");
2656 
2657 		case 0xc8:
2658 			return ("ASI_PST8_PL");
2659 
2660 		case 0xc9:
2661 			return ("ASI_PST8_SL");
2662 
2663 		case 0xca:
2664 			return ("ASI_PST16_PL");
2665 
2666 		case 0xcb:
2667 			return ("ASI_PST16_SL");
2668 
2669 		case 0xcc:
2670 			return ("ASI_PST32_PL");
2671 
2672 		case 0xcd:
2673 			return ("ASI_PST32_SL");
2674 
2675 		case 0xd0:
2676 			return ("ASI_FL8_P");
2677 
2678 		case 0xd1:
2679 			return ("ASI_FL8_S");
2680 
2681 		case 0xd2:
2682 			return ("ASI_FL16_P");
2683 
2684 		case 0xd3:
2685 			return ("ASI_FL16_S");
2686 
2687 		case 0xd8:
2688 			return ("ASI_FL8_PL");
2689 
2690 		case 0xd9:
2691 			return ("ASI_FL8_SL");
2692 
2693 		case 0xda:
2694 			return ("ASI_FL16_PL");
2695 
2696 		case 0xdb:
2697 			return ("ASI_FL16_SL");
2698 
2699 		case 0xe0:
2700 			return ("ASI_BLK_COMMIT_P");
2701 
2702 		case 0xe1:
2703 			return ("ASI_BLK_SOMMIT_S");
2704 
2705 		case 0xe2:
2706 			return ("ASI_TWINX_P");
2707 
2708 		case 0xe3:
2709 			return ("ASI_TWINX_S");
2710 
2711 		case 0xea:
2712 			return ("ASI_TWINX_PL");
2713 
2714 		case 0xeb:
2715 			return ("ASI_TWINX_SL");
2716 
2717 		case 0xf0:
2718 			return ("ASI_BLK_P");
2719 
2720 		case 0xf1:
2721 			return ("ASI_BLK_S");
2722 
2723 		case 0xf8:
2724 			return ("ASI_BLK_PL");
2725 
2726 		case 0xf9:
2727 			return ("ASI_BLK_SL");
2728 
2729 		default:
2730 			return (NULL);
2731 	}
2732 }
2733 
2734 /*
2735  * just a handy function that takes care of managing the buffer length
2736  * w/ printf
2737  */
2738 
2739 /*
2740  * PRINTF LIKE 1
2741  */
2742 static void
bprintf(dis_handle_t * dhp,const char * fmt,...)2743 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2744 {
2745 	size_t curlen;
2746 	va_list ap;
2747 
2748 	curlen = strlen(dhp->dh_buf);
2749 
2750 	va_start(ap, fmt);
2751 	(void) vsnprintf(dhp->dh_buf + curlen, dhp->dh_buflen - curlen, fmt,
2752 	    ap);
2753 	va_end(ap);
2754 }
2755