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