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