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