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  * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
31  */
32 
33 
34 #include <sys/byteorder.h>
35 #include <sys/debug.h>
36 #include <stdarg.h>
37 
38 #if !defined(DIS_STANDALONE)
39 #include <stdio.h>
40 #endif /* DIS_STANDALONE */
41 
42 #include "libdisasm.h"
43 #include "libdisasm_impl.h"
44 #include "dis_sparc.h"
45 #include "dis_sparc_fmt.h"
46 
47 extern char *strncpy(char *, const char *, size_t);
48 extern size_t strlen(const char *);
49 extern int strcmp(const char *, const char *);
50 extern int strncmp(const char *, const char *, size_t);
51 extern size_t strlcat(char *, const char *, size_t);
52 extern size_t strlcpy(char *, const char *, size_t);
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, uint32_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 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
702 	ifmt_t *f = (ifmt_t *)&instr;
703 
704 	int32_t disp;
705 	size_t curlen;
706 
707 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
708 
709 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
710 		prt_field("op", f->f1.op, 2);
711 		prt_field("disp30", f->f1.disp30, 30);
712 	}
713 
714 	disp = sign_extend(f->f1.disp30, 30) * 4;
715 
716 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
717 
718 	bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
719 	    (disp < 0) ? "-" : "+",
720 	    (disp < 0) ? (-disp) : disp);
721 
722 	(void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen);
723 
724 	curlen = strlen(dhx->dhx_buf);
725 	dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
726 	    dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL,
727 	    NULL);
728 	(void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
729 
730 
731 	return (0);
732 }
733 
734 int
fmt_sethi(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)735 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
736 {
737 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
738 	ifmt_t *f = (ifmt_t *)&instr;
739 
740 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
741 		prt_field("op", f->f2.op, 2);
742 		prt_field("op2", f->f2.op2, 3);
743 		prt_field("rd", f->f2.rd, 5);
744 		prt_field("imm22", f->f2.imm22, 22);
745 	}
746 
747 	if (idx == 0) {
748 		/* unimp / illtrap */
749 		prt_name(dhp, inp->in_data.in_def.in_name, 1);
750 		prt_imm(dhp, f->f2.imm22, 0);
751 		return (0);
752 	}
753 
754 	if (f->f2.imm22 == 0 && f->f2.rd == 0) {
755 		prt_name(dhp, "nop", 0);
756 		return (0);
757 	}
758 
759 	/* ?? Should we return -1 if rd == 0 && disp != 0 */
760 
761 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
762 
763 	bprintf(dhp,
764 	    ((dhp->dh_flags & DIS_OCTAL) != 0) ?
765 	    "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
766 	    f->f2.imm22 << 10,
767 	    reg_names[f->f2.rd]);
768 
769 	return (0);
770 }
771 
772 /* ARGSUSED3 */
773 int
fmt_branch(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)774 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
775 {
776 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
777 	const char *name = inp->in_data.in_def.in_name;
778 	const char *r = NULL;
779 	const char *annul = "";
780 	const char *pred  = "";
781 
782 	char buf[15];
783 
784 	ifmt_t *f = (ifmt_t *)&instr;
785 
786 	size_t curlen;
787 	int32_t disp;
788 	uint32_t flags = inp->in_data.in_def.in_flags;
789 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
790 
791 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
792 		prt_field("op", f->f2.op, 2);
793 		prt_field("op2", f->f2.op2, 3);
794 
795 		switch (FLG_DISP_VAL(flags)) {
796 		case DISP22:
797 			prt_field("cond", f->f2a.cond, 4);
798 			prt_field("a", f->f2a.a, 1);
799 			prt_field("disp22", f->f2a.disp22, 22);
800 			break;
801 
802 		case DISP19:
803 			prt_field("cond", f->f2a.cond, 4);
804 			prt_field("a", f->f2a.a, 1);
805 			prt_field("p", f->f2b.p, 1);
806 			prt_field("cc", f->f2b.cc, 2);
807 			prt_field("disp19", f->f2b.disp19, 19);
808 			break;
809 
810 		case DISP16:
811 			prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
812 			prt_field("rcond", f->f2c.cond, 3);
813 			prt_field("p", f->f2c.p, 1);
814 			prt_field("rs1", f->f2c.rs1, 5);
815 			prt_field("d16hi", f->f2c.d16hi, 2);
816 			prt_field("d16lo", f->f2c.d16lo, 14);
817 			break;
818 		}
819 	}
820 
821 	if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
822 	    f->f2b.cc == 0x02 && ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0)) {
823 		name = "iprefetch";
824 		flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
825 	}
826 
827 
828 	switch (FLG_DISP_VAL(flags)) {
829 	case DISP22:
830 		disp = sign_extend(f->f2a.disp22, 22);
831 		break;
832 
833 	case DISP19:
834 		disp = sign_extend(f->f2b.disp19, 19);
835 		break;
836 
837 	case DISP16:
838 		disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
839 		break;
840 
841 	}
842 
843 	disp *= 4;
844 
845 	if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
846 		r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
847 	else
848 		r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
849 
850 	if (r == NULL)
851 		return (-1);
852 
853 	if (f->f2a.a == 1)
854 		annul = ",a";
855 
856 	if ((flags & FLG_PRED) != 0) {
857 		if (f->f2b.p == 0) {
858 			pred = ",pn";
859 		} else {
860 			if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
861 				pred = ",pt";
862 		}
863 	}
864 
865 	(void) dis_snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
866 	prt_name(dhp, buf, 1);
867 
868 
869 	switch (FLG_DISP_VAL(flags)) {
870 	case DISP22:
871 		bprintf(dhp,
872 		    (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
873 		    (disp < 0) ? "-" : "+",
874 		    (disp < 0) ? (-disp) : disp);
875 		break;
876 
877 	case DISP19:
878 		bprintf(dhp,
879 		    (octal != 0) ? "%s, %s0%-5lo <" :
880 		    "%s, %s0x%-04lx <", r,
881 		    (disp < 0) ? "-" : "+",
882 		    (disp < 0) ? (-disp) : disp);
883 		break;
884 
885 	case DISP16:
886 		bprintf(dhp,
887 		    (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
888 		    r,
889 		    (disp < 0) ? "-" : "+",
890 		    (disp < 0) ? (-disp) : disp);
891 		break;
892 	}
893 
894 	curlen = strlen(dhx->dhx_buf);
895 	dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
896 	    dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, NULL);
897 
898 	(void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
899 
900 	return (0);
901 }
902 
903 
904 
905 /*
906  * print out the compare and swap instructions (casa/casxa)
907  * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
908  *	    casa/casxa [%rs1] %asi, %rs2, %rd
909  *
910  * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
911  * when an immediate ASI value is given as follows:
912  *
913  * casa  [%rs1]#ASI_P, %rs2, %rd    -> cas   [%rs1], %rs2, %rd
914  * casa  [%rs1]#ASI_P_L, %rs2, %rd  -> casl  [%rs1], %rs2, %rd
915  * casxa [%rs1]#ASI_P, %rs2, %rd    -> casx  [%rs1], %rs2, %rd
916  * casxa [%rs1]#ASI_P_L, %rs2, %rd  -> casxl [%rs1], %rs2, %rd
917  */
918 static int
fmt_cas(dis_handle_t * dhp,uint32_t instr,const char * name)919 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
920 {
921 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
922 	ifmt_t *f = (ifmt_t *)&instr;
923 	const char *asistr = NULL;
924 	int noasi = 0;
925 
926 	asistr = get_asi_name(f->f3.asi);
927 
928 	if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
929 		if (f->f3.op3 == 0x3c && f->f3.i == 0) {
930 			if (f->f3.asi == 0x80) {
931 				noasi = 1;
932 				name = "cas";
933 			}
934 
935 			if (f->f3.asi == 0x88) {
936 				noasi = 1;
937 				name = "casl";
938 			}
939 		}
940 
941 		if (f->f3.op3 == 0x3e && f->f3.i == 0) {
942 			if (f->f3.asi == 0x80) {
943 				noasi = 1;
944 				name = "casx";
945 			}
946 
947 			if (f->f3.asi == 0x88) {
948 				noasi = 1;
949 				name = "casxl";
950 			}
951 		}
952 	}
953 
954 	prt_name(dhp, name, 1);
955 
956 	bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
957 
958 	if (noasi == 0) {
959 		(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
960 		prt_asi(dhp, instr);
961 	}
962 
963 	bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
964 
965 	if (noasi == 0 && asistr != NULL)
966 		bprintf(dhp, "\t<%s>", asistr);
967 
968 	return (0);
969 }
970 
971 /*
972  * format a load/store instruction
973  * format: ldXX [%rs1 + %rs2], %rd	  load, i==0
974  *	    ldXX [%rs1 +/- nn], %rd	  load, i==1
975  *	    ldXX [%rs1 + %rs2] #XX, %rd   load w/ imm_asi, i==0
976  *	    ldXX [%rs1 +/- nn] %asi, %rd  load from asi[%asi], i==1
977  *
978  *	    stXX %rd, [%rs1 + %rs2]	  store, i==0
979  *	    stXX %rd, [%rs1 +/- nn]	  store, i==1
980  *	    stXX %rd, [%rs1 + %rs1] #XX   store to imm_asi, i==0
981  *	    stXX %rd, [%rs1 +/-nn] %asi   store to asi[%asi], i==1
982  *
983  * The register sets used for %rd are set in the instructions flags field
984  * The asi variants are used if FLG_ASI is set in the instructions flags field
985  *
986  * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set,
987  * When %rs1, %rs2 or nn are 0, they are not printed, i.e.
988  * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example
989  *
990  * The following synthetic instructions are also implemented:
991  *
992  * stb %g0, [addr] -> clrb [addr]    DIS_DEBUG_SYNTH_ALL
993  * sth %g0, [addr] -> crlh [addr]    DIS_DEBUG_SYNTH_ALL
994  * stw %g0, [addr] -> clr  [addr]    DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT
995  * stx %g0, [addr] -> clrx [addr]    DIS_DEBUG_SYNTH_ALL
996  *
997  * If DIS_DEBUG_COMPAT is set, the following substitutions also take place
998  *	lduw -> ld
999  *	ldtw -> ld
1000  *	stuw -> st
1001  *	sttw -> st
1002  */
1003 int
fmt_ls(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1004 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1005 {
1006 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1007 	ifmt_t *f = (ifmt_t *)&instr;
1008 	const char *regstr = NULL;
1009 	const char *asistr = NULL;
1010 
1011 	const char *iname = inp->in_data.in_def.in_name;
1012 	uint32_t flags = inp->in_data.in_def.in_flags;
1013 
1014 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1015 		prt_field("op", f->f3.op, 2);
1016 		prt_field("op3", f->f3.op3, 6);
1017 		prt_field("rs1", f->f3.rs1, 5);
1018 		prt_field("i", f->f3.i, 1);
1019 		if (f->f3.i != 0) {
1020 			prt_field("simm13", f->f3a.simm13, 13);
1021 		} else {
1022 			if ((flags & FLG_ASI) != 0)
1023 				prt_field("imm_asi", f->f3.asi, 8);
1024 			prt_field("rs2", f->f3.rs2, 5);
1025 		}
1026 		prt_field("rd", f->f3.rd, 5);
1027 	}
1028 
1029 	if (idx == 0x2d || idx == 0x3d) {
1030 		/* prefetch / prefetcha */
1031 
1032 		prt_name(dhp, iname, 1);
1033 
1034 		prt_address(dhp, instr, 0);
1035 
1036 		if (idx == 0x3d) {
1037 			(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1038 			prt_asi(dhp, instr);
1039 		}
1040 
1041 		(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1042 
1043 		/* fcn field is the same as rd */
1044 		if (prefetch_str[f->f3.rd] != NULL)
1045 			(void) strlcat(dhx->dhx_buf, prefetch_str[f->f3.rd],
1046 			    dhx->dhx_buflen);
1047 		else
1048 			prt_imm(dhp, f->f3.rd, 0);
1049 
1050 		if (idx == 0x3d && f->f3.i == 0) {
1051 			asistr = get_asi_name(f->f3.asi);
1052 			if (asistr != NULL)
1053 				bprintf(dhp, "\t<%s>", asistr);
1054 		}
1055 
1056 		return (0);
1057 	}
1058 
1059 	/* casa / casxa */
1060 	if (idx == 0x3c || idx == 0x3e)
1061 		return (fmt_cas(dhp, instr, iname));
1062 
1063 	/* synthetic instructions & special cases */
1064 	switch (idx) {
1065 	case 0x00:
1066 		/* ld */
1067 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1068 			iname = "lduw";
1069 		break;
1070 
1071 	case 0x03:
1072 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1073 			iname = "ldtw";
1074 		break;
1075 
1076 	case 0x04:
1077 		/* stw */
1078 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1079 			iname = "stuw";
1080 
1081 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1082 		    == 0)
1083 			break;
1084 
1085 		if (f->f3.rd == 0) {
1086 			iname = "clr";
1087 			flags = FLG_RD(REG_NONE);
1088 		}
1089 		break;
1090 
1091 	case 0x05:
1092 		/* stb */
1093 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1094 		    == 0)
1095 			break;
1096 
1097 		if (f->f3.rd == 0) {
1098 			iname = "clrb";
1099 			flags = FLG_RD(REG_NONE);
1100 		}
1101 		break;
1102 
1103 	case 0x06:
1104 		/* sth */
1105 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1106 		    == 0)
1107 			break;
1108 
1109 		if (f->f3.rd == 0) {
1110 			iname = "clrh";
1111 			flags = FLG_RD(REG_NONE);
1112 		}
1113 		break;
1114 
1115 	case 0x07:
1116 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1117 			iname = "sttw";
1118 		break;
1119 
1120 	case 0x0e:
1121 		/* stx */
1122 
1123 		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1124 		    == 0)
1125 			break;
1126 
1127 		if (f->f3.rd == 0) {
1128 			iname = "clrx";
1129 			flags = FLG_RD(REG_NONE);
1130 		}
1131 		break;
1132 
1133 	case 0x13:
1134 		/* ldtwa */
1135 		if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1136 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1137 			iname = "ldtwa";
1138 		break;
1139 
1140 	case 0x17:
1141 		/* sttwa */
1142 		if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1143 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1144 			iname = "sttwa";
1145 		break;
1146 
1147 	case 0x21:
1148 	case 0x25:
1149 		/*
1150 		 * on sparcv8 it merely says that rd != 1 should generate an
1151 		 * exception, on v9, it is illegal
1152 		 */
1153 		if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1154 			break;
1155 
1156 		iname = (idx == 0x21) ? "ldx" : "stx";
1157 
1158 		if (f->f3.rd > 1)
1159 			return (-1);
1160 
1161 		break;
1162 
1163 	case 0x31:
1164 		/* stda */
1165 		switch (f->f3.asi) {
1166 			case 0xc0:
1167 			case 0xc1:
1168 			case 0xc8:
1169 			case 0xc9:
1170 			case 0xc2:
1171 			case 0xc3:
1172 			case 0xca:
1173 			case 0xcb:
1174 			case 0xc4:
1175 			case 0xc5:
1176 			case 0xcc:
1177 			case 0xcd:
1178 				/*
1179 				 * store partial floating point, only valid w/
1180 				 * vis
1181 				 *
1182 				 * Somewhat confusingly, it uses the same op
1183 				 * code as 'stda' -- store double to alternate
1184 				 * space.  It is distinguised by specific
1185 				 * imm_asi values (as seen above), and
1186 				 * has a slightly different output syntax
1187 				 */
1188 
1189 				if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0)
1190 					break;
1191 				if (f->f3.i != 0)
1192 					break;
1193 				prt_name(dhp, iname, 1);
1194 				bprintf(dhp, "%s, %s, [%s] ",
1195 				    get_regname(dhp, REG_FPD, f->f3.rd),
1196 				    get_regname(dhp, REG_FPD, f->f3.rs2),
1197 				    get_regname(dhp, REG_FPD, f->f3.rs1));
1198 				prt_asi(dhp, instr);
1199 				asistr = get_asi_name(f->f3.asi);
1200 				if (asistr != NULL)
1201 					bprintf(dhp, "\t<%s>", asistr);
1202 
1203 				return (0);
1204 
1205 			default:
1206 				break;
1207 		}
1208 
1209 	}
1210 
1211 	regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1212 
1213 	if (f->f3.i == 0)
1214 		asistr = get_asi_name(f->f3.asi);
1215 
1216 	prt_name(dhp, iname, 1);
1217 
1218 	if ((flags & FLG_STORE) != 0) {
1219 		if (regstr[0] != '\0') {
1220 			(void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1221 			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1222 		}
1223 
1224 		prt_address(dhp, instr, 0);
1225 		if ((flags & FLG_ASI) != 0) {
1226 			(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1227 			prt_asi(dhp, instr);
1228 		}
1229 	} else {
1230 		prt_address(dhp, instr, 0);
1231 		if ((flags & FLG_ASI) != 0) {
1232 			(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1233 			prt_asi(dhp, instr);
1234 		}
1235 
1236 		if (regstr[0] != '\0') {
1237 			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1238 			(void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1239 		}
1240 	}
1241 
1242 	if ((flags & FLG_ASI) != 0 && asistr != NULL)
1243 		bprintf(dhp, "\t<%s>", asistr);
1244 
1245 	return (0);
1246 }
1247 
1248 static int
fmt_cpop(dis_handle_t * dhp,uint32_t instr,const inst_t * inp)1249 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1250 {
1251 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1252 	ifmt_t *f = (ifmt_t *)&instr;
1253 	int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1254 
1255 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1256 		prt_field("op", f->fcp.op, 2);
1257 		prt_field("op3", f->fcp.op3, 6);
1258 		prt_field("opc", f->fcp.opc, 9);
1259 		prt_field("rs1", f->fcp.rs1, 5);
1260 		prt_field("rs2", f->fcp.rs2, 5);
1261 		prt_field("rd", f->fcp.rd, 5);
1262 	}
1263 
1264 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1265 	prt_imm(dhp, f->fcp.opc, 0);
1266 
1267 	(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1268 	(void) prt_aluargs(dhp, instr, flags);
1269 
1270 	return (0);
1271 }
1272 
1273 static int
dis_fmt_rdwr(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1274 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1275 {
1276 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1277 	const char *psr_str = "%psr";
1278 	const char *wim_str = "%wim";
1279 	const char *tbr_str = "%tbr";
1280 
1281 	const char *name = inp->in_data.in_def.in_name;
1282 	const char *regstr = NULL;
1283 
1284 	ifmt_t *f = (ifmt_t *)&instr;
1285 
1286 	int rd = (idx < 0x30);
1287 	int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1288 	int ridx = f->f3.rs1;
1289 	int i, first;
1290 	int pr_rs1 = 1;
1291 	int pr_rs2 = 1;
1292 
1293 	int use_mask = 1;
1294 	uint32_t mask;
1295 
1296 	if (rd == 0)
1297 		ridx = f->f3.rd;
1298 
1299 	switch (idx) {
1300 	case 0x28:
1301 		/* rd */
1302 
1303 		/* stbar */
1304 		if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) {
1305 			prt_name(dhp, "stbar", 0);
1306 			return (0);
1307 		}
1308 
1309 		/* membar */
1310 		if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) &&
1311 		    (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) {
1312 
1313 			prt_name(dhp, "membar",
1314 			    ((f->fmb.cmask != 0) || (f->fmb.mmask != 0)));
1315 
1316 			first = 0;
1317 
1318 			for (i = 0; i < 4; ++i) {
1319 				if ((f->fmb.cmask & (1L << i)) != 0) {
1320 					bprintf(dhp, "%s%s",
1321 					    (first != 0) ? "|" : "",
1322 					    membar_cmask[i]);
1323 					first = 1;
1324 				}
1325 			}
1326 
1327 			for (i = 0; i < 5; ++i) {
1328 				if ((f->fmb.mmask & (1L << i)) != 0) {
1329 					bprintf(dhp, "%s%s",
1330 					    (first != 0) ? "|" : "",
1331 					    membar_mmask[i]);
1332 					first = 1;
1333 				}
1334 			}
1335 
1336 			return (0);
1337 		}
1338 
1339 		if (v9 != 0) {
1340 			regstr = v9_asr_names[ridx];
1341 			mask = v9_asr_rdmask;
1342 		} else {
1343 			regstr = asr_names[ridx];
1344 			mask = asr_rdmask;
1345 		}
1346 		break;
1347 
1348 	case 0x29:
1349 		if (v9 != 0) {
1350 			regstr = v9_hprivreg_names[ridx];
1351 			mask = v9_hpr_rdmask;
1352 		} else {
1353 			regstr = psr_str;
1354 			use_mask = 0;
1355 		}
1356 		break;
1357 
1358 	case 0x2a:
1359 		if (v9 != 0) {
1360 			regstr = v9_privreg_names[ridx];
1361 			mask = v9_pr_rdmask;
1362 		} else {
1363 			regstr = wim_str;
1364 			use_mask = 0;
1365 		}
1366 		break;
1367 
1368 	case 0x2b:
1369 		if (v9 != 0) {
1370 			/* flushw */
1371 			prt_name(dhp, name, 0);
1372 			return (0);
1373 		}
1374 
1375 		regstr = tbr_str;
1376 		use_mask = 0;
1377 		break;
1378 
1379 	case 0x30:
1380 		if (v9 != 0) {
1381 			regstr = v9_asr_names[ridx];
1382 			mask = v9_asr_wrmask;
1383 		} else {
1384 			regstr = asr_names[ridx];
1385 			mask = asr_wrmask;
1386 		}
1387 
1388 		/*
1389 		 * sir is shoehorned in here, per Ultrasparc 2007
1390 		 * hyperprivileged edition, section 7.88, all of
1391 		 * these must be true to distinguish from WRasr
1392 		 */
1393 		if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 &&
1394 		    f->f3.i == 1) {
1395 			prt_name(dhp, "sir", 1);
1396 			prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1397 			    IMM_SIGNED);
1398 			return (0);
1399 		}
1400 
1401 		/* synth: mov */
1402 		if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1403 		    == 0)
1404 			break;
1405 
1406 		if (v9 == 0) {
1407 			if (f->f3.rs1 == 0) {
1408 				name = "mov";
1409 				pr_rs1 = 0;
1410 			}
1411 
1412 			if ((f->f3.i == 0 && f->f3.rs2 == 0) ||
1413 			    (f->f3.i == 1 && f->f3a.simm13 == 0)) {
1414 				name = "mov";
1415 				pr_rs2 = 0;
1416 			}
1417 		}
1418 
1419 		if (pr_rs1 == 0)
1420 			pr_rs2 = 1;
1421 
1422 		break;
1423 
1424 	case 0x31:
1425 		/*
1426 		 * NOTE: due to the presence of an overlay entry for another
1427 		 * table, this case only happens when doing v8 instructions
1428 		 * only
1429 		 */
1430 		regstr = psr_str;
1431 		use_mask = 0;
1432 		break;
1433 
1434 	case 0x32:
1435 		if (v9 != 0) {
1436 			regstr = v9_privreg_names[ridx];
1437 			mask = v9_pr_wrmask;
1438 		} else {
1439 			regstr = wim_str;
1440 			use_mask = 0;
1441 		}
1442 		break;
1443 
1444 	case 0x33:
1445 		if (v9 != 0) {
1446 			regstr = v9_hprivreg_names[ridx];
1447 			mask = v9_hpr_wrmask;
1448 		} else {
1449 			regstr = tbr_str;
1450 			use_mask = 0;
1451 		}
1452 		break;
1453 	}
1454 
1455 	if (regstr == NULL)
1456 		return (-1);
1457 
1458 	if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1459 		return (-1);
1460 
1461 	prt_name(dhp, name, 1);
1462 
1463 	if (rd != 0) {
1464 		bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1465 	} else {
1466 		if (pr_rs1 == 1)
1467 			bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1468 
1469 		if (pr_rs2 != 0) {
1470 			if (f->f3.i == 1)
1471 				prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1472 				    IMM_SIGNED);
1473 			else
1474 				(void) strlcat(dhx->dhx_buf,
1475 				    reg_names[f->f3.rs2], dhx->dhx_buflen);
1476 			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1477 		}
1478 
1479 		(void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1480 	}
1481 
1482 	return (0);
1483 }
1484 
1485 /* ARGSUSED3 */
1486 int
fmt_trap(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1487 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1488 {
1489 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1490 	ifmt_t *f = (ifmt_t *)&instr;
1491 
1492 	int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1493 	int p_rs1, p_t;
1494 
1495 	if (f->ftcc.undef != 0)
1496 		return (-1);
1497 
1498 	if (icc_names[f->ftcc.cc] == NULL)
1499 		return (-1);
1500 
1501 	if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1502 		return (-1);
1503 
1504 	if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1505 		return (-1);
1506 
1507 	p_rs1 = ((f->ftcc.rs1 != 0) ||
1508 	    ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1509 
1510 	if (f->ftcc.i == 0) {
1511 		p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1512 
1513 		bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1514 		    (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1515 		    (v9 != 0) ? ", " : "",
1516 		    (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1517 		    (p_rs1 != 0) ? " + " : "",
1518 		    (p_t != 0) ? reg_names[f->f3.rs2] : "");
1519 	} else {
1520 		bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name,
1521 		    (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1522 		    (v9 != 0) ? ", " : "",
1523 		    (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1524 		    (p_rs1 != 0) ? " + " : "",
1525 		    f->ftcc.immtrap);
1526 	}
1527 	return (0);
1528 }
1529 
1530 static int
prt_shift(dis_handle_t * dhp,uint32_t instr,const inst_t * inp)1531 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1532 {
1533 	char name[5];
1534 	uint32_t cnt;
1535 
1536 	ifmt_t *f = (ifmt_t *)&instr;
1537 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
1538 
1539 	name[0] = '\0';
1540 	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
1541 
1542 	if (f->f3b.i == 1)
1543 		cnt = f->f3.rs2;
1544 
1545 	if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) {
1546 		cnt = f->f3b.shcnt;
1547 		(void) strlcat(name, "x", sizeof (name));
1548 	}
1549 
1550 	prt_name(dhp, name, 1);
1551 
1552 	if (f->f3b.i == 1)
1553 		bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1554 		    reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1555 	else
1556 		bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1557 		    reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1558 
1559 	return (0);
1560 }
1561 
1562 /* ARGSUSED3 */
1563 static int
prt_jmpl(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1564 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1565 {
1566 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1567 	const char *name = inp->in_data.in_def.in_name;
1568 	ifmt_t *f = (ifmt_t *)&instr;
1569 
1570 	if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1571 		name = "call";
1572 
1573 	if (f->f3.rd == 0) {
1574 		if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1575 			if (f->f3.rs1 == 15) {
1576 				prt_name(dhp, "retl", 0);
1577 				return (0);
1578 			}
1579 
1580 			if (f->f3.rs1 == 31) {
1581 				prt_name(dhp, "ret", 0);
1582 				return (0);
1583 			}
1584 		}
1585 
1586 		name = "jmp";
1587 	}
1588 
1589 	prt_name(dhp, name, 1);
1590 	prt_address(dhp, instr, 1);
1591 
1592 	if (f->f3.rd == 0)
1593 		return (0);
1594 
1595 	if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1596 		return (0);
1597 
1598 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1599 
1600 	return (0);
1601 }
1602 
1603 int
fmt_alu(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1604 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1605 {
1606 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1607 	ifmt_t *f = (ifmt_t *)&instr;
1608 
1609 	const char *name = inp->in_data.in_def.in_name;
1610 	int flags = inp->in_data.in_def.in_flags;
1611 	int arg = 0;
1612 
1613 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1614 		prt_field("op", f->f3.op, 2);
1615 		prt_field("op3", f->f3.op3, 6);
1616 		prt_field("rs1", f->f3.rs1, 5);
1617 
1618 		switch (idx) {
1619 			/* TODO: more formats */
1620 
1621 		default:
1622 			if (f->f3.i == 0)
1623 				prt_field("rs2", f->f3.rs2, 5);
1624 			else
1625 				prt_field("simm13", f->f3a.simm13, 13);
1626 
1627 			prt_field("rd", f->f3.rd, 5);
1628 		}
1629 
1630 	}
1631 
1632 	switch (idx) {
1633 	case 0x00:
1634 		/* add */
1635 
1636 		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1637 			break;
1638 
1639 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1640 		    f->f3a.simm13 == 1) {
1641 			name = "inc";
1642 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1643 			break;
1644 		}
1645 
1646 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1647 		    f->f3a.simm13 != 1) {
1648 			name = "inc";
1649 			flags = FLG_P1(REG_NONE);
1650 			break;
1651 		}
1652 		break;
1653 
1654 	case 0x02:
1655 		/* or */
1656 
1657 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1658 		    == 0)
1659 			break;
1660 
1661 		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0) {
1662 			if (f->f3.rs1 == f->f3.rd) {
1663 				name = "bset";
1664 				flags = FLG_P1(REG_NONE);
1665 				break;
1666 			}
1667 		}
1668 
1669 		if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1670 		    (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1671 		    (f->f3.rs1 == 0)) {
1672 			name = "clr";
1673 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1674 			break;
1675 		}
1676 
1677 		if (f->f3.rs1 == 0) {
1678 			name = "mov";
1679 			flags = FLG_P1(REG_NONE);
1680 			break;
1681 		}
1682 		break;
1683 
1684 	case 0x04:
1685 		/* sub */
1686 
1687 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1688 		    == 0)
1689 			break;
1690 
1691 		if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1692 			name = "neg";
1693 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1694 			break;
1695 		}
1696 
1697 		if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1698 			name = "neg";
1699 			flags = FLG_P1(REG_NONE);
1700 			break;
1701 		}
1702 
1703 		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1704 			break;
1705 
1706 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1707 		    f->f3a.simm13 == 1) {
1708 			name = "dec";
1709 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1710 			break;
1711 		}
1712 
1713 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1714 		    f->f3a.simm13 != 1) {
1715 			name = "dec";
1716 			flags = FLG_P1(REG_NONE);
1717 			break;
1718 		}
1719 		break;
1720 
1721 	case 0x07:
1722 		/* xnor */
1723 
1724 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1725 		    == 0)
1726 			break;
1727 
1728 		/*
1729 		 * xnor -> not when you have:
1730 		 *	 xnor %rs1, 0x0 or %g0, %rd
1731 		 */
1732 		if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1733 		    (f->f3.i == 1 && f->f3a.simm13 != 0))
1734 			break;
1735 
1736 		name = "not";
1737 
1738 		if (f->f3.rs1 == f->f3.rd)
1739 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1740 			    FLG_P3(REG_INT);
1741 		else
1742 			flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1743 			    FLG_P3(REG_INT);
1744 
1745 		break;
1746 
1747 	case 0x10:
1748 		/* addcc */
1749 
1750 		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1751 			break;
1752 
1753 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1754 		    f->f3a.simm13 == 1) {
1755 			name = "inccc";
1756 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1757 			break;
1758 		}
1759 
1760 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1761 		    f->f3a.simm13 != 1) {
1762 			name = "inccc";
1763 			flags = FLG_P1(REG_NONE);
1764 			break;
1765 		}
1766 		break;
1767 
1768 	case 0x11:
1769 		/* andcc */
1770 
1771 		if (f->f3.rd != 0)
1772 			break;
1773 
1774 		if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1775 		    == 0)
1776 			break;
1777 
1778 		if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) &&
1779 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1780 			break;
1781 
1782 		name = "btst";
1783 		flags = FLG_P1(REG_NONE);
1784 		f->f3.rd = f->f3.rs1;
1785 		break;
1786 
1787 	case 0x12:
1788 		/* orcc */
1789 
1790 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1791 		    == 0)
1792 			break;
1793 
1794 		if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1795 			name = "tst";
1796 			flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1797 			break;
1798 		}
1799 
1800 		if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1801 			name = "tst";
1802 			flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1803 			break;
1804 		}
1805 
1806 		break;
1807 
1808 	case 0x14:
1809 		/* subcc */
1810 
1811 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1812 		    == 0)
1813 			break;
1814 
1815 		if (f->f3.rd == 0) {
1816 			name = "cmp";
1817 			flags = FLG_P3(REG_NONE);
1818 			break;
1819 		}
1820 
1821 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
1822 			break;
1823 
1824 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1825 		    f->f3a.simm13 == 1) {
1826 			name = "deccc";
1827 			flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1828 			break;
1829 		}
1830 
1831 		if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1832 		    f->f3a.simm13 != 1) {
1833 			name = "deccc";
1834 			flags = FLG_P1(REG_NONE);
1835 			break;
1836 		}
1837 
1838 		break;
1839 
1840 	case 0x25:
1841 	case 0x26:
1842 	case 0x27:
1843 		return (prt_shift(dhp, instr, inp));
1844 
1845 	case 0x28:
1846 	case 0x29:
1847 	case 0x2a:
1848 	case 0x2b:
1849 	case 0x30:
1850 	case 0x31:
1851 	case 0x32:
1852 	case 0x33:
1853 		return (dis_fmt_rdwr(dhp, instr, inp, idx));
1854 
1855 	case 0x36:
1856 	case 0x37:
1857 		/* NOTE: overlayed on v9 */
1858 		if ((dhp->dh_flags & DIS_SPARC_V8) != 0)
1859 			return (fmt_cpop(dhp, instr, inp));
1860 		break;
1861 
1862 	case 0x38:
1863 		/* jmpl */
1864 		return (prt_jmpl(dhp, instr, inp, idx));
1865 
1866 	case 0x39:
1867 		/* rett / return */
1868 		prt_name(dhp, name, 1);
1869 		prt_address(dhp, instr, 1);
1870 		return (0);
1871 
1872 	case 0x3b:
1873 		/* flush */
1874 		prt_name(dhp, name, 1);
1875 		prt_address(dhp, instr, 0);
1876 		return (0);
1877 
1878 	case 0x3c:
1879 	case 0x3d:
1880 		/* save / restore */
1881 		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1882 		    == 0)
1883 			break;
1884 
1885 		if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1886 			break;
1887 
1888 		if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0))
1889 			break;
1890 
1891 		prt_name(dhp, name, 0);
1892 		return (0);
1893 	}
1894 
1895 	if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1896 	    FLG_P3_VAL(flags) != REG_NONE)
1897 		arg = 1;
1898 
1899 	prt_name(dhp, name, (arg != 0));
1900 	prt_aluargs(dhp, instr, flags);
1901 
1902 	return (0);
1903 }
1904 
1905 /* ARGSUSED1 */
1906 int
fmt_regwin(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1907 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1908 {
1909 	prt_name(dhp, inp->in_data.in_def.in_name, 0);
1910 	return (0);
1911 }
1912 
1913 /* ARGSUSED1 */
1914 int
fmt_trap_ret(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1915 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1916 {
1917 	ifmt_t *f = (ifmt_t *)&instr;
1918 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1919 
1920 	if (f->f3.rd == 0xf) {
1921 		/* jpriv */
1922 		prt_address(dhp, instr, 1);
1923 	}
1924 
1925 	return (0);
1926 }
1927 
1928 /* ARGSUSED3 */
1929 int
fmt_movcc(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1930 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1931 {
1932 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1933 	ifmt_t *f = (ifmt_t *)&instr;
1934 	const char **regs = NULL;
1935 
1936 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1937 		prt_field("op", f->f3c.op, 2);
1938 		prt_field("op3", f->f3c.op3, 6);
1939 		prt_field("cond", f->f3c.cond, 4);
1940 		prt_field("cc2", f->f3c.cc2, 1);
1941 		prt_field("cc", f->f3c.cc, 2);
1942 		prt_field("i", f->f3c.i, 1);
1943 
1944 		if (f->f3c.i == 0)
1945 			prt_field("rs2", f->f3.rs2, 5);
1946 		else
1947 			prt_field("simm11", f->f3c.simm11, 11);
1948 
1949 		prt_field("rd", f->f3.rd, 5);
1950 	}
1951 
1952 	if (f->f3c.cc2 == 0) {
1953 		regs = fcc_names;
1954 	} else {
1955 		regs = icc_names;
1956 		if (regs[f->f3c.cc] == NULL)
1957 			return (-1);
1958 	}
1959 
1960 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1961 
1962 	bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1963 
1964 	if (f->f3c.i == 1)
1965 		prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1966 	else
1967 		(void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1968 		    dhx->dhx_buflen);
1969 
1970 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1971 
1972 	return (0);
1973 }
1974 
1975 /* ARGSUSED3 */
1976 int
fmt_movr(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1977 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1978 {
1979 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1980 	ifmt_t *f = (ifmt_t *)&instr;
1981 
1982 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1983 
1984 	bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1985 
1986 	if (f->f3d.i == 1)
1987 		prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1988 	else
1989 		(void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1990 		    dhx->dhx_buflen);
1991 
1992 	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1993 
1994 	return (0);
1995 }
1996 
1997 /* ARGSUSED3 */
1998 int
fmt_fpop1(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)1999 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2000 {
2001 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2002 	ifmt_t *f = (ifmt_t *)&instr;
2003 	int flags = inp->in_data.in_def.in_flags;
2004 
2005 	flags |= FLG_NOIMM;
2006 
2007 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2008 		prt_field("op", f->f3.op, 2);
2009 		prt_field("op3", f->f3.op3, 6);
2010 		prt_field("opf", f->fcmp.opf, 9);
2011 		prt_field("rs1", f->f3.rs1, 5);
2012 		prt_field("rs2", f->f3.rs2, 5);
2013 		prt_field("rd", f->f3.rd, 5);
2014 	}
2015 
2016 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2017 	prt_aluargs(dhp, instr, flags);
2018 
2019 	return (0);
2020 }
2021 
2022 int
fmt_fpop2(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2023 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2024 {
2025 	static const char *condstr_icc[16] = {
2026 		"n", "e",  "le", "l",  "leu", "lu",  "neg", "vs",
2027 		"a", "nz", "g",  "ge", "gu",  "geu", "pos", "vc"
2028 	};
2029 
2030 	static const char *condstr_fcc[16] = {
2031 		"n", "nz", "lg", "ul", "l",   "ug", "g",   "u",
2032 		"a", "e",  "ue", "ge", "uge", "le", "ule", "o"
2033 	};
2034 
2035 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2036 	ifmt_t *f = (ifmt_t *)&instr;
2037 	const char *ccstr = "";
2038 	char name[15];
2039 
2040 	int flags = inp->in_data.in_def.in_flags;
2041 	int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2042 	    idx == 0x55 || idx == 0x56 || idx == 0x57);
2043 	int is_fmov = (idx & 0x3f);
2044 	int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2045 	int is_compat = ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0);
2046 
2047 	int p_cc = 0;
2048 
2049 	is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2050 
2051 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2052 		prt_field("op", f->f3.op, 2);
2053 		prt_field("op3", f->f3.op3, 6);
2054 		prt_field("opf", f->fcmp.opf, 9);
2055 
2056 		switch (idx & 0x3f) {
2057 		case 0x51:
2058 		case 0x52:
2059 		case 0x53:
2060 		case 0x55:
2061 		case 0x56:
2062 		case 0x57:
2063 			prt_field("cc", f->fcmp.cc, 2);
2064 			prt_field("rs1", f->f3.rs1, 5);
2065 			prt_field("rs2", f->f3.rs2, 5);
2066 			break;
2067 
2068 		case 0x01:
2069 		case 0x02:
2070 		case 0x03:
2071 			prt_field("opf_low", f->fmv.opf, 6);
2072 			prt_field("cond", f->fmv.cond, 4);
2073 			prt_field("opf_cc", f->fmv.cc, 3);
2074 			prt_field("rs2", f->fmv.rs2, 5);
2075 			break;
2076 
2077 		default:
2078 			prt_field("rs1", f->f3.rs1, 5);
2079 			prt_field("rs2", f->f3.rs2, 5);
2080 			prt_field("rd", f->f3.rd, 5);
2081 		}
2082 	}
2083 
2084 	name[0] = '\0';
2085 	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
2086 
2087 	if (is_fmov != 0) {
2088 		(void) strlcat(name,
2089 		    (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond]
2090 		    : condstr_icc[f->fmv.cond],
2091 		    sizeof (name));
2092 	}
2093 
2094 	prt_name(dhp, name, 1);
2095 
2096 	if (is_cmp != 0)
2097 		ccstr = fcc_names[f->fcmp.cc];
2098 
2099 	if (is_fmov != 0)
2100 		ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3]
2101 		    : icc_names[f->fmv.cc & 0x3];
2102 
2103 	if (ccstr == NULL)
2104 		return (-1);
2105 
2106 	p_cc = (is_compat == 0 || is_v9 != 0 ||
2107 	    (is_cmp != 0 && f->fcmp.cc != 0) ||
2108 	    (is_fmov != 0 && f->fmv.cc != 0));
2109 
2110 	if (p_cc != 0)
2111 		bprintf(dhp, "%s, ", ccstr);
2112 
2113 	prt_aluargs(dhp, instr, flags);
2114 
2115 	return (0);
2116 }
2117 
2118 int
fmt_vis(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2119 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2120 {
2121 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2122 	ifmt_t *f = (ifmt_t *)&instr;
2123 	int flags = inp->in_data.in_def.in_flags;
2124 
2125 	if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2126 		prt_field("op", f->f3.op, 2);
2127 		prt_field("op3", f->f3.op3, 6);
2128 		prt_field("opf", f->fcmp.opf, 9);
2129 
2130 		if (idx == 0x081) {
2131 			prt_field("mode", instr & 02L, 2);
2132 		} else {
2133 			prt_field("rs1", f->f3.rs1, 5);
2134 			prt_field("rs2", f->f3.rs2, 5);
2135 			prt_field("rd", f->f3.rd, 5);
2136 		}
2137 	}
2138 
2139 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2140 
2141 	if (idx == 0x081) {
2142 		/* siam */
2143 		bprintf(dhp, "%d", instr & 0x7L);
2144 		return (0);
2145 	}
2146 
2147 	prt_aluargs(dhp, instr, flags);
2148 
2149 	return (0);
2150 }
2151 
2152 /* ARGSUSED3 */
2153 int
fmt_fused(dis_handle_t * dhp,uint32_t instr,const inst_t * inp,int idx)2154 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2155 {
2156 	ifmt_t *f = (ifmt_t *)&instr;
2157 	int flags = inp->in_data.in_def.in_flags;
2158 
2159 	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2160 	bprintf(dhp, "%s, %s, %s, %s",
2161 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1),
2162 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2),
2163 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3),
2164 	    get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd));
2165 
2166 	return (0);
2167 }
2168 /*
2169  * put name into the output buffer
2170  * if add_space !=0, append a space after it
2171  */
2172 static void
prt_name(dis_handle_t * dhp,const char * name,int add_space)2173 prt_name(dis_handle_t *dhp, const char *name, int add_space)
2174 {
2175 	bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name);
2176 }
2177 
2178 /*
2179  * For debugging, print out a field of the instruction
2180  * field is the name of the field
2181  * val is the value of the field
2182  * len is the length of the field (in bits)
2183  */
2184 #if defined(DIS_STANDALONE)
2185 /* ARGSUSED */
2186 static void
prt_field(const char * field,uint32_t val,int len)2187 prt_field(const char *field, uint32_t val, int len)
2188 {
2189 
2190 }
2191 
2192 #else
2193 static void
prt_field(const char * field,uint32_t val,int len)2194 prt_field(const char *field, uint32_t val, int len)
2195 {
2196 	(void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val);
2197 	prt_binary(val, len);
2198 	(void) fprintf(stderr, ")\n");
2199 }
2200 #endif /* DIS_STANDALONE */
2201 
2202 /*
2203  * sign extend a val (that is 'bits' bits in length) to a 32-bit signed
2204  * integer
2205  */
2206 static int32_t
sign_extend(int32_t val,uint32_t bits)2207 sign_extend(int32_t val, uint32_t bits)
2208 {
2209 	uint32_t mask;
2210 
2211 	ASSERT(bits > 0);
2212 	mask = 1L << (bits - 1);	/* 2**(bits - 1) */
2213 	return (-(val & mask) + (val & ~mask));
2214 }
2215 
2216 /*
2217  * print out an immediate (i.e. constant) value
2218  * val is the value
2219  * format indicates if it is:
2220  * 0		 Unsigned
2221  * IMM_SIGNED  A signed value (prepend +/- to the value)
2222  * IMM_ADDR    Part of an address expression (prepend +/- but with a space
2223  *		   between the sign and the value for things like [%i1 + 0x55]
2224  */
2225 static void
prt_imm(dis_handle_t * dhp,uint32_t val,int format)2226 prt_imm(dis_handle_t *dhp, uint32_t val, int format)
2227 {
2228 	const char *fmtstr = NULL;
2229 	int32_t sv = (int32_t)val;
2230 	int octal = dhp->dh_flags & DIS_OCTAL;
2231 
2232 	switch (format) {
2233 	case IMM_ADDR:
2234 		if (sv < 0) {
2235 			sv = -sv;
2236 			fmtstr = (octal != 0) ? "- 0%lo" : "- 0x%lx";
2237 		} else {
2238 			fmtstr = (octal != 0) ? "+ 0%lo" : "+ 0x%lx";
2239 		}
2240 		break;
2241 
2242 	case IMM_SIGNED:
2243 		if (sv < 0) {
2244 			sv = -sv;
2245 			fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx";
2246 			break;
2247 		}
2248 		/* fall through */
2249 
2250 	default:
2251 		fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2252 	}
2253 
2254 	bprintf(dhp, fmtstr, sv);
2255 }
2256 
2257 /*
2258  * return the symbolic name of a register
2259  * regset is one of the REG_* values indicating which type of register it is
2260  * such as integer, floating point, etc.
2261  * idx is the numeric value of the register
2262  *
2263  * If regset is REG_NONE, an empty, but non-NULL string is returned
2264  * NULL may be returned if the index indicates an invalid register value
2265  * such as with the %icc/%xcc sets
2266  */
2267 static const char *
get_regname(dis_handle_t * dhp,int regset,uint32_t idx)2268 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2269 {
2270 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2271 	const char *regname = NULL;
2272 
2273 	switch (regset) {
2274 	case REG_INT:
2275 		regname = reg_names[idx];
2276 		break;
2277 
2278 	case REG_FP:
2279 		regname = freg_names[idx];
2280 		break;
2281 
2282 	case REG_FPD:
2283 		if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) ||
2284 		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
2285 			regname = fdreg_names[idx];
2286 		else
2287 			regname = compat_fdreg_names[idx];
2288 
2289 		break;
2290 
2291 	case REG_FPQ:
2292 		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
2293 			regname = fqreg_names[idx];
2294 		else
2295 			regname = freg_names[idx];
2296 
2297 		break;
2298 
2299 	case REG_CP:
2300 		regname = cpreg_names[idx];
2301 		break;
2302 
2303 	case REG_ICC:
2304 		regname = icc_names[idx];
2305 		break;
2306 
2307 	case REG_FCC:
2308 		regname = fcc_names[idx];
2309 		break;
2310 
2311 	case REG_FSR:
2312 		regname = "%fsr";
2313 		break;
2314 
2315 	case REG_CSR:
2316 		regname = "%csr";
2317 		break;
2318 
2319 	case REG_CQ:
2320 		regname = "%cq";
2321 		break;
2322 
2323 	case REG_NONE:
2324 		regname = "";
2325 		break;
2326 	}
2327 
2328 	return (regname);
2329 }
2330 
2331 /*
2332  * output the asi value from the instruction
2333  *
2334  * TODO: investigate if this should perhaps have a mask -- are undefined ASI
2335  *	  values for an instruction still disassembled??
2336  */
2337 static void
prt_asi(dis_handle_t * dhp,uint32_t instr)2338 prt_asi(dis_handle_t *dhp, uint32_t instr)
2339 {
2340 	ifmt_t *f = (ifmt_t *)&instr;
2341 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2342 
2343 	if (f->f3.i != 0)
2344 		bprintf(dhp, "%%asi");
2345 	else
2346 		bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi);
2347 
2348 }
2349 
2350 /*
2351  * put an address expression into the output buffer
2352  *
2353  * instr is the instruction to use
2354  * if nobrackets != 0, [] are not added around the instruction
2355  *
2356  * Currently this option is set when printing out the address portion
2357  * of a jmpl instruction, but otherwise 0 for load/stores
2358  *
2359  * If no debug flags are set, the full expression is output, even when
2360  * %g0 or 0x0 appears in the address
2361  *
2362  * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0
2363  * appear in the address, they are not output.  If the wierd (and probably
2364  * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered,
2365  * [%g0] is output
2366  */
2367 static void
prt_address(dis_handle_t * dhp,uint32_t instr,int nobrackets)2368 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
2369 {
2370 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2371 	ifmt_t *f = (ifmt_t *)&instr;
2372 	int32_t simm13;
2373 	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2374 	int p1 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2375 	int p2 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2376 
2377 	if (f->f3a.i == 0) {
2378 		p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2379 		p2 |= (f->f3.rs2 != 0);
2380 
2381 		bprintf(dhp, "%s%s%s%s%s",
2382 		    (nobrackets == 0) ? "[" : "",
2383 		    (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2384 		    (p1 != 0 && p2 != 0) ? " + " : "",
2385 		    (p2 != 0) ? reg_names[f->f3.rs2] : "",
2386 		    (nobrackets == 0) ? "]" : "");
2387 	} else {
2388 		const char *sign;
2389 
2390 		simm13 = sign_extend(f->f3a.simm13, 13);
2391 		sign = (simm13 < 0) ? "-" : "+";
2392 
2393 		p1 |= (f->f3a.rs1 != 0);
2394 		p2 |= (p1 == 0 || simm13 != 0);
2395 
2396 		if (p1 == 0 && simm13 == 0)
2397 			p2 = 1;
2398 
2399 		if (p1 == 0 && simm13 >= 0)
2400 			sign = "";
2401 
2402 		if (p2 != 0)
2403 			bprintf(dhp,
2404 			    (octal != 0) ? "%s%s%s%s%s0%lo%s" :
2405 			    "%s%s%s%s%s0x%lx%s",
2406 			    (nobrackets == 0) ? "[" : "",
2407 			    (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2408 			    (p1 != 0) ? " " : "",
2409 			    sign,
2410 			    (p1 != 0) ? " " : "",
2411 			    (simm13 < 0) ? -(simm13) : simm13,
2412 			    (nobrackets == 0) ? "]" : "");
2413 		else
2414 			bprintf(dhp, "%s%s%s",
2415 			    (nobrackets == 0) ? "[" : "",
2416 			    reg_names[f->f3a.rs1],
2417 			    (nobrackets == 0) ? "]" : "");
2418 	}
2419 }
2420 
2421 /*
2422  * print out the arguments to an alu operation (add, sub, etc.)
2423  * conatined in 'instr'
2424  *
2425  * alu instructions have the following format:
2426  *	 %rs1, %rs2, %rd    (i == 0)
2427  *	 %rs1, 0xnnn, %rd   (i == 1)
2428  *	   ^	^	^
2429  *	   |	|	|
2430  *	  p1    p2	p3
2431  *
2432  * flags indicates the register set to use for each position (p1, p2, p3)
2433  * as well as if immediate values (i == 1) are allowed
2434  *
2435  * if flags indicates a specific position has REG_NONE set as it's register
2436  * set, it is omitted from the output.  This is primarly used for certain
2437  * floating point operations
2438  */
2439 static void
prt_aluargs(dis_handle_t * dhp,uint32_t instr,uint32_t flags)2440 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
2441 {
2442 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2443 	ifmt_t *f = (ifmt_t *)&instr;
2444 	const char *r1, *r2, *r3;
2445 	int p1, p2, p3;
2446 	unsigned int opf = 0;
2447 
2448 	r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1);
2449 	r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2);
2450 	r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd);
2451 
2452 	p1 = (FLG_P1_VAL(flags) != REG_NONE);
2453 	p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE));
2454 	p3 = (FLG_RD_VAL(flags) != REG_NONE);
2455 
2456 	if (r1 == NULL || r1[0] == '\0')
2457 		p1 = 0;
2458 
2459 	if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2460 		p2 = 0;
2461 
2462 	if (r3 == NULL || r3[0] == '\0')
2463 		p3 = 0;
2464 
2465 	if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2466 		opf = f->fcmp.opf;
2467 
2468 	if ((opf == 0x151) || (opf == 0x152)) {
2469 		(void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2470 		(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2471 		p3 = 0;
2472 	}
2473 
2474 	if (p1 != 0) {
2475 		(void) strlcat(dhx->dhx_buf, r1, dhx->dhx_buflen);
2476 		if (p2 != 0 || p3 != 0)
2477 			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2478 	}
2479 
2480 	if (p2 != 0) {
2481 		if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0))
2482 			(void) strlcat(dhx->dhx_buf, r2, dhx->dhx_buflen);
2483 		else
2484 			prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
2485 			    IMM_SIGNED);
2486 
2487 		if (p3 != 0)
2488 			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2489 	}
2490 
2491 	if (p3 != 0)
2492 		(void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2493 }
2494 
2495 static const char *
get_asi_name(uint8_t asi)2496 get_asi_name(uint8_t asi)
2497 {
2498 	switch (asi) {
2499 		case 0x04:
2500 			return ("ASI_N");
2501 
2502 		case 0x0c:
2503 			return ("ASI_NL");
2504 
2505 		case 0x10:
2506 			return ("ASI_AIUP");
2507 
2508 		case 0x11:
2509 			return ("ASI_AIUS");
2510 
2511 		case 0x14:
2512 			return ("ASI_REAL");
2513 
2514 		case 0x15:
2515 			return ("ASI_REAL_IO");
2516 
2517 		case 0x16:
2518 			return ("ASI_BLK_AIUP");
2519 
2520 		case 0x17:
2521 			return ("ASI_BLK_AIUS");
2522 
2523 		case 0x18:
2524 			return ("ASI_AIUPL");
2525 
2526 		case 0x19:
2527 			return ("ASI_AIUSL");
2528 
2529 		case 0x1c:
2530 			return ("ASI_REAL_L");
2531 
2532 		case 0x1d:
2533 			return ("ASI_REAL_IO_L");
2534 
2535 		case 0x1e:
2536 			return ("ASI_BLK_AIUPL");
2537 
2538 		case 0x1f:
2539 			return ("ASI_BLK_AIUS_L");
2540 
2541 		case 0x20:
2542 			return ("ASI_SCRATCHPAD");
2543 
2544 		case 0x21:
2545 			return ("ASI_MMU_CONTEXTID");
2546 
2547 		case 0x22:
2548 			return ("ASI_TWINX_AIUP");
2549 
2550 		case 0x23:
2551 			return ("ASI_TWINX_AIUS");
2552 
2553 		case 0x25:
2554 			return ("ASI_QUEUE");
2555 
2556 		case 0x26:
2557 			return ("ASI_TWINX_R");
2558 
2559 		case 0x27:
2560 			return ("ASI_TWINX_N");
2561 
2562 		case 0x2a:
2563 			return ("ASI_LDTX_AIUPL");
2564 
2565 		case 0x2b:
2566 			return ("ASI_TWINX_AIUS_L");
2567 
2568 		case 0x2e:
2569 			return ("ASI_TWINX_REAL_L");
2570 
2571 		case 0x2f:
2572 			return ("ASI_TWINX_NL");
2573 
2574 		case 0x30:
2575 			return ("ASI_AIPP");
2576 
2577 		case 0x31:
2578 			return ("ASI_AIPS");
2579 
2580 		case 0x36:
2581 			return ("ASI_AIPN");
2582 
2583 		case 0x38:
2584 			return ("ASI_AIPP_L");
2585 
2586 		case 0x39:
2587 			return ("ASI_AIPS_L");
2588 
2589 		case 0x3e:
2590 			return ("ASI_AIPN_L");
2591 
2592 		case 0x41:
2593 			return ("ASI_CMT_SHARED");
2594 
2595 		case 0x4f:
2596 			return ("ASI_HYP_SCRATCHPAD");
2597 
2598 		case 0x50:
2599 			return ("ASI_IMMU");
2600 
2601 		case 0x52:
2602 			return ("ASI_MMU_REAL");
2603 
2604 		case 0x54:
2605 			return ("ASI_MMU");
2606 
2607 		case 0x55:
2608 			return ("ASI_ITLB_DATA_ACCESS_REG");
2609 
2610 		case 0x56:
2611 			return ("ASI_ITLB_TAG_READ_REG");
2612 
2613 		case 0x57:
2614 			return ("ASI_IMMU_DEMAP");
2615 
2616 		case 0x58:
2617 			return ("ASI_DMMU / ASI_UMMU");
2618 
2619 		case 0x5c:
2620 			return ("ASI_DTLB_DATA_IN_REG");
2621 
2622 		case 0x5d:
2623 			return ("ASI_DTLB_DATA_ACCESS_REG");
2624 
2625 		case 0x5e:
2626 			return ("ASI_DTLB_TAG_READ_REG");
2627 
2628 		case 0x5f:
2629 			return ("ASI_DMMU_DEMAP");
2630 
2631 		case 0x63:
2632 			return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE");
2633 
2634 		case 0x80:
2635 			return ("ASI_P");
2636 
2637 		case 0x81:
2638 			return ("ASI_S");
2639 
2640 		case 0x82:
2641 			return ("ASI_PNF");
2642 
2643 		case 0x83:
2644 			return ("ASI_SNF");
2645 
2646 		case 0x88:
2647 			return ("ASI_PL");
2648 
2649 		case 0x89:
2650 			return ("ASI_SL");
2651 
2652 		case 0x8a:
2653 			return ("ASI_PNFL");
2654 
2655 		case 0x8b:
2656 			return ("ASI_SNFL");
2657 
2658 		case 0xc0:
2659 			return ("ASI_PST8_P");
2660 
2661 		case 0xc1:
2662 			return ("ASI_PST8_S");
2663 
2664 		case 0xc2:
2665 			return ("ASI_PST16_P");
2666 
2667 		case 0xc3:
2668 			return ("ASI_PST16_S");
2669 
2670 		case 0xc4:
2671 			return ("ASI_PST32_P");
2672 
2673 		case 0xc5:
2674 			return ("ASI_PST32_S");
2675 
2676 		case 0xc8:
2677 			return ("ASI_PST8_PL");
2678 
2679 		case 0xc9:
2680 			return ("ASI_PST8_SL");
2681 
2682 		case 0xca:
2683 			return ("ASI_PST16_PL");
2684 
2685 		case 0xcb:
2686 			return ("ASI_PST16_SL");
2687 
2688 		case 0xcc:
2689 			return ("ASI_PST32_PL");
2690 
2691 		case 0xcd:
2692 			return ("ASI_PST32_SL");
2693 
2694 		case 0xd0:
2695 			return ("ASI_FL8_P");
2696 
2697 		case 0xd1:
2698 			return ("ASI_FL8_S");
2699 
2700 		case 0xd2:
2701 			return ("ASI_FL16_P");
2702 
2703 		case 0xd3:
2704 			return ("ASI_FL16_S");
2705 
2706 		case 0xd8:
2707 			return ("ASI_FL8_PL");
2708 
2709 		case 0xd9:
2710 			return ("ASI_FL8_SL");
2711 
2712 		case 0xda:
2713 			return ("ASI_FL16_PL");
2714 
2715 		case 0xdb:
2716 			return ("ASI_FL16_SL");
2717 
2718 		case 0xe0:
2719 			return ("ASI_BLK_COMMIT_P");
2720 
2721 		case 0xe1:
2722 			return ("ASI_BLK_SOMMIT_S");
2723 
2724 		case 0xe2:
2725 			return ("ASI_TWINX_P");
2726 
2727 		case 0xe3:
2728 			return ("ASI_TWINX_S");
2729 
2730 		case 0xea:
2731 			return ("ASI_TWINX_PL");
2732 
2733 		case 0xeb:
2734 			return ("ASI_TWINX_SL");
2735 
2736 		case 0xf0:
2737 			return ("ASI_BLK_P");
2738 
2739 		case 0xf1:
2740 			return ("ASI_BLK_S");
2741 
2742 		case 0xf8:
2743 			return ("ASI_BLK_PL");
2744 
2745 		case 0xf9:
2746 			return ("ASI_BLK_SL");
2747 
2748 		default:
2749 			return (NULL);
2750 	}
2751 }
2752 
2753 /*
2754  * just a handy function that takes care of managing the buffer length
2755  * w/ printf
2756  */
2757 
2758 /*
2759  * PRINTF LIKE 1
2760  */
2761 static void
bprintf(dis_handle_t * dhp,const char * fmt,...)2762 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2763 {
2764 	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2765 	size_t curlen;
2766 	va_list ap;
2767 
2768 	curlen = strlen(dhx->dhx_buf);
2769 
2770 	va_start(ap, fmt);
2771 	(void) dis_vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen -
2772 	    curlen, fmt, ap);
2773 	va_end(ap);
2774 }
2775