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