8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libdisasm / common / dis_sparc_fmt.c
blobceaafa47fef0030e052631bc3396f2d689f00401
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright 2009 Jason King. All rights reserved.
29 * Use is subject to license terms.
30 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
34 #include <sys/byteorder.h>
35 #include <sys/debug.h>
36 #include <stdarg.h>
38 #if !defined(DIS_STANDALONE)
39 #include <stdio.h>
40 #endif /* DIS_STANDALONE */
42 #include "libdisasm.h"
43 #include "libdisasm_impl.h"
44 #include "dis_sparc.h"
45 #include "dis_sparc_fmt.h"
47 extern char *strncpy(char *, const char *, size_t);
48 extern size_t strlen(const char *);
49 extern int strcmp(const char *, const char *);
50 extern int strncmp(const char *, const char *, size_t);
51 extern size_t strlcat(char *, const char *, size_t);
52 extern size_t strlcpy(char *, const char *, size_t);
55 * This file has the functions that do all the dirty work of outputting the
56 * disassembled instruction
58 * All the non-static functions follow the format_fcn (in dis_sparc.h):
59 * Input:
60 * disassembler handle/context
61 * instruction to disassemble
62 * instruction definition pointer (inst_t *)
63 * index in the table of the instruction
64 * Return:
65 * 0 Success
66 * !0 Invalid instruction
68 * Generally, instructions found in the same table use the same output format
69 * or have a few minor differences (which are described in the 'flags' field
70 * of the instruction definition. In some cases, certain instructions differ
71 * radically enough from those in the same table, that their own format
72 * function is used.
74 * Typically each table has a unique format function defined in this file. In
75 * some cases (such as branches) a common one for all the tables is used.
77 * When adding support for new instructions, it is largely a judgement call
78 * as to when a new format function is defined.
81 /* The various instruction formats of a sparc instruction */
83 #if defined(_BIT_FIELDS_HTOL)
84 typedef struct format1 {
85 uint32_t op:2;
86 uint32_t disp30:30;
87 } format1_t;
88 #elif defined(_BIT_FIELDS_LTOH)
89 typedef struct format1 {
90 uint32_t disp30:30;
91 uint32_t op:2;
92 } format1_t;
93 #else
94 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
95 #endif
97 #if defined(_BIT_FIELDS_HTOL)
98 typedef struct format2 {
99 uint32_t op:2;
100 uint32_t rd:5;
101 uint32_t op2:3;
102 uint32_t imm22:22;
103 } format2_t;
104 #elif defined(_BIT_FIELDS_LTOH)
105 typedef struct format2 {
106 uint32_t imm22:22;
107 uint32_t op2:3;
108 uint32_t rd:5;
109 uint32_t op:2;
110 } format2_t;
111 #else
112 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
113 #endif
115 #if defined(_BIT_FIELDS_HTOL)
116 typedef struct format2a {
117 uint32_t op:2;
118 uint32_t a:1;
119 uint32_t cond:4;
120 uint32_t op2:3;
121 uint32_t disp22:22;
122 } format2a_t;
123 #elif defined(_BIT_FIELDS_LTOH)
124 typedef struct format2a {
125 uint32_t disp22:22;
126 uint32_t op2:3;
127 uint32_t cond:4;
128 uint32_t a:1;
129 uint32_t op:2;
130 } format2a_t;
131 #else
132 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
133 #endif
135 #if defined(_BIT_FIELDS_HTOL)
136 typedef struct format2b {
137 uint32_t op:2;
138 uint32_t a:1;
139 uint32_t cond:4;
140 uint32_t op2:3;
141 uint32_t cc:2;
142 uint32_t p:1;
143 uint32_t disp19:19;
144 } format2b_t;
145 #elif defined(_BIT_FIELDS_LTOH)
146 typedef struct format2b {
147 uint32_t disp19:19;
148 uint32_t p:1;
149 uint32_t cc:2;
150 uint32_t op2:3;
151 uint32_t cond:4;
152 uint32_t a:1;
153 uint32_t op:2;
154 } format2b_t;
155 #else
156 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
157 #endif
159 #if defined(_BIT_FIELDS_HTOL)
160 typedef struct format2c {
161 uint32_t op:2;
162 uint32_t a:1;
163 uint32_t cond:4;
164 uint32_t op2:3;
165 uint32_t d16hi:2;
166 uint32_t p:1;
167 uint32_t rs1:5;
168 uint32_t d16lo:14;
169 } format2c_t;
170 #elif defined(_BIT_FIELDS_LTOH)
171 typedef struct format2c {
172 uint32_t d16lo:14;
173 uint32_t rs1:5;
174 uint32_t p:1;
175 uint32_t d16hi:2;
176 uint32_t op2:3;
177 uint32_t cond:4;
178 uint32_t a:1;
179 uint32_t op:2;
180 } format2c_t;
181 #else
182 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
183 #endif
185 #if defined(_BIT_FIELDS_HTOL)
186 typedef struct format3 {
187 uint32_t op:2;
188 uint32_t rd:5;
189 uint32_t op3:6;
190 uint32_t rs1:5;
191 uint32_t i:1;
192 uint32_t asi:8;
193 uint32_t rs2:5;
194 } format3_t;
195 #elif defined(_BIT_FIELDS_LTOH)
196 typedef struct format3 {
197 uint32_t rs2:5;
198 uint32_t asi:8;
199 uint32_t i:1;
200 uint32_t rs1:5;
201 uint32_t op3:6;
202 uint32_t rd:5;
203 uint32_t op:2;
204 } format3_t;
205 #else
206 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
207 #endif
209 #if defined(_BIT_FIELDS_HTOL)
210 typedef struct format3a {
211 uint32_t op:2;
212 uint32_t rd:5;
213 uint32_t op3:6;
214 uint32_t rs1:5;
215 uint32_t i:1;
216 uint32_t simm13:13;
217 } format3a_t;
218 #elif defined(_BIT_FIELDS_LTOH)
219 typedef struct format3a {
220 uint32_t simm13:13;
221 uint32_t i:1;
222 uint32_t rs1:5;
223 uint32_t op3:6;
224 uint32_t rd:5;
225 uint32_t op:2;
226 } format3a_t;
227 #else
228 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
229 #endif
231 #if defined(_BIT_FIELDS_HTOL)
232 typedef struct format3b {
233 uint32_t op:2;
234 uint32_t rd:5;
235 uint32_t op3:6;
236 uint32_t rs1:5;
237 uint32_t i:1;
238 uint32_t x:1;
239 uint32_t undef:6;
240 uint32_t shcnt:6;
241 } format3b_t;
242 #elif defined(_BIT_FIELDS_LTOH)
243 typedef struct format3b {
244 uint32_t shcnt:6;
245 uint32_t undef:6;
246 uint32_t x:1;
247 uint32_t i:1;
248 uint32_t rs1:5;
249 uint32_t op3:6;
250 uint32_t rd:5;
251 uint32_t op:2;
252 } format3b_t;
253 #else
254 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
255 #endif
257 #if defined(_BIT_FIELDS_HTOL)
258 typedef struct format3c {
259 uint32_t op:2;
260 uint32_t rd:5;
261 uint32_t op3:6;
262 uint32_t cc2:1;
263 uint32_t cond:4;
264 uint32_t i:1;
265 uint32_t cc:2;
266 uint32_t simm11:11;
267 } format3c_t;
268 #elif defined(_BIT_FIELDS_LTOH)
269 typedef struct format3c {
270 uint32_t simm11:11;
271 uint32_t cc:2;
272 uint32_t i:1;
273 uint32_t cond:4;
274 uint32_t cc2:1;
275 uint32_t op3:6;
276 uint32_t rd:5;
277 uint32_t op:2;
278 } format3c_t;
279 #else
280 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
281 #endif
283 #if defined(_BIT_FIELDS_HTOL)
284 typedef struct format3d {
285 uint32_t op:2;
286 uint32_t rd:5;
287 uint32_t op3:6;
288 uint32_t rs1:5;
289 uint32_t i:1;
290 uint32_t rcond:3;
291 uint32_t simm10:10;
292 } format3d_t;
293 #elif defined(_BIT_FIELDS_LTOH)
294 typedef struct format3d {
295 uint32_t simm10:10;
296 uint32_t rcond:3;
297 uint32_t i:1;
298 uint32_t rs1:5;
299 uint32_t op3:6;
300 uint32_t rd:5;
301 uint32_t op:2;
302 } format3d_t;
303 #else
304 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
305 #endif
307 #if defined(_BIT_FIELDS_HTOL)
308 typedef struct formatcp {
309 uint32_t op:2;
310 uint32_t rd:5;
311 uint32_t op3:6;
312 uint32_t rs1:5;
313 uint32_t opc:9;
314 uint32_t rs2:5;
315 } formatcp_t;
316 #elif defined(_BIT_FIELDS_LTOH)
317 typedef struct formatcp {
318 uint32_t rs2:5;
319 uint32_t opc:9;
320 uint32_t rs1:5;
321 uint32_t op3:6;
322 uint32_t rd:5;
323 uint32_t op:2;
324 } formatcp_t;
325 #else
326 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
327 #endif
329 #if defined(_BIT_FIELDS_HTOL)
330 typedef struct formattcc {
331 uint32_t op:2;
332 uint32_t undef:1;
333 uint32_t cond:4;
334 uint32_t op3:6;
335 uint32_t rs1:5;
336 uint32_t i:1;
337 uint32_t cc:2;
338 uint32_t undef2:3;
339 uint32_t immtrap:8;
340 } formattcc_t;
341 #elif defined(_BIT_FIELDS_LTOH)
342 typedef struct formattcc {
343 uint32_t immtrap:8;
344 uint32_t undef2:3;
345 uint32_t cc:2;
346 uint32_t i:1;
347 uint32_t rs1:5;
348 uint32_t op3:6;
349 uint32_t cond:4;
350 uint32_t undef:1;
351 uint32_t op:2;
352 } formattcc_t;
353 #else
354 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
355 #endif
357 #if defined(_BIT_FIELDS_HTOL)
358 typedef struct formattcc2 {
359 uint32_t op:2;
360 uint32_t undef:1;
361 uint32_t cond:4;
362 uint32_t op3:6;
363 uint32_t rs1:5;
364 uint32_t i:1;
365 uint32_t cc:2;
366 uint32_t undef2:6;
367 uint32_t rs2:5;
368 } formattcc2_t;
369 #elif defined(_BIT_FIELDS_LTOH)
370 typedef struct formattcc2 {
371 uint32_t rs2:5;
372 uint32_t undef2:6;
373 uint32_t cc:2;
374 uint32_t i:1;
375 uint32_t rs1:5;
376 uint32_t op3:6;
377 uint32_t cond:4;
378 uint32_t undef:1;
379 uint32_t op:2;
380 } formattcc2_t;
381 #else
382 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
383 #endif
385 #if defined(_BIT_FIELDS_HTOL)
386 typedef struct formatmbr {
387 uint32_t op:2;
388 uint32_t rd:5;
389 uint32_t op3:6;
390 uint32_t rs1:5;
391 uint32_t i:1;
392 uint32_t undef:6;
393 uint32_t cmask:3;
394 uint32_t mmask:4;
395 } formatmbr_t;
396 #elif defined(_BIT_FIELDS_LTOH)
397 typedef struct formatmbr {
398 uint32_t mmask:4;
399 uint32_t cmask:3;
400 uint32_t undef:6;
401 uint32_t i:1;
402 uint32_t rs1:5;
403 uint32_t op3:6;
404 uint32_t rd:5;
405 uint32_t op:2;
406 } formatmbr_t;
407 #else
408 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
409 #endif
411 #if defined(_BIT_FIELDS_HTOL)
412 typedef struct formatfcmp {
413 uint32_t op:2;
414 uint32_t undef:3;
415 uint32_t cc:2;
416 uint32_t op3:6;
417 uint32_t rs1:5;
418 uint32_t opf:9;
419 uint32_t rs2:5;
420 } formatfcmp_t;
421 #elif defined(_BIT_FIELDS_LTOH)
422 typedef struct formatfcmp {
423 uint32_t rs2:5;
424 uint32_t opf:9;
425 uint32_t rs1:5;
426 uint32_t op3:6;
427 uint32_t cc:2;
428 uint32_t undef:3;
429 uint32_t op:2;
430 } formatfcmp_t;
431 #else
432 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
433 #endif
435 #if defined(_BIT_FIELDS_HTOL)
436 typedef struct formatfmov {
437 uint32_t op:2;
438 uint32_t rd:5;
439 uint32_t op3:6;
440 uint32_t undef:1;
441 uint32_t cond:4;
442 uint32_t cc:3;
443 uint32_t opf:6;
444 uint32_t rs2:5;
445 } formatfmov_t;
446 #elif defined(_BIT_FIELDS_LTOH)
447 typedef struct formatfmov {
448 uint32_t rs2:5;
449 uint32_t opf:6;
450 uint32_t cc:3;
451 uint32_t cond:4;
452 uint32_t undef:1;
453 uint32_t op3:6;
454 uint32_t rd:5;
455 uint32_t op:2;
456 } formatfmov_t;
457 #else
458 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
459 #endif
461 #if defined(_BIT_FIELDS_HTOL)
462 typedef struct formatfused {
463 uint32_t op:2;
464 uint32_t rd:5;
465 uint32_t op3:6;
466 uint32_t rs1:5;
467 uint32_t rs3:5;
468 uint32_t op5:4;
469 uint32_t rs2:5;
470 } formatfused_t;
471 #elif defined(_BIT_FIELDS_LTOH)
472 typedef struct formatfused {
473 uint32_t rs2:5;
474 uint32_t op5:4;
475 uint32_t rs3:5;
476 uint32_t rs1:5;
477 uint32_t op3:6;
478 uint32_t rd:5;
479 uint32_t op:2;
480 } formatfused_t;
481 #else
482 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
483 #endif
485 typedef union ifmt {
486 uint32_t i;
487 format1_t f1;
488 format2_t f2;
489 format2a_t f2a;
490 format2b_t f2b;
491 format2c_t f2c;
492 format3_t f3;
493 format3a_t f3a;
494 format3b_t f3b;
495 format3c_t f3c;
496 format3d_t f3d;
497 formatcp_t fcp;
498 formattcc_t ftcc;
499 formattcc2_t ftcc2;
500 formatfcmp_t fcmp;
501 formatmbr_t fmb;
502 formatfmov_t fmv;
503 formatfused_t fused;
504 } ifmt_t;
506 /* integer register names */
507 static const char *reg_names[32] = {
508 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
509 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
510 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
511 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7"
514 /* floating point register names */
515 static const char *freg_names[32] = {
516 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
517 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
518 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
519 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"
522 /* double precision register names */
523 static const char *fdreg_names[32] = {
524 "%d0", "%d32", "%d2", "%d34", "%d4", "%d36", "%d6", "%d38",
525 "%d8", "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46",
526 "%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54",
527 "%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62"
530 static const char *compat_fdreg_names[32] = {
531 "%f0", "%f32", "%f2", "%f34", "%f4", "%f36", "%f6", "%f38",
532 "%f8", "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46",
533 "%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54",
534 "%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62"
538 static const char *fqreg_names[32] = {
539 "%q0", "%q32", "%f2", "%f3", "%f4", "%q4", "%q36", "%f6",
540 "%f7", "%q8", "%q40", "%f10", "%f11", "%q12", "%q44", "%f14",
541 "%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22",
542 "%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30",
546 /* coprocessor register names -- sparcv8 only */
547 static const char *cpreg_names[32] = {
548 "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
549 "%c8", "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
550 "%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23",
551 "%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31",
554 /* floating point condition code names */
555 static const char *fcc_names[4] = {
556 "%fcc0", "%fcc1", "%fcc2", "%fcc3"
559 /* condition code names */
560 static const char *icc_names[4] = {
561 "%icc", NULL, "%xcc", NULL
564 /* bitmask values for membar */
565 static const char *membar_mmask[4] = {
566 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore"
569 static const char *membar_cmask[3] = {
570 "#Lookaside", "#MemIssue", "#Sync"
573 /* v8 ancillary state register names */
574 static const char *asr_names[32] = {
575 "%y", "%asr1", "%asr2", "%asr3",
576 "%asr4", "%asr5", "%asr6", "%asr7",
577 "%asr8", "%asr9", "%asr10", "%asr11",
578 "%asr12", "%asr13", "%asr14", "%asr15",
579 NULL, NULL, NULL, NULL,
580 NULL, NULL, NULL, NULL,
581 NULL, NULL, NULL, NULL,
582 NULL, NULL, NULL, NULL
584 static const uint32_t asr_rdmask = 0x0000ffffL;
585 static const uint32_t asr_wrmask = 0x0000ffffL;
587 static const char *v9_asr_names[32] = {
588 "%y", NULL, "%ccr", "%asi",
589 "%tick", "%pc", "%fprs", NULL,
590 NULL, NULL, NULL, NULL,
591 NULL, NULL, NULL, NULL,
592 "%pcr", "%pic", "%dcr", "%gsr",
593 "%softint_set", "%softint_clr", "%softint", "%tick_cmpr",
594 "%stick", "%stick_cmpr", NULL, NULL,
595 NULL, NULL, NULL, NULL
598 * on v9, only certain registers are valid for read or writing
599 * these are bitmasks corresponding to which registers are valid in which
600 * case. Any access to %dcr is illegal.
602 static const uint32_t v9_asr_rdmask = 0x03cb007d;
603 static const uint32_t v9_asr_wrmask = 0x03fb004d;
605 /* privledged register names on v9 */
606 /* TODO: compat - NULL to %priv_nn */
607 static const char *v9_privreg_names[32] = {
608 "%tpc", "%tnpc", "%tstate", "%tt",
609 "%tick", "%tba", "%pstate", "%tl",
610 "%pil", "%cwp", "%cansave", "%canrestore",
611 "%cleanwin", "%otherwin", "%wstate", "%fq",
612 "%gl", NULL, NULL, NULL,
613 NULL, NULL, NULL, NULL,
614 NULL, NULL, NULL, NULL,
615 NULL, NULL, NULL, "%ver"
618 /* hyper privileged register names on v9 */
619 static const char *v9_hprivreg_names[32] = {
620 "%hpstate", "%htstate", NULL, "%hintp",
621 NULL, "%htba", "%hver", NULL,
622 NULL, NULL, NULL, NULL,
623 NULL, NULL, NULL, NULL,
624 NULL, NULL, NULL, NULL,
625 NULL, NULL, NULL, NULL,
626 NULL, NULL, NULL, NULL,
627 NULL, NULL, NULL, "%hstick_cmpr"
630 static const uint32_t v9_pr_rdmask = 0x80017fff;
631 static const uint32_t v9_pr_wrmask = 0x00017fff;
632 static const uint32_t v9_hpr_rdmask = 0x8000006b;
633 static const uint32_t v9_hpr_wrmask = 0x8000006b;
635 static const char *prefetch_str[32] = {
636 "#n_reads", "#one_read",
637 "#n_writes", "#one_write",
638 "#page", NULL, NULL, NULL,
639 NULL, NULL, NULL, NULL,
640 NULL, NULL, NULL, NULL,
641 NULL, "#unified", NULL, NULL,
642 "#n_reads_strong", "#one_read_strong",
643 "#n_writes_strong", "#one_write_strong",
644 NULL, NULL, NULL, NULL,
645 NULL, NULL, NULL, NULL
648 static void prt_field(const char *, uint32_t, int);
650 static const char *get_regname(dis_handle_t *, int, uint32_t);
651 static int32_t sign_extend(int32_t, uint32_t);
653 static void prt_name(dis_handle_t *, const char *, int);
655 #define IMM_SIGNED 0x01 /* Is immediate value signed */
656 #define IMM_ADDR 0x02 /* Is immediate value part of an address */
657 static void prt_imm(dis_handle_t *, uint32_t, int);
659 static void prt_asi(dis_handle_t *, uint32_t);
660 static const char *get_asi_name(uint8_t);
661 static void prt_address(dis_handle_t *, uint32_t, int);
662 static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t);
663 static void bprintf(dis_handle_t *, const char *, ...);
666 * print out val (which is 'bitlen' bits long) in binary
668 #if defined(DIS_STANDALONE)
669 /* ARGSUSED */
670 void
671 prt_binary(uint32_t val, int bitlen)
676 #else
678 void
679 prt_binary(uint32_t val, int bitlen)
681 int i;
683 for (i = bitlen - 1; i >= 0; --i) {
684 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
686 if (i % 4 == 0 && i != 0)
687 (void) fprintf(stderr, " ");
690 #endif /* DIS_STANDALONE */
694 * print out a call instruction
695 * format: call address <name>
697 /* ARGSUSED1 */
699 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
701 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
702 ifmt_t *f = (ifmt_t *)&instr;
704 int32_t disp;
705 size_t curlen;
707 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
709 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
710 prt_field("op", f->f1.op, 2);
711 prt_field("disp30", f->f1.disp30, 30);
714 disp = sign_extend(f->f1.disp30, 30) * 4;
716 prt_name(dhp, inp->in_data.in_def.in_name, 1);
718 bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
719 (disp < 0) ? "-" : "+",
720 (disp < 0) ? (-disp) : disp);
722 (void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen);
724 curlen = strlen(dhx->dhx_buf);
725 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
726 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL,
727 NULL);
728 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
731 return (0);
735 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
737 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
738 ifmt_t *f = (ifmt_t *)&instr;
740 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
741 prt_field("op", f->f2.op, 2);
742 prt_field("op2", f->f2.op2, 3);
743 prt_field("rd", f->f2.rd, 5);
744 prt_field("imm22", f->f2.imm22, 22);
747 if (idx == 0) {
748 /* unimp / illtrap */
749 prt_name(dhp, inp->in_data.in_def.in_name, 1);
750 prt_imm(dhp, f->f2.imm22, 0);
751 return (0);
754 if (f->f2.imm22 == 0 && f->f2.rd == 0) {
755 prt_name(dhp, "nop", 0);
756 return (0);
759 /* ?? Should we return -1 if rd == 0 && disp != 0 */
761 prt_name(dhp, inp->in_data.in_def.in_name, 1);
763 bprintf(dhp,
764 ((dhp->dh_flags & DIS_OCTAL) != 0) ?
765 "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
766 f->f2.imm22 << 10,
767 reg_names[f->f2.rd]);
769 return (0);
772 /* ARGSUSED3 */
774 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
776 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
777 const char *name = inp->in_data.in_def.in_name;
778 const char *r = NULL;
779 const char *annul = "";
780 const char *pred = "";
782 char buf[15];
784 ifmt_t *f = (ifmt_t *)&instr;
786 size_t curlen;
787 int32_t disp;
788 uint32_t flags = inp->in_data.in_def.in_flags;
789 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
791 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
792 prt_field("op", f->f2.op, 2);
793 prt_field("op2", f->f2.op2, 3);
795 switch (FLG_DISP_VAL(flags)) {
796 case DISP22:
797 prt_field("cond", f->f2a.cond, 4);
798 prt_field("a", f->f2a.a, 1);
799 prt_field("disp22", f->f2a.disp22, 22);
800 break;
802 case DISP19:
803 prt_field("cond", f->f2a.cond, 4);
804 prt_field("a", f->f2a.a, 1);
805 prt_field("p", f->f2b.p, 1);
806 prt_field("cc", f->f2b.cc, 2);
807 prt_field("disp19", f->f2b.disp19, 19);
808 break;
810 case DISP16:
811 prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
812 prt_field("rcond", f->f2c.cond, 3);
813 prt_field("p", f->f2c.p, 1);
814 prt_field("rs1", f->f2c.rs1, 5);
815 prt_field("d16hi", f->f2c.d16hi, 2);
816 prt_field("d16lo", f->f2c.d16lo, 14);
817 break;
821 if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
822 f->f2b.cc == 0x02 && ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0)) {
823 name = "iprefetch";
824 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
828 switch (FLG_DISP_VAL(flags)) {
829 case DISP22:
830 disp = sign_extend(f->f2a.disp22, 22);
831 break;
833 case DISP19:
834 disp = sign_extend(f->f2b.disp19, 19);
835 break;
837 case DISP16:
838 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
839 break;
843 disp *= 4;
845 if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
846 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
847 else
848 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
850 if (r == NULL)
851 return (-1);
853 if (f->f2a.a == 1)
854 annul = ",a";
856 if ((flags & FLG_PRED) != 0) {
857 if (f->f2b.p == 0) {
858 pred = ",pn";
859 } else {
860 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
861 pred = ",pt";
865 (void) dis_snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
866 prt_name(dhp, buf, 1);
869 switch (FLG_DISP_VAL(flags)) {
870 case DISP22:
871 bprintf(dhp,
872 (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
873 (disp < 0) ? "-" : "+",
874 (disp < 0) ? (-disp) : disp);
875 break;
877 case DISP19:
878 bprintf(dhp,
879 (octal != 0) ? "%s, %s0%-5lo <" :
880 "%s, %s0x%-04lx <", r,
881 (disp < 0) ? "-" : "+",
882 (disp < 0) ? (-disp) : disp);
883 break;
885 case DISP16:
886 bprintf(dhp,
887 (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
889 (disp < 0) ? "-" : "+",
890 (disp < 0) ? (-disp) : disp);
891 break;
894 curlen = strlen(dhx->dhx_buf);
895 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
896 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, NULL);
898 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
900 return (0);
906 * print out the compare and swap instructions (casa/casxa)
907 * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
908 * casa/casxa [%rs1] %asi, %rs2, %rd
910 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
911 * when an immediate ASI value is given as follows:
913 * casa [%rs1]#ASI_P, %rs2, %rd -> cas [%rs1], %rs2, %rd
914 * casa [%rs1]#ASI_P_L, %rs2, %rd -> casl [%rs1], %rs2, %rd
915 * casxa [%rs1]#ASI_P, %rs2, %rd -> casx [%rs1], %rs2, %rd
916 * casxa [%rs1]#ASI_P_L, %rs2, %rd -> casxl [%rs1], %rs2, %rd
918 static int
919 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
921 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
922 ifmt_t *f = (ifmt_t *)&instr;
923 const char *asistr = NULL;
924 int noasi = 0;
926 asistr = get_asi_name(f->f3.asi);
928 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
929 if (f->f3.op3 == 0x3c && f->f3.i == 0) {
930 if (f->f3.asi == 0x80) {
931 noasi = 1;
932 name = "cas";
935 if (f->f3.asi == 0x88) {
936 noasi = 1;
937 name = "casl";
941 if (f->f3.op3 == 0x3e && f->f3.i == 0) {
942 if (f->f3.asi == 0x80) {
943 noasi = 1;
944 name = "casx";
947 if (f->f3.asi == 0x88) {
948 noasi = 1;
949 name = "casxl";
954 prt_name(dhp, name, 1);
956 bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
958 if (noasi == 0) {
959 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
960 prt_asi(dhp, instr);
963 bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
965 if (noasi == 0 && asistr != NULL)
966 bprintf(dhp, "\t<%s>", asistr);
968 return (0);
972 * format a load/store instruction
973 * format: ldXX [%rs1 + %rs2], %rd load, i==0
974 * ldXX [%rs1 +/- nn], %rd load, i==1
975 * ldXX [%rs1 + %rs2] #XX, %rd load w/ imm_asi, i==0
976 * ldXX [%rs1 +/- nn] %asi, %rd load from asi[%asi], i==1
978 * stXX %rd, [%rs1 + %rs2] store, i==0
979 * stXX %rd, [%rs1 +/- nn] store, i==1
980 * stXX %rd, [%rs1 + %rs1] #XX store to imm_asi, i==0
981 * stXX %rd, [%rs1 +/-nn] %asi store to asi[%asi], i==1
983 * The register sets used for %rd are set in the instructions flags field
984 * The asi variants are used if FLG_ASI is set in the instructions flags field
986 * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set,
987 * When %rs1, %rs2 or nn are 0, they are not printed, i.e.
988 * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example
990 * The following synthetic instructions are also implemented:
992 * stb %g0, [addr] -> clrb [addr] DIS_DEBUG_SYNTH_ALL
993 * sth %g0, [addr] -> crlh [addr] DIS_DEBUG_SYNTH_ALL
994 * stw %g0, [addr] -> clr [addr] DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT
995 * stx %g0, [addr] -> clrx [addr] DIS_DEBUG_SYNTH_ALL
997 * If DIS_DEBUG_COMPAT is set, the following substitutions also take place
998 * lduw -> ld
999 * ldtw -> ld
1000 * stuw -> st
1001 * sttw -> st
1004 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1006 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1007 ifmt_t *f = (ifmt_t *)&instr;
1008 const char *regstr = NULL;
1009 const char *asistr = NULL;
1011 const char *iname = inp->in_data.in_def.in_name;
1012 uint32_t flags = inp->in_data.in_def.in_flags;
1014 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1015 prt_field("op", f->f3.op, 2);
1016 prt_field("op3", f->f3.op3, 6);
1017 prt_field("rs1", f->f3.rs1, 5);
1018 prt_field("i", f->f3.i, 1);
1019 if (f->f3.i != 0) {
1020 prt_field("simm13", f->f3a.simm13, 13);
1021 } else {
1022 if ((flags & FLG_ASI) != 0)
1023 prt_field("imm_asi", f->f3.asi, 8);
1024 prt_field("rs2", f->f3.rs2, 5);
1026 prt_field("rd", f->f3.rd, 5);
1029 if (idx == 0x2d || idx == 0x3d) {
1030 /* prefetch / prefetcha */
1032 prt_name(dhp, iname, 1);
1034 prt_address(dhp, instr, 0);
1036 if (idx == 0x3d) {
1037 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1038 prt_asi(dhp, instr);
1041 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1043 /* fcn field is the same as rd */
1044 if (prefetch_str[f->f3.rd] != NULL)
1045 (void) strlcat(dhx->dhx_buf, prefetch_str[f->f3.rd],
1046 dhx->dhx_buflen);
1047 else
1048 prt_imm(dhp, f->f3.rd, 0);
1050 if (idx == 0x3d && f->f3.i == 0) {
1051 asistr = get_asi_name(f->f3.asi);
1052 if (asistr != NULL)
1053 bprintf(dhp, "\t<%s>", asistr);
1056 return (0);
1059 /* casa / casxa */
1060 if (idx == 0x3c || idx == 0x3e)
1061 return (fmt_cas(dhp, instr, iname));
1063 /* synthetic instructions & special cases */
1064 switch (idx) {
1065 case 0x00:
1066 /* ld */
1067 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1068 iname = "lduw";
1069 break;
1071 case 0x03:
1072 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1073 iname = "ldtw";
1074 break;
1076 case 0x04:
1077 /* stw */
1078 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1079 iname = "stuw";
1081 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1082 == 0)
1083 break;
1085 if (f->f3.rd == 0) {
1086 iname = "clr";
1087 flags = FLG_RD(REG_NONE);
1089 break;
1091 case 0x05:
1092 /* stb */
1093 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1094 == 0)
1095 break;
1097 if (f->f3.rd == 0) {
1098 iname = "clrb";
1099 flags = FLG_RD(REG_NONE);
1101 break;
1103 case 0x06:
1104 /* sth */
1105 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1106 == 0)
1107 break;
1109 if (f->f3.rd == 0) {
1110 iname = "clrh";
1111 flags = FLG_RD(REG_NONE);
1113 break;
1115 case 0x07:
1116 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1117 iname = "sttw";
1118 break;
1120 case 0x0e:
1121 /* stx */
1123 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1124 == 0)
1125 break;
1127 if (f->f3.rd == 0) {
1128 iname = "clrx";
1129 flags = FLG_RD(REG_NONE);
1131 break;
1133 case 0x13:
1134 /* ldtwa */
1135 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1136 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1137 iname = "ldtwa";
1138 break;
1140 case 0x17:
1141 /* sttwa */
1142 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1143 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1144 iname = "sttwa";
1145 break;
1147 case 0x21:
1148 case 0x25:
1150 * on sparcv8 it merely says that rd != 1 should generate an
1151 * exception, on v9, it is illegal
1153 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1154 break;
1156 iname = (idx == 0x21) ? "ldx" : "stx";
1158 if (f->f3.rd > 1)
1159 return (-1);
1161 break;
1163 case 0x31:
1164 /* stda */
1165 switch (f->f3.asi) {
1166 case 0xc0:
1167 case 0xc1:
1168 case 0xc8:
1169 case 0xc9:
1170 case 0xc2:
1171 case 0xc3:
1172 case 0xca:
1173 case 0xcb:
1174 case 0xc4:
1175 case 0xc5:
1176 case 0xcc:
1177 case 0xcd:
1179 * store partial floating point, only valid w/
1180 * vis
1182 * Somewhat confusingly, it uses the same op
1183 * code as 'stda' -- store double to alternate
1184 * space. It is distinguised by specific
1185 * imm_asi values (as seen above), and
1186 * has a slightly different output syntax
1189 if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0)
1190 break;
1191 if (f->f3.i != 0)
1192 break;
1193 prt_name(dhp, iname, 1);
1194 bprintf(dhp, "%s, %s, [%s] ",
1195 get_regname(dhp, REG_FPD, f->f3.rd),
1196 get_regname(dhp, REG_FPD, f->f3.rs2),
1197 get_regname(dhp, REG_FPD, f->f3.rs1));
1198 prt_asi(dhp, instr);
1199 asistr = get_asi_name(f->f3.asi);
1200 if (asistr != NULL)
1201 bprintf(dhp, "\t<%s>", asistr);
1203 return (0);
1205 default:
1206 break;
1211 regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1213 if (f->f3.i == 0)
1214 asistr = get_asi_name(f->f3.asi);
1216 prt_name(dhp, iname, 1);
1218 if ((flags & FLG_STORE) != 0) {
1219 if (regstr[0] != '\0') {
1220 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1221 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1224 prt_address(dhp, instr, 0);
1225 if ((flags & FLG_ASI) != 0) {
1226 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1227 prt_asi(dhp, instr);
1229 } else {
1230 prt_address(dhp, instr, 0);
1231 if ((flags & FLG_ASI) != 0) {
1232 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1233 prt_asi(dhp, instr);
1236 if (regstr[0] != '\0') {
1237 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1238 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1242 if ((flags & FLG_ASI) != 0 && asistr != NULL)
1243 bprintf(dhp, "\t<%s>", asistr);
1245 return (0);
1248 static int
1249 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1251 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1252 ifmt_t *f = (ifmt_t *)&instr;
1253 int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1255 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1256 prt_field("op", f->fcp.op, 2);
1257 prt_field("op3", f->fcp.op3, 6);
1258 prt_field("opc", f->fcp.opc, 9);
1259 prt_field("rs1", f->fcp.rs1, 5);
1260 prt_field("rs2", f->fcp.rs2, 5);
1261 prt_field("rd", f->fcp.rd, 5);
1264 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1265 prt_imm(dhp, f->fcp.opc, 0);
1267 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1268 (void) prt_aluargs(dhp, instr, flags);
1270 return (0);
1273 static int
1274 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1276 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1277 const char *psr_str = "%psr";
1278 const char *wim_str = "%wim";
1279 const char *tbr_str = "%tbr";
1281 const char *name = inp->in_data.in_def.in_name;
1282 const char *regstr = NULL;
1284 ifmt_t *f = (ifmt_t *)&instr;
1286 int rd = (idx < 0x30);
1287 int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1288 int ridx = f->f3.rs1;
1289 int i, first;
1290 int pr_rs1 = 1;
1291 int pr_rs2 = 1;
1293 int use_mask = 1;
1294 uint32_t mask;
1296 if (rd == 0)
1297 ridx = f->f3.rd;
1299 switch (idx) {
1300 case 0x28:
1301 /* rd */
1303 /* stbar */
1304 if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) {
1305 prt_name(dhp, "stbar", 0);
1306 return (0);
1309 /* membar */
1310 if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) &&
1311 (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) {
1313 prt_name(dhp, "membar",
1314 ((f->fmb.cmask != 0) || (f->fmb.mmask != 0)));
1316 first = 0;
1318 for (i = 0; i < 4; ++i) {
1319 if ((f->fmb.cmask & (1L << i)) != 0) {
1320 bprintf(dhp, "%s%s",
1321 (first != 0) ? "|" : "",
1322 membar_cmask[i]);
1323 first = 1;
1327 for (i = 0; i < 5; ++i) {
1328 if ((f->fmb.mmask & (1L << i)) != 0) {
1329 bprintf(dhp, "%s%s",
1330 (first != 0) ? "|" : "",
1331 membar_mmask[i]);
1332 first = 1;
1336 return (0);
1339 if (v9 != 0) {
1340 regstr = v9_asr_names[ridx];
1341 mask = v9_asr_rdmask;
1342 } else {
1343 regstr = asr_names[ridx];
1344 mask = asr_rdmask;
1346 break;
1348 case 0x29:
1349 if (v9 != 0) {
1350 regstr = v9_hprivreg_names[ridx];
1351 mask = v9_hpr_rdmask;
1352 } else {
1353 regstr = psr_str;
1354 use_mask = 0;
1356 break;
1358 case 0x2a:
1359 if (v9 != 0) {
1360 regstr = v9_privreg_names[ridx];
1361 mask = v9_pr_rdmask;
1362 } else {
1363 regstr = wim_str;
1364 use_mask = 0;
1366 break;
1368 case 0x2b:
1369 if (v9 != 0) {
1370 /* flushw */
1371 prt_name(dhp, name, 0);
1372 return (0);
1375 regstr = tbr_str;
1376 use_mask = 0;
1377 break;
1379 case 0x30:
1380 if (v9 != 0) {
1381 regstr = v9_asr_names[ridx];
1382 mask = v9_asr_wrmask;
1383 } else {
1384 regstr = asr_names[ridx];
1385 mask = asr_wrmask;
1389 * sir is shoehorned in here, per Ultrasparc 2007
1390 * hyperprivileged edition, section 7.88, all of
1391 * these must be true to distinguish from WRasr
1393 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 &&
1394 f->f3.i == 1) {
1395 prt_name(dhp, "sir", 1);
1396 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1397 IMM_SIGNED);
1398 return (0);
1401 /* synth: mov */
1402 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1403 == 0)
1404 break;
1406 if (v9 == 0) {
1407 if (f->f3.rs1 == 0) {
1408 name = "mov";
1409 pr_rs1 = 0;
1412 if ((f->f3.i == 0 && f->f3.rs2 == 0) ||
1413 (f->f3.i == 1 && f->f3a.simm13 == 0)) {
1414 name = "mov";
1415 pr_rs2 = 0;
1419 if (pr_rs1 == 0)
1420 pr_rs2 = 1;
1422 break;
1424 case 0x31:
1426 * NOTE: due to the presence of an overlay entry for another
1427 * table, this case only happens when doing v8 instructions
1428 * only
1430 regstr = psr_str;
1431 use_mask = 0;
1432 break;
1434 case 0x32:
1435 if (v9 != 0) {
1436 regstr = v9_privreg_names[ridx];
1437 mask = v9_pr_wrmask;
1438 } else {
1439 regstr = wim_str;
1440 use_mask = 0;
1442 break;
1444 case 0x33:
1445 if (v9 != 0) {
1446 regstr = v9_hprivreg_names[ridx];
1447 mask = v9_hpr_wrmask;
1448 } else {
1449 regstr = tbr_str;
1450 use_mask = 0;
1452 break;
1455 if (regstr == NULL)
1456 return (-1);
1458 if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1459 return (-1);
1461 prt_name(dhp, name, 1);
1463 if (rd != 0) {
1464 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1465 } else {
1466 if (pr_rs1 == 1)
1467 bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1469 if (pr_rs2 != 0) {
1470 if (f->f3.i == 1)
1471 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1472 IMM_SIGNED);
1473 else
1474 (void) strlcat(dhx->dhx_buf,
1475 reg_names[f->f3.rs2], dhx->dhx_buflen);
1476 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1479 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1482 return (0);
1485 /* ARGSUSED3 */
1487 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1489 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1490 ifmt_t *f = (ifmt_t *)&instr;
1492 int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1493 int p_rs1, p_t;
1495 if (f->ftcc.undef != 0)
1496 return (-1);
1498 if (icc_names[f->ftcc.cc] == NULL)
1499 return (-1);
1501 if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1502 return (-1);
1504 if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1505 return (-1);
1507 p_rs1 = ((f->ftcc.rs1 != 0) ||
1508 ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1510 if (f->ftcc.i == 0) {
1511 p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1513 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1514 (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1515 (v9 != 0) ? ", " : "",
1516 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1517 (p_rs1 != 0) ? " + " : "",
1518 (p_t != 0) ? reg_names[f->f3.rs2] : "");
1519 } else {
1520 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name,
1521 (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1522 (v9 != 0) ? ", " : "",
1523 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1524 (p_rs1 != 0) ? " + " : "",
1525 f->ftcc.immtrap);
1527 return (0);
1530 static int
1531 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1533 char name[5];
1534 uint32_t cnt;
1536 ifmt_t *f = (ifmt_t *)&instr;
1537 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
1539 name[0] = '\0';
1540 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
1542 if (f->f3b.i == 1)
1543 cnt = f->f3.rs2;
1545 if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) {
1546 cnt = f->f3b.shcnt;
1547 (void) strlcat(name, "x", sizeof (name));
1550 prt_name(dhp, name, 1);
1552 if (f->f3b.i == 1)
1553 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1554 reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1555 else
1556 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1557 reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1559 return (0);
1562 /* ARGSUSED3 */
1563 static int
1564 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1566 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1567 const char *name = inp->in_data.in_def.in_name;
1568 ifmt_t *f = (ifmt_t *)&instr;
1570 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1571 name = "call";
1573 if (f->f3.rd == 0) {
1574 if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1575 if (f->f3.rs1 == 15) {
1576 prt_name(dhp, "retl", 0);
1577 return (0);
1580 if (f->f3.rs1 == 31) {
1581 prt_name(dhp, "ret", 0);
1582 return (0);
1586 name = "jmp";
1589 prt_name(dhp, name, 1);
1590 prt_address(dhp, instr, 1);
1592 if (f->f3.rd == 0)
1593 return (0);
1595 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1596 return (0);
1598 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1600 return (0);
1604 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1606 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1607 ifmt_t *f = (ifmt_t *)&instr;
1609 const char *name = inp->in_data.in_def.in_name;
1610 int flags = inp->in_data.in_def.in_flags;
1611 int arg = 0;
1613 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1614 prt_field("op", f->f3.op, 2);
1615 prt_field("op3", f->f3.op3, 6);
1616 prt_field("rs1", f->f3.rs1, 5);
1618 switch (idx) {
1619 /* TODO: more formats */
1621 default:
1622 if (f->f3.i == 0)
1623 prt_field("rs2", f->f3.rs2, 5);
1624 else
1625 prt_field("simm13", f->f3a.simm13, 13);
1627 prt_field("rd", f->f3.rd, 5);
1632 switch (idx) {
1633 case 0x00:
1634 /* add */
1636 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1637 break;
1639 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1640 f->f3a.simm13 == 1) {
1641 name = "inc";
1642 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1643 break;
1646 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1647 f->f3a.simm13 != 1) {
1648 name = "inc";
1649 flags = FLG_P1(REG_NONE);
1650 break;
1652 break;
1654 case 0x02:
1655 /* or */
1657 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1658 == 0)
1659 break;
1661 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0) {
1662 if (f->f3.rs1 == f->f3.rd) {
1663 name = "bset";
1664 flags = FLG_P1(REG_NONE);
1665 break;
1669 if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1670 (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1671 (f->f3.rs1 == 0)) {
1672 name = "clr";
1673 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1674 break;
1677 if (f->f3.rs1 == 0) {
1678 name = "mov";
1679 flags = FLG_P1(REG_NONE);
1680 break;
1682 break;
1684 case 0x04:
1685 /* sub */
1687 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1688 == 0)
1689 break;
1691 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1692 name = "neg";
1693 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1694 break;
1697 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1698 name = "neg";
1699 flags = FLG_P1(REG_NONE);
1700 break;
1703 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1704 break;
1706 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1707 f->f3a.simm13 == 1) {
1708 name = "dec";
1709 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1710 break;
1713 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1714 f->f3a.simm13 != 1) {
1715 name = "dec";
1716 flags = FLG_P1(REG_NONE);
1717 break;
1719 break;
1721 case 0x07:
1722 /* xnor */
1724 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1725 == 0)
1726 break;
1729 * xnor -> not when you have:
1730 * xnor %rs1, 0x0 or %g0, %rd
1732 if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1733 (f->f3.i == 1 && f->f3a.simm13 != 0))
1734 break;
1736 name = "not";
1738 if (f->f3.rs1 == f->f3.rd)
1739 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1740 FLG_P3(REG_INT);
1741 else
1742 flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1743 FLG_P3(REG_INT);
1745 break;
1747 case 0x10:
1748 /* addcc */
1750 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1751 break;
1753 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1754 f->f3a.simm13 == 1) {
1755 name = "inccc";
1756 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1757 break;
1760 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1761 f->f3a.simm13 != 1) {
1762 name = "inccc";
1763 flags = FLG_P1(REG_NONE);
1764 break;
1766 break;
1768 case 0x11:
1769 /* andcc */
1771 if (f->f3.rd != 0)
1772 break;
1774 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1775 == 0)
1776 break;
1778 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) &&
1779 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1780 break;
1782 name = "btst";
1783 flags = FLG_P1(REG_NONE);
1784 f->f3.rd = f->f3.rs1;
1785 break;
1787 case 0x12:
1788 /* orcc */
1790 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1791 == 0)
1792 break;
1794 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1795 name = "tst";
1796 flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1797 break;
1800 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1801 name = "tst";
1802 flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1803 break;
1806 break;
1808 case 0x14:
1809 /* subcc */
1811 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1812 == 0)
1813 break;
1815 if (f->f3.rd == 0) {
1816 name = "cmp";
1817 flags = FLG_P3(REG_NONE);
1818 break;
1821 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
1822 break;
1824 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1825 f->f3a.simm13 == 1) {
1826 name = "deccc";
1827 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1828 break;
1831 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1832 f->f3a.simm13 != 1) {
1833 name = "deccc";
1834 flags = FLG_P1(REG_NONE);
1835 break;
1838 break;
1840 case 0x25:
1841 case 0x26:
1842 case 0x27:
1843 return (prt_shift(dhp, instr, inp));
1845 case 0x28:
1846 case 0x29:
1847 case 0x2a:
1848 case 0x2b:
1849 case 0x30:
1850 case 0x31:
1851 case 0x32:
1852 case 0x33:
1853 return (dis_fmt_rdwr(dhp, instr, inp, idx));
1855 case 0x36:
1856 case 0x37:
1857 /* NOTE: overlayed on v9 */
1858 if ((dhp->dh_flags & DIS_SPARC_V8) != 0)
1859 return (fmt_cpop(dhp, instr, inp));
1860 break;
1862 case 0x38:
1863 /* jmpl */
1864 return (prt_jmpl(dhp, instr, inp, idx));
1866 case 0x39:
1867 /* rett / return */
1868 prt_name(dhp, name, 1);
1869 prt_address(dhp, instr, 1);
1870 return (0);
1872 case 0x3b:
1873 /* flush */
1874 prt_name(dhp, name, 1);
1875 prt_address(dhp, instr, 0);
1876 return (0);
1878 case 0x3c:
1879 case 0x3d:
1880 /* save / restore */
1881 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1882 == 0)
1883 break;
1885 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1886 break;
1888 if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0))
1889 break;
1891 prt_name(dhp, name, 0);
1892 return (0);
1895 if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1896 FLG_P3_VAL(flags) != REG_NONE)
1897 arg = 1;
1899 prt_name(dhp, name, (arg != 0));
1900 prt_aluargs(dhp, instr, flags);
1902 return (0);
1905 /* ARGSUSED1 */
1907 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1909 prt_name(dhp, inp->in_data.in_def.in_name, 0);
1910 return (0);
1913 /* ARGSUSED1 */
1915 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1917 ifmt_t *f = (ifmt_t *)&instr;
1918 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1920 if (f->f3.rd == 0xf) {
1921 /* jpriv */
1922 prt_address(dhp, instr, 1);
1925 return (0);
1928 /* ARGSUSED3 */
1930 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1932 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1933 ifmt_t *f = (ifmt_t *)&instr;
1934 const char **regs = NULL;
1936 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1937 prt_field("op", f->f3c.op, 2);
1938 prt_field("op3", f->f3c.op3, 6);
1939 prt_field("cond", f->f3c.cond, 4);
1940 prt_field("cc2", f->f3c.cc2, 1);
1941 prt_field("cc", f->f3c.cc, 2);
1942 prt_field("i", f->f3c.i, 1);
1944 if (f->f3c.i == 0)
1945 prt_field("rs2", f->f3.rs2, 5);
1946 else
1947 prt_field("simm11", f->f3c.simm11, 11);
1949 prt_field("rd", f->f3.rd, 5);
1952 if (f->f3c.cc2 == 0) {
1953 regs = fcc_names;
1954 } else {
1955 regs = icc_names;
1956 if (regs[f->f3c.cc] == NULL)
1957 return (-1);
1960 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1962 bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1964 if (f->f3c.i == 1)
1965 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1966 else
1967 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1968 dhx->dhx_buflen);
1970 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1972 return (0);
1975 /* ARGSUSED3 */
1977 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1979 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1980 ifmt_t *f = (ifmt_t *)&instr;
1982 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1984 bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1986 if (f->f3d.i == 1)
1987 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1988 else
1989 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1990 dhx->dhx_buflen);
1992 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1994 return (0);
1997 /* ARGSUSED3 */
1999 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2001 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2002 ifmt_t *f = (ifmt_t *)&instr;
2003 int flags = inp->in_data.in_def.in_flags;
2005 flags |= FLG_NOIMM;
2007 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2008 prt_field("op", f->f3.op, 2);
2009 prt_field("op3", f->f3.op3, 6);
2010 prt_field("opf", f->fcmp.opf, 9);
2011 prt_field("rs1", f->f3.rs1, 5);
2012 prt_field("rs2", f->f3.rs2, 5);
2013 prt_field("rd", f->f3.rd, 5);
2016 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2017 prt_aluargs(dhp, instr, flags);
2019 return (0);
2023 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2025 static const char *condstr_icc[16] = {
2026 "n", "e", "le", "l", "leu", "lu", "neg", "vs",
2027 "a", "nz", "g", "ge", "gu", "geu", "pos", "vc"
2030 static const char *condstr_fcc[16] = {
2031 "n", "nz", "lg", "ul", "l", "ug", "g", "u",
2032 "a", "e", "ue", "ge", "uge", "le", "ule", "o"
2035 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2036 ifmt_t *f = (ifmt_t *)&instr;
2037 const char *ccstr = "";
2038 char name[15];
2040 int flags = inp->in_data.in_def.in_flags;
2041 int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2042 idx == 0x55 || idx == 0x56 || idx == 0x57);
2043 int is_fmov = (idx & 0x3f);
2044 int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2045 int is_compat = ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0);
2047 int p_cc = 0;
2049 is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2051 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2052 prt_field("op", f->f3.op, 2);
2053 prt_field("op3", f->f3.op3, 6);
2054 prt_field("opf", f->fcmp.opf, 9);
2056 switch (idx & 0x3f) {
2057 case 0x51:
2058 case 0x52:
2059 case 0x53:
2060 case 0x55:
2061 case 0x56:
2062 case 0x57:
2063 prt_field("cc", f->fcmp.cc, 2);
2064 prt_field("rs1", f->f3.rs1, 5);
2065 prt_field("rs2", f->f3.rs2, 5);
2066 break;
2068 case 0x01:
2069 case 0x02:
2070 case 0x03:
2071 prt_field("opf_low", f->fmv.opf, 6);
2072 prt_field("cond", f->fmv.cond, 4);
2073 prt_field("opf_cc", f->fmv.cc, 3);
2074 prt_field("rs2", f->fmv.rs2, 5);
2075 break;
2077 default:
2078 prt_field("rs1", f->f3.rs1, 5);
2079 prt_field("rs2", f->f3.rs2, 5);
2080 prt_field("rd", f->f3.rd, 5);
2084 name[0] = '\0';
2085 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
2087 if (is_fmov != 0) {
2088 (void) strlcat(name,
2089 (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond]
2090 : condstr_icc[f->fmv.cond],
2091 sizeof (name));
2094 prt_name(dhp, name, 1);
2096 if (is_cmp != 0)
2097 ccstr = fcc_names[f->fcmp.cc];
2099 if (is_fmov != 0)
2100 ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3]
2101 : icc_names[f->fmv.cc & 0x3];
2103 if (ccstr == NULL)
2104 return (-1);
2106 p_cc = (is_compat == 0 || is_v9 != 0 ||
2107 (is_cmp != 0 && f->fcmp.cc != 0) ||
2108 (is_fmov != 0 && f->fmv.cc != 0));
2110 if (p_cc != 0)
2111 bprintf(dhp, "%s, ", ccstr);
2113 prt_aluargs(dhp, instr, flags);
2115 return (0);
2119 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2121 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2122 ifmt_t *f = (ifmt_t *)&instr;
2123 int flags = inp->in_data.in_def.in_flags;
2125 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2126 prt_field("op", f->f3.op, 2);
2127 prt_field("op3", f->f3.op3, 6);
2128 prt_field("opf", f->fcmp.opf, 9);
2130 if (idx == 0x081) {
2131 prt_field("mode", instr & 02L, 2);
2132 } else {
2133 prt_field("rs1", f->f3.rs1, 5);
2134 prt_field("rs2", f->f3.rs2, 5);
2135 prt_field("rd", f->f3.rd, 5);
2139 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2141 if (idx == 0x081) {
2142 /* siam */
2143 bprintf(dhp, "%d", instr & 0x7L);
2144 return (0);
2147 prt_aluargs(dhp, instr, flags);
2149 return (0);
2152 /* ARGSUSED3 */
2154 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2156 ifmt_t *f = (ifmt_t *)&instr;
2157 int flags = inp->in_data.in_def.in_flags;
2159 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2160 bprintf(dhp, "%s, %s, %s, %s",
2161 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1),
2162 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2),
2163 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3),
2164 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd));
2166 return (0);
2169 * put name into the output buffer
2170 * if add_space !=0, append a space after it
2172 static void
2173 prt_name(dis_handle_t *dhp, const char *name, int add_space)
2175 bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name);
2179 * For debugging, print out a field of the instruction
2180 * field is the name of the field
2181 * val is the value of the field
2182 * len is the length of the field (in bits)
2184 #if defined(DIS_STANDALONE)
2185 /* ARGSUSED */
2186 static void
2187 prt_field(const char *field, uint32_t val, int len)
2192 #else
2193 static void
2194 prt_field(const char *field, uint32_t val, int len)
2196 (void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val);
2197 prt_binary(val, len);
2198 (void) fprintf(stderr, ")\n");
2200 #endif /* DIS_STANDALONE */
2203 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed
2204 * integer
2206 static int32_t
2207 sign_extend(int32_t val, uint32_t bits)
2209 uint32_t mask;
2211 ASSERT(bits > 0);
2212 mask = 1L << (bits - 1); /* 2**(bits - 1) */
2213 return (-(val & mask) + (val & ~mask));
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]
2225 static void
2226 prt_imm(dis_handle_t *dhp, uint32_t val, int format)
2228 const char *fmtstr = NULL;
2229 int32_t sv = (int32_t)val;
2230 int octal = dhp->dh_flags & DIS_OCTAL;
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";
2240 break;
2242 case IMM_SIGNED:
2243 if (sv < 0) {
2244 sv = -sv;
2245 fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx";
2246 break;
2248 /* fall through */
2250 default:
2251 fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2254 bprintf(dhp, fmtstr, sv);
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
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
2267 static const char *
2268 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2270 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2271 const char *regname = NULL;
2273 switch (regset) {
2274 case REG_INT:
2275 regname = reg_names[idx];
2276 break;
2278 case REG_FP:
2279 regname = freg_names[idx];
2280 break;
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];
2289 break;
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];
2297 break;
2299 case REG_CP:
2300 regname = cpreg_names[idx];
2301 break;
2303 case REG_ICC:
2304 regname = icc_names[idx];
2305 break;
2307 case REG_FCC:
2308 regname = fcc_names[idx];
2309 break;
2311 case REG_FSR:
2312 regname = "%fsr";
2313 break;
2315 case REG_CSR:
2316 regname = "%csr";
2317 break;
2319 case REG_CQ:
2320 regname = "%cq";
2321 break;
2323 case REG_NONE:
2324 regname = "";
2325 break;
2328 return (regname);
2332 * output the asi value from the instruction
2334 * TODO: investigate if this should perhaps have a mask -- are undefined ASI
2335 * values for an instruction still disassembled??
2337 static void
2338 prt_asi(dis_handle_t *dhp, uint32_t instr)
2340 ifmt_t *f = (ifmt_t *)&instr;
2341 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2343 if (f->f3.i != 0)
2344 bprintf(dhp, "%%asi");
2345 else
2346 bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi);
2351 * put an address expression into the output buffer
2353 * instr is the instruction to use
2354 * if nobrackets != 0, [] are not added around the instruction
2356 * Currently this option is set when printing out the address portion
2357 * of a jmpl instruction, but otherwise 0 for load/stores
2359 * If no debug flags are set, the full expression is output, even when
2360 * %g0 or 0x0 appears in the address
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
2367 static void
2368 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
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);
2377 if (f->f3a.i == 0) {
2378 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2379 p2 |= (f->f3.rs2 != 0);
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;
2390 simm13 = sign_extend(f->f3a.simm13, 13);
2391 sign = (simm13 < 0) ? "-" : "+";
2393 p1 |= (f->f3a.rs1 != 0);
2394 p2 |= (p1 == 0 || simm13 != 0);
2396 if (p1 == 0 && simm13 == 0)
2397 p2 = 1;
2399 if (p1 == 0 && simm13 >= 0)
2400 sign = "";
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) ? "]" : "");
2422 * print out the arguments to an alu operation (add, sub, etc.)
2423 * conatined in 'instr'
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
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
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
2439 static void
2440 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
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;
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);
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);
2456 if (r1 == NULL || r1[0] == '\0')
2457 p1 = 0;
2459 if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2460 p2 = 0;
2462 if (r3 == NULL || r3[0] == '\0')
2463 p3 = 0;
2465 if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2466 opf = f->fcmp.opf;
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;
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);
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);
2487 if (p3 != 0)
2488 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2491 if (p3 != 0)
2492 (void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2495 static const char *
2496 get_asi_name(uint8_t asi)
2498 switch (asi) {
2499 case 0x04:
2500 return ("ASI_N");
2502 case 0x0c:
2503 return ("ASI_NL");
2505 case 0x10:
2506 return ("ASI_AIUP");
2508 case 0x11:
2509 return ("ASI_AIUS");
2511 case 0x14:
2512 return ("ASI_REAL");
2514 case 0x15:
2515 return ("ASI_REAL_IO");
2517 case 0x16:
2518 return ("ASI_BLK_AIUP");
2520 case 0x17:
2521 return ("ASI_BLK_AIUS");
2523 case 0x18:
2524 return ("ASI_AIUPL");
2526 case 0x19:
2527 return ("ASI_AIUSL");
2529 case 0x1c:
2530 return ("ASI_REAL_L");
2532 case 0x1d:
2533 return ("ASI_REAL_IO_L");
2535 case 0x1e:
2536 return ("ASI_BLK_AIUPL");
2538 case 0x1f:
2539 return ("ASI_BLK_AIUS_L");
2541 case 0x20:
2542 return ("ASI_SCRATCHPAD");
2544 case 0x21:
2545 return ("ASI_MMU_CONTEXTID");
2547 case 0x22:
2548 return ("ASI_TWINX_AIUP");
2550 case 0x23:
2551 return ("ASI_TWINX_AIUS");
2553 case 0x25:
2554 return ("ASI_QUEUE");
2556 case 0x26:
2557 return ("ASI_TWINX_R");
2559 case 0x27:
2560 return ("ASI_TWINX_N");
2562 case 0x2a:
2563 return ("ASI_LDTX_AIUPL");
2565 case 0x2b:
2566 return ("ASI_TWINX_AIUS_L");
2568 case 0x2e:
2569 return ("ASI_TWINX_REAL_L");
2571 case 0x2f:
2572 return ("ASI_TWINX_NL");
2574 case 0x30:
2575 return ("ASI_AIPP");
2577 case 0x31:
2578 return ("ASI_AIPS");
2580 case 0x36:
2581 return ("ASI_AIPN");
2583 case 0x38:
2584 return ("ASI_AIPP_L");
2586 case 0x39:
2587 return ("ASI_AIPS_L");
2589 case 0x3e:
2590 return ("ASI_AIPN_L");
2592 case 0x41:
2593 return ("ASI_CMT_SHARED");
2595 case 0x4f:
2596 return ("ASI_HYP_SCRATCHPAD");
2598 case 0x50:
2599 return ("ASI_IMMU");
2601 case 0x52:
2602 return ("ASI_MMU_REAL");
2604 case 0x54:
2605 return ("ASI_MMU");
2607 case 0x55:
2608 return ("ASI_ITLB_DATA_ACCESS_REG");
2610 case 0x56:
2611 return ("ASI_ITLB_TAG_READ_REG");
2613 case 0x57:
2614 return ("ASI_IMMU_DEMAP");
2616 case 0x58:
2617 return ("ASI_DMMU / ASI_UMMU");
2619 case 0x5c:
2620 return ("ASI_DTLB_DATA_IN_REG");
2622 case 0x5d:
2623 return ("ASI_DTLB_DATA_ACCESS_REG");
2625 case 0x5e:
2626 return ("ASI_DTLB_TAG_READ_REG");
2628 case 0x5f:
2629 return ("ASI_DMMU_DEMAP");
2631 case 0x63:
2632 return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE");
2634 case 0x80:
2635 return ("ASI_P");
2637 case 0x81:
2638 return ("ASI_S");
2640 case 0x82:
2641 return ("ASI_PNF");
2643 case 0x83:
2644 return ("ASI_SNF");
2646 case 0x88:
2647 return ("ASI_PL");
2649 case 0x89:
2650 return ("ASI_SL");
2652 case 0x8a:
2653 return ("ASI_PNFL");
2655 case 0x8b:
2656 return ("ASI_SNFL");
2658 case 0xc0:
2659 return ("ASI_PST8_P");
2661 case 0xc1:
2662 return ("ASI_PST8_S");
2664 case 0xc2:
2665 return ("ASI_PST16_P");
2667 case 0xc3:
2668 return ("ASI_PST16_S");
2670 case 0xc4:
2671 return ("ASI_PST32_P");
2673 case 0xc5:
2674 return ("ASI_PST32_S");
2676 case 0xc8:
2677 return ("ASI_PST8_PL");
2679 case 0xc9:
2680 return ("ASI_PST8_SL");
2682 case 0xca:
2683 return ("ASI_PST16_PL");
2685 case 0xcb:
2686 return ("ASI_PST16_SL");
2688 case 0xcc:
2689 return ("ASI_PST32_PL");
2691 case 0xcd:
2692 return ("ASI_PST32_SL");
2694 case 0xd0:
2695 return ("ASI_FL8_P");
2697 case 0xd1:
2698 return ("ASI_FL8_S");
2700 case 0xd2:
2701 return ("ASI_FL16_P");
2703 case 0xd3:
2704 return ("ASI_FL16_S");
2706 case 0xd8:
2707 return ("ASI_FL8_PL");
2709 case 0xd9:
2710 return ("ASI_FL8_SL");
2712 case 0xda:
2713 return ("ASI_FL16_PL");
2715 case 0xdb:
2716 return ("ASI_FL16_SL");
2718 case 0xe0:
2719 return ("ASI_BLK_COMMIT_P");
2721 case 0xe1:
2722 return ("ASI_BLK_SOMMIT_S");
2724 case 0xe2:
2725 return ("ASI_TWINX_P");
2727 case 0xe3:
2728 return ("ASI_TWINX_S");
2730 case 0xea:
2731 return ("ASI_TWINX_PL");
2733 case 0xeb:
2734 return ("ASI_TWINX_SL");
2736 case 0xf0:
2737 return ("ASI_BLK_P");
2739 case 0xf1:
2740 return ("ASI_BLK_S");
2742 case 0xf8:
2743 return ("ASI_BLK_PL");
2745 case 0xf9:
2746 return ("ASI_BLK_SL");
2748 default:
2749 return (NULL);
2754 * just a handy function that takes care of managing the buffer length
2755 * w/ printf
2759 * PRINTF LIKE 1
2761 static void
2762 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2764 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2765 size_t curlen;
2766 va_list ap;
2768 curlen = strlen(dhx->dhx_buf);
2770 va_start(ap, fmt);
2771 (void) dis_vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen -
2772 curlen, fmt, ap);
2773 va_end(ap);