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 <sys/debug.h>
36#include <stdarg.h>
37
38#if !defined(DIS_STANDALONE)
39#include <stdio.h>
40#endif /* DIS_STANDALONE */
41
42#include "libdisasm.h"
43#include "libdisasm_impl.h"
44#include "dis_sparc.h"
45#include "dis_sparc_fmt.h"
46
47extern char *strncpy(char *, const char *, size_t);
48extern size_t strlen(const char *);
49extern int strcmp(const char *, const char *);
50extern int strncmp(const char *, const char *, size_t);
51extern size_t strlcat(char *, const char *, size_t);
52extern size_t strlcpy(char *, const char *, size_t);
53
54/*
55 * This file has the functions that do all the dirty work of outputting the
56 * disassembled instruction
57 *
58 * All the non-static functions follow the format_fcn (in dis_sparc.h):
59 * Input:
60 *	disassembler handle/context
61 *	instruction to disassemble
62 *	instruction definition pointer (inst_t *)
63 *	index in the table of the instruction
64 * Return:
65 *	0 Success
66 *    !0 Invalid instruction
67 *
68 * Generally, instructions found in the same table use the same output format
69 * or have a few minor differences (which are described in the 'flags' field
70 * of the instruction definition. In some cases, certain instructions differ
71 * radically enough from those in the same table, that their own format
72 * function is used.
73 *
74 * Typically each table has a unique format function defined in this file.  In
75 * some cases (such as branches) a common one for all the tables is used.
76 *
77 * When adding support for new instructions, it is largely a judgement call
78 * as to when a new format function is defined.
79 */
80
81/* The various instruction formats of a sparc instruction */
82
83#if defined(_BIT_FIELDS_HTOL)
84typedef struct format1 {
85	uint32_t op:2;
86	uint32_t disp30:30;
87} format1_t;
88#elif defined(_BIT_FIELDS_LTOH)
89typedef struct format1 {
90	uint32_t disp30:30;
91	uint32_t op:2;
92} format1_t;
93#else
94#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
95#endif
96
97#if defined(_BIT_FIELDS_HTOL)
98typedef 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)
105typedef struct format2 {
106	uint32_t imm22:22;
107	uint32_t op2:3;
108	uint32_t rd:5;
109	uint32_t op:2;
110} format2_t;
111#else
112#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
113#endif
114
115#if defined(_BIT_FIELDS_HTOL)
116typedef 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)
124typedef struct format2a {
125	uint32_t disp22:22;
126	uint32_t op2:3;
127	uint32_t cond:4;
128	uint32_t a:1;
129	uint32_t op:2;
130} format2a_t;
131#else
132#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
133#endif
134
135#if defined(_BIT_FIELDS_HTOL)
136typedef 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)
146typedef struct format2b {
147	uint32_t disp19:19;
148	uint32_t p:1;
149	uint32_t cc:2;
150	uint32_t op2:3;
151	uint32_t cond:4;
152	uint32_t a:1;
153	uint32_t op:2;
154} format2b_t;
155#else
156#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
157#endif
158
159#if defined(_BIT_FIELDS_HTOL)
160typedef 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)
171typedef struct format2c {
172	uint32_t d16lo:14;
173	uint32_t rs1:5;
174	uint32_t p:1;
175	uint32_t d16hi:2;
176	uint32_t op2:3;
177	uint32_t cond:4;
178	uint32_t a:1;
179	uint32_t op:2;
180} format2c_t;
181#else
182#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
183#endif
184
185#if defined(_BIT_FIELDS_HTOL)
186typedef 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)
196typedef struct format3 {
197	uint32_t rs2:5;
198	uint32_t asi:8;
199	uint32_t i:1;
200	uint32_t rs1:5;
201	uint32_t op3:6;
202	uint32_t rd:5;
203	uint32_t op:2;
204} format3_t;
205#else
206#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
207#endif
208
209#if defined(_BIT_FIELDS_HTOL)
210typedef 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)
219typedef struct format3a {
220	uint32_t simm13:13;
221	uint32_t i:1;
222	uint32_t rs1:5;
223	uint32_t op3:6;
224	uint32_t rd:5;
225	uint32_t op:2;
226} format3a_t;
227#else
228#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
229#endif
230
231#if defined(_BIT_FIELDS_HTOL)
232typedef 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)
243typedef struct format3b {
244	uint32_t shcnt:6;
245	uint32_t undef:6;
246	uint32_t x:1;
247	uint32_t i:1;
248	uint32_t rs1:5;
249	uint32_t op3:6;
250	uint32_t rd:5;
251	uint32_t op:2;
252} format3b_t;
253#else
254#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
255#endif
256
257#if defined(_BIT_FIELDS_HTOL)
258typedef 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)
269typedef struct format3c {
270	uint32_t simm11:11;
271	uint32_t cc:2;
272	uint32_t i:1;
273	uint32_t cond:4;
274	uint32_t cc2:1;
275	uint32_t op3:6;
276	uint32_t rd:5;
277	uint32_t op:2;
278} format3c_t;
279#else
280#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
281#endif
282
283#if defined(_BIT_FIELDS_HTOL)
284typedef 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)
294typedef struct format3d {
295	uint32_t simm10:10;
296	uint32_t rcond:3;
297	uint32_t i:1;
298	uint32_t rs1:5;
299	uint32_t op3:6;
300	uint32_t rd:5;
301	uint32_t op:2;
302} format3d_t;
303#else
304#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
305#endif
306
307#if defined(_BIT_FIELDS_HTOL)
308typedef 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)
317typedef struct formatcp {
318	uint32_t rs2:5;
319	uint32_t opc:9;
320	uint32_t rs1:5;
321	uint32_t op3:6;
322	uint32_t rd:5;
323	uint32_t op:2;
324} formatcp_t;
325#else
326#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
327#endif
328
329#if defined(_BIT_FIELDS_HTOL)
330typedef 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)
342typedef struct formattcc {
343	uint32_t immtrap:8;
344	uint32_t undef2:3;
345	uint32_t cc:2;
346	uint32_t i:1;
347	uint32_t rs1:5;
348	uint32_t op3:6;
349	uint32_t cond:4;
350	uint32_t undef:1;
351	uint32_t op:2;
352} formattcc_t;
353#else
354#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
355#endif
356
357#if defined(_BIT_FIELDS_HTOL)
358typedef 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)
370typedef struct formattcc2 {
371	uint32_t rs2:5;
372	uint32_t undef2:6;
373	uint32_t cc:2;
374	uint32_t i:1;
375	uint32_t rs1:5;
376	uint32_t op3:6;
377	uint32_t cond:4;
378	uint32_t undef:1;
379	uint32_t op:2;
380} formattcc2_t;
381#else
382#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
383#endif
384
385#if defined(_BIT_FIELDS_HTOL)
386typedef 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)
397typedef struct formatmbr {
398	uint32_t mmask:4;
399	uint32_t cmask:3;
400	uint32_t undef:6;
401	uint32_t i:1;
402	uint32_t rs1:5;
403	uint32_t op3:6;
404	uint32_t rd:5;
405	uint32_t op:2;
406} formatmbr_t;
407#else
408#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
409#endif
410
411#if defined(_BIT_FIELDS_HTOL)
412typedef 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)
422typedef struct formatfcmp {
423	uint32_t rs2:5;
424	uint32_t opf:9;
425	uint32_t rs1:5;
426	uint32_t op3:6;
427	uint32_t cc:2;
428	uint32_t undef:3;
429	uint32_t op:2;
430} formatfcmp_t;
431#else
432#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
433#endif
434
435#if defined(_BIT_FIELDS_HTOL)
436typedef 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)
447typedef struct formatfmov {
448	uint32_t rs2:5;
449	uint32_t opf:6;
450	uint32_t cc:3;
451	uint32_t cond:4;
452	uint32_t undef:1;
453	uint32_t op3:6;
454	uint32_t rd:5;
455	uint32_t op:2;
456} formatfmov_t;
457#else
458#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
459#endif
460
461#if defined(_BIT_FIELDS_HTOL)
462typedef 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)
472typedef struct formatfused {
473	uint32_t rs2:5;
474	uint32_t op5:4;
475	uint32_t rs3:5;
476	uint32_t rs1:5;
477	uint32_t op3:6;
478	uint32_t rd:5;
479	uint32_t op:2;
480} formatfused_t;
481#else
482#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
483#endif
484
485typedef union ifmt {
486	uint32_t	i;
487	format1_t	f1;
488	format2_t	f2;
489	format2a_t	f2a;
490	format2b_t	f2b;
491	format2c_t	f2c;
492	format3_t	f3;
493	format3a_t	f3a;
494	format3b_t	f3b;
495	format3c_t	f3c;
496	format3d_t	f3d;
497	formatcp_t	fcp;
498	formattcc_t	ftcc;
499	formattcc2_t	ftcc2;
500	formatfcmp_t	fcmp;
501	formatmbr_t	fmb;
502	formatfmov_t	fmv;
503	formatfused_t	fused;
504} ifmt_t;
505
506/* integer register names */
507static const char *reg_names[32] = {
508	"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
509	"%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
510	"%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
511	"%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7"
512};
513
514/* floating point register names */
515static const char *freg_names[32] = {
516	"%f0",  "%f1",  "%f2",  "%f3",  "%f4",  "%f5",  "%f6",  "%f7",
517	"%f8",  "%f9",  "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
518	"%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
519	"%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"
520};
521
522/* double precision register names */
523static const char *fdreg_names[32] = {
524	"%d0",  "%d32", "%d2",  "%d34", "%d4",  "%d36", "%d6",  "%d38",
525	"%d8",  "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46",
526	"%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54",
527	"%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62"
528};
529
530static const char *compat_fdreg_names[32] = {
531	"%f0",  "%f32", "%f2",  "%f34", "%f4",  "%f36", "%f6",  "%f38",
532	"%f8",  "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46",
533	"%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54",
534	"%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62"
535};
536
537
538static const char *fqreg_names[32] = {
539	"%q0",  "%q32", "%f2",  "%f3",  "%f4",  "%q4",  "%q36", "%f6",
540	"%f7",  "%q8",  "%q40", "%f10", "%f11", "%q12", "%q44", "%f14",
541	"%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22",
542	"%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30",
543};
544
545
546/* coprocessor register names -- sparcv8 only */
547static const char *cpreg_names[32] = {
548	"%c0",  "%c1",  "%c2",  "%c3",  "%c4",  "%c5",  "%c6",  "%c7",
549	"%c8",  "%c9",  "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
550	"%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23",
551	"%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31",
552};
553
554/* floating point condition code names */
555static const char *fcc_names[4] = {
556	"%fcc0", "%fcc1", "%fcc2", "%fcc3"
557};
558
559/* condition code names */
560static const char *icc_names[4] = {
561	"%icc", NULL, "%xcc", NULL
562};
563
564/* bitmask values for membar */
565static const char *membar_mmask[4] = {
566	"#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore"
567};
568
569static const char *membar_cmask[3] = {
570	"#Lookaside", "#MemIssue", "#Sync"
571};
572
573/* v8 ancillary state register names */
574static const char *asr_names[32] = {
575	"%y",	"%asr1",  "%asr2",  "%asr3",
576	"%asr4",  "%asr5",  "%asr6",  "%asr7",
577	"%asr8",  "%asr9",  "%asr10", "%asr11",
578	"%asr12", "%asr13", "%asr14", "%asr15",
579	NULL,	NULL,	NULL,	NULL,
580	NULL,	NULL,	NULL,	NULL,
581	NULL,	NULL,	NULL,	NULL,
582	NULL,	NULL,	NULL,	NULL
583};
584static const uint32_t asr_rdmask = 0x0000ffffL;
585static const uint32_t asr_wrmask = 0x0000ffffL;
586
587static const char *v9_asr_names[32] = {
588	"%y",		NULL,		"%ccr",	"%asi",
589	"%tick",	"%pc",		"%fprs",	NULL,
590	NULL,		NULL,		NULL,	NULL,
591	NULL,		NULL,		NULL,	NULL,
592	"%pcr",		"%pic",		"%dcr",	"%gsr",
593	"%softint_set",	"%softint_clr",	"%softint",	"%tick_cmpr",
594	"%stick",	"%stick_cmpr",	NULL,	NULL,
595	NULL,		NULL,		NULL,	NULL
596};
597/*
598 * on v9, only certain registers are valid for read or writing
599 * these are bitmasks corresponding to which registers are valid in which
600 * case. Any access to %dcr is illegal.
601 */
602static const uint32_t v9_asr_rdmask = 0x03cb007d;
603static const uint32_t v9_asr_wrmask = 0x03fb004d;
604
605/* privledged register names on v9 */
606/* TODO: compat - NULL to %priv_nn */
607static const char *v9_privreg_names[32] = {
608	"%tpc",	 "%tnpc",	"%tstate",  "%tt",
609	"%tick",	"%tba",	 "%pstate",  "%tl",
610	"%pil",	 "%cwp",	 "%cansave", "%canrestore",
611	"%cleanwin", "%otherwin", "%wstate",  "%fq",
612	"%gl",	NULL,	NULL,	NULL,
613	NULL,	NULL,	NULL,	NULL,
614	NULL,	NULL,	NULL,	NULL,
615	NULL,	NULL,	NULL,	"%ver"
616};
617
618/* hyper privileged register names on v9 */
619static const char *v9_hprivreg_names[32] = {
620	"%hpstate",	 "%htstate",	NULL,  "%hintp",
621	NULL,	"%htba",	 "%hver",  NULL,
622	NULL,	NULL,	NULL,	NULL,
623	NULL,	NULL,	NULL,	NULL,
624	NULL,	NULL,	NULL,	NULL,
625	NULL,	NULL,	NULL,	NULL,
626	NULL,	NULL,	NULL,	NULL,
627	NULL,	NULL,	NULL,	"%hstick_cmpr"
628};
629
630static const uint32_t v9_pr_rdmask = 0x80017fff;
631static const uint32_t v9_pr_wrmask = 0x00017fff;
632static const uint32_t v9_hpr_rdmask = 0x8000006b;
633static const uint32_t v9_hpr_wrmask = 0x8000006b;
634
635static const char *prefetch_str[32] = {
636	"#n_reads", "#one_read",
637	"#n_writes", "#one_write",
638	"#page",    NULL, NULL, NULL,
639	NULL, NULL, NULL, NULL,
640	NULL, NULL, NULL, NULL,
641	NULL, "#unified", NULL, NULL,
642	"#n_reads_strong", "#one_read_strong",
643	"#n_writes_strong", "#one_write_strong",
644	NULL, NULL, NULL, NULL,
645	NULL, NULL, NULL, NULL
646};
647
648static void prt_field(const char *, uint32_t, int);
649
650static const char *get_regname(dis_handle_t *, int, uint32_t);
651static int32_t sign_extend(int32_t, uint32_t);
652
653static void prt_name(dis_handle_t *, const char *, int);
654
655#define	IMM_SIGNED 0x01  /* Is immediate value signed		*/
656#define	IMM_ADDR   0x02  /* Is immediate value part of an address */
657static void prt_imm(dis_handle_t *, uint32_t, int);
658
659static void prt_asi(dis_handle_t *, uint32_t);
660static const char *get_asi_name(uint8_t);
661static void prt_address(dis_handle_t *, uint32_t, int);
662static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t);
663static void bprintf(dis_handle_t *, const char *, ...);
664
665/*
666 * print out val (which is 'bitlen' bits long) in binary
667 */
668#if defined(DIS_STANDALONE)
669/* ARGSUSED */
670void
671prt_binary(uint32_t val, int bitlen)
672{
673
674}
675
676#else
677
678void
679prt_binary(uint32_t val, int bitlen)
680{
681	int i;
682
683	for (i = bitlen - 1; i >= 0; --i) {
684		(void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
685
686		if (i % 4 == 0 && i != 0)
687			(void) fprintf(stderr, " ");
688	}
689}
690#endif /* DIS_STANDALONE */
691
692
693/*
694 * print out a call instruction
695 * format: call address  <name>
696 */
697/* ARGSUSED1 */
698int
699fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
700{
701	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
702	ifmt_t *f = (ifmt_t *)&instr;
703
704	int32_t disp;
705	size_t curlen;
706
707	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
708
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);
712	}
713
714	disp = sign_extend(f->f1.disp30, 30) * 4;
715
716	prt_name(dhp, inp->in_data.in_def.in_name, 1);
717
718	bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
719	    (disp < 0) ? "-" : "+",
720	    (disp < 0) ? (-disp) : disp);
721
722	(void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen);
723
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);
729
730
731	return (0);
732}
733
734int
735fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
736{
737	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
738	ifmt_t *f = (ifmt_t *)&instr;
739
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);
745	}
746
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);
752	}
753
754	if (f->f2.imm22 == 0 && f->f2.rd == 0) {
755		prt_name(dhp, "nop", 0);
756		return (0);
757	}
758
759	/* ?? Should we return -1 if rd == 0 && disp != 0 */
760
761	prt_name(dhp, inp->in_data.in_def.in_name, 1);
762
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]);
768
769	return (0);
770}
771
772/* ARGSUSED3 */
773int
774fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
775{
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  = "";
781
782	char buf[15];
783
784	ifmt_t *f = (ifmt_t *)&instr;
785
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);
790
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);
794
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;
801
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;
809
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;
818		}
819	}
820
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);
825	}
826
827
828	switch (FLG_DISP_VAL(flags)) {
829	case DISP22:
830		disp = sign_extend(f->f2a.disp22, 22);
831		break;
832
833	case DISP19:
834		disp = sign_extend(f->f2b.disp19, 19);
835		break;
836
837	case DISP16:
838		disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
839		break;
840
841	}
842
843	disp *= 4;
844
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);
849
850	if (r == NULL)
851		return (-1);
852
853	if (f->f2a.a == 1)
854		annul = ",a";
855
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";
862		}
863	}
864
865	(void) dis_snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
866	prt_name(dhp, buf, 1);
867
868
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;
876
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;
884
885	case DISP16:
886		bprintf(dhp,
887		    (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
888		    r,
889		    (disp < 0) ? "-" : "+",
890		    (disp < 0) ? (-disp) : disp);
891		break;
892	}
893
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);
897
898	(void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
899
900	return (0);
901}
902
903
904
905/*
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
909 *
910 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
911 * when an immediate ASI value is given as follows:
912 *
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
917 */
918static int
919fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
920{
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;
925
926	asistr = get_asi_name(f->f3.asi);
927
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";
933			}
934
935			if (f->f3.asi == 0x88) {
936				noasi = 1;
937				name = "casl";
938			}
939		}
940
941		if (f->f3.op3 == 0x3e && f->f3.i == 0) {
942			if (f->f3.asi == 0x80) {
943				noasi = 1;
944				name = "casx";
945			}
946
947			if (f->f3.asi == 0x88) {
948				noasi = 1;
949				name = "casxl";
950			}
951		}
952	}
953
954	prt_name(dhp, name, 1);
955
956	bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
957
958	if (noasi == 0) {
959		(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
960		prt_asi(dhp, instr);
961	}
962
963	bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
964
965	if (noasi == 0 && asistr != NULL)
966		bprintf(dhp, "\t<%s>", asistr);
967
968	return (0);
969}
970
971/*
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
977 *
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
982 *
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
985 *
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
989 *
990 * The following synthetic instructions are also implemented:
991 *
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
996 *
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
1002 */
1003int
1004fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1005{
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;
1010
1011	const char *iname = inp->in_data.in_def.in_name;
1012	uint32_t flags = inp->in_data.in_def.in_flags;
1013
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);
1025		}
1026		prt_field("rd", f->f3.rd, 5);
1027	}
1028
1029	if (idx == 0x2d || idx == 0x3d) {
1030		/* prefetch / prefetcha */
1031
1032		prt_name(dhp, iname, 1);
1033
1034		prt_address(dhp, instr, 0);
1035
1036		if (idx == 0x3d) {
1037			(void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1038			prt_asi(dhp, instr);
1039		}
1040
1041		(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1042
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);
1049
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);
1054		}
1055
1056		return (0);
1057	}
1058
1059	/* casa / casxa */
1060	if (idx == 0x3c || idx == 0x3e)
1061		return (fmt_cas(dhp, instr, iname));
1062
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;
1070
1071	case 0x03:
1072		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1073			iname = "ldtw";
1074		break;
1075
1076	case 0x04:
1077		/* stw */
1078		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1079			iname = "stuw";
1080
1081		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1082		    == 0)
1083			break;
1084
1085		if (f->f3.rd == 0) {
1086			iname = "clr";
1087			flags = FLG_RD(REG_NONE);
1088		}
1089		break;
1090
1091	case 0x05:
1092		/* stb */
1093		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1094		    == 0)
1095			break;
1096
1097		if (f->f3.rd == 0) {
1098			iname = "clrb";
1099			flags = FLG_RD(REG_NONE);
1100		}
1101		break;
1102
1103	case 0x06:
1104		/* sth */
1105		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1106		    == 0)
1107			break;
1108
1109		if (f->f3.rd == 0) {
1110			iname = "clrh";
1111			flags = FLG_RD(REG_NONE);
1112		}
1113		break;
1114
1115	case 0x07:
1116		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1117			iname = "sttw";
1118		break;
1119
1120	case 0x0e:
1121		/* stx */
1122
1123		if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1124		    == 0)
1125			break;
1126
1127		if (f->f3.rd == 0) {
1128			iname = "clrx";
1129			flags = FLG_RD(REG_NONE);
1130		}
1131		break;
1132
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;
1139
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;
1146
1147	case 0x21:
1148	case 0x25:
1149		/*
1150		 * on sparcv8 it merely says that rd != 1 should generate an
1151		 * exception, on v9, it is illegal
1152		 */
1153		if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1154			break;
1155
1156		iname = (idx == 0x21) ? "ldx" : "stx";
1157
1158		if (f->f3.rd > 1)
1159			return (-1);
1160
1161		break;
1162
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:
1178				/*
1179				 * store partial floating point, only valid w/
1180				 * vis
1181				 *
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
1187				 */
1188
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);
1202
1203				return (0);
1204
1205			default:
1206				break;
1207		}
1208
1209	}
1210
1211	regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1212
1213	if (f->f3.i == 0)
1214		asistr = get_asi_name(f->f3.asi);
1215
1216	prt_name(dhp, iname, 1);
1217
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);
1222		}
1223
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);
1228		}
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);
1234		}
1235
1236		if (regstr[0] != '\0') {
1237			(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1238			(void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1239		}
1240	}
1241
1242	if ((flags & FLG_ASI) != 0 && asistr != NULL)
1243		bprintf(dhp, "\t<%s>", asistr);
1244
1245	return (0);
1246}
1247
1248static int
1249fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1250{
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);
1254
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);
1262	}
1263
1264	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1265	prt_imm(dhp, f->fcp.opc, 0);
1266
1267	(void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1268	(void) prt_aluargs(dhp, instr, flags);
1269
1270	return (0);
1271}
1272
1273static int
1274dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1275{
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";
1280
1281	const char *name = inp->in_data.in_def.in_name;
1282	const char *regstr = NULL;
1283
1284	ifmt_t *f = (ifmt_t *)&instr;
1285
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;
1292
1293	int use_mask = 1;
1294	uint32_t mask;
1295
1296	if (rd == 0)
1297		ridx = f->f3.rd;
1298
1299	switch (idx) {
1300	case 0x28:
1301		/* rd */
1302
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);
1307		}
1308
1309		/* membar */
1310		if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) &&
1311		    (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) {
1312
1313			prt_name(dhp, "membar",
1314			    ((f->fmb.cmask != 0) || (f->fmb.mmask != 0)));
1315
1316			first = 0;
1317
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;
1324				}
1325			}
1326
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;
1333				}
1334			}
1335
1336			return (0);
1337		}
1338
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;
1345		}
1346		break;
1347
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;
1355		}
1356		break;
1357
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;
1365		}
1366		break;
1367
1368	case 0x2b:
1369		if (v9 != 0) {
1370			/* flushw */
1371			prt_name(dhp, name, 0);
1372			return (0);
1373		}
1374
1375		regstr = tbr_str;
1376		use_mask = 0;
1377		break;
1378
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;
1386		}
1387
1388		/*
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
1392		 */
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);
1399		}
1400
1401		/* synth: mov */
1402		if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1403		    == 0)
1404			break;
1405
1406		if (v9 == 0) {
1407			if (f->f3.rs1 == 0) {
1408				name = "mov";
1409				pr_rs1 = 0;
1410			}
1411
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;
1416			}
1417		}
1418
1419		if (pr_rs1 == 0)
1420			pr_rs2 = 1;
1421
1422		break;
1423
1424	case 0x31:
1425		/*
1426		 * NOTE: due to the presence of an overlay entry for another
1427		 * table, this case only happens when doing v8 instructions
1428		 * only
1429		 */
1430		regstr = psr_str;
1431		use_mask = 0;
1432		break;
1433
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;
1441		}
1442		break;
1443
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;
1451		}
1452		break;
1453	}
1454
1455	if (regstr == NULL)
1456		return (-1);
1457
1458	if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1459		return (-1);
1460
1461	prt_name(dhp, name, 1);
1462
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]);
1468
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);
1477		}
1478
1479		(void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1480	}
1481
1482	return (0);
1483}
1484
1485/* ARGSUSED3 */
1486int
1487fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1488{
1489	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1490	ifmt_t *f = (ifmt_t *)&instr;
1491
1492	int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1493	int p_rs1, p_t;
1494
1495	if (f->ftcc.undef != 0)
1496		return (-1);
1497
1498	if (icc_names[f->ftcc.cc] == NULL)
1499		return (-1);
1500
1501	if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1502		return (-1);
1503
1504	if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1505		return (-1);
1506
1507	p_rs1 = ((f->ftcc.rs1 != 0) ||
1508	    ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1509
1510	if (f->ftcc.i == 0) {
1511		p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1512
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);
1526	}
1527	return (0);
1528}
1529
1530static int
1531prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1532{
1533	char name[5];
1534	uint32_t cnt;
1535
1536	ifmt_t *f = (ifmt_t *)&instr;
1537	int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
1538
1539	name[0] = '\0';
1540	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
1541
1542	if (f->f3b.i == 1)
1543		cnt = f->f3.rs2;
1544
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));
1548	}
1549
1550	prt_name(dhp, name, 1);
1551
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]);
1558
1559	return (0);
1560}
1561
1562/* ARGSUSED3 */
1563static int
1564prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1565{
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;
1569
1570	if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1571		name = "call";
1572
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);
1578			}
1579
1580			if (f->f3.rs1 == 31) {
1581				prt_name(dhp, "ret", 0);
1582				return (0);
1583			}
1584		}
1585
1586		name = "jmp";
1587	}
1588
1589	prt_name(dhp, name, 1);
1590	prt_address(dhp, instr, 1);
1591
1592	if (f->f3.rd == 0)
1593		return (0);
1594
1595	if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1596		return (0);
1597
1598	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1599
1600	return (0);
1601}
1602
1603int
1604fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1605{
1606	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1607	ifmt_t *f = (ifmt_t *)&instr;
1608
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;
1612
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);
1617
1618		switch (idx) {
1619			/* TODO: more formats */
1620
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);
1626
1627			prt_field("rd", f->f3.rd, 5);
1628		}
1629
1630	}
1631
1632	switch (idx) {
1633	case 0x00:
1634		/* add */
1635
1636		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1637			break;
1638
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;
1644		}
1645
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;
1651		}
1652		break;
1653
1654	case 0x02:
1655		/* or */
1656
1657		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1658		    == 0)
1659			break;
1660
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;
1666			}
1667		}
1668
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;
1675		}
1676
1677		if (f->f3.rs1 == 0) {
1678			name = "mov";
1679			flags = FLG_P1(REG_NONE);
1680			break;
1681		}
1682		break;
1683
1684	case 0x04:
1685		/* sub */
1686
1687		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1688		    == 0)
1689			break;
1690
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;
1695		}
1696
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;
1701		}
1702
1703		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1704			break;
1705
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;
1711		}
1712
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;
1718		}
1719		break;
1720
1721	case 0x07:
1722		/* xnor */
1723
1724		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1725		    == 0)
1726			break;
1727
1728		/*
1729		 * xnor -> not when you have:
1730		 *	 xnor %rs1, 0x0 or %g0, %rd
1731		 */
1732		if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1733		    (f->f3.i == 1 && f->f3a.simm13 != 0))
1734			break;
1735
1736		name = "not";
1737
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);
1744
1745		break;
1746
1747	case 0x10:
1748		/* addcc */
1749
1750		if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1751			break;
1752
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;
1758		}
1759
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;
1765		}
1766		break;
1767
1768	case 0x11:
1769		/* andcc */
1770
1771		if (f->f3.rd != 0)
1772			break;
1773
1774		if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1775		    == 0)
1776			break;
1777
1778		if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) &&
1779		    ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1780			break;
1781
1782		name = "btst";
1783		flags = FLG_P1(REG_NONE);
1784		f->f3.rd = f->f3.rs1;
1785		break;
1786
1787	case 0x12:
1788		/* orcc */
1789
1790		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1791		    == 0)
1792			break;
1793
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;
1798		}
1799
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;
1804		}
1805
1806		break;
1807
1808	case 0x14:
1809		/* subcc */
1810
1811		if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1812		    == 0)
1813			break;
1814
1815		if (f->f3.rd == 0) {
1816			name = "cmp";
1817			flags = FLG_P3(REG_NONE);
1818			break;
1819		}
1820
1821		if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
1822			break;
1823
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;
1829		}
1830
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;
1836		}
1837
1838		break;
1839
1840	case 0x25:
1841	case 0x26:
1842	case 0x27:
1843		return (prt_shift(dhp, instr, inp));
1844
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));
1854
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;
1861
1862	case 0x38:
1863		/* jmpl */
1864		return (prt_jmpl(dhp, instr, inp, idx));
1865
1866	case 0x39:
1867		/* rett / return */
1868		prt_name(dhp, name, 1);
1869		prt_address(dhp, instr, 1);
1870		return (0);
1871
1872	case 0x3b:
1873		/* flush */
1874		prt_name(dhp, name, 1);
1875		prt_address(dhp, instr, 0);
1876		return (0);
1877
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;
1884
1885		if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1886			break;
1887
1888		if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0))
1889			break;
1890
1891		prt_name(dhp, name, 0);
1892		return (0);
1893	}
1894
1895	if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1896	    FLG_P3_VAL(flags) != REG_NONE)
1897		arg = 1;
1898
1899	prt_name(dhp, name, (arg != 0));
1900	prt_aluargs(dhp, instr, flags);
1901
1902	return (0);
1903}
1904
1905/* ARGSUSED1 */
1906int
1907fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1908{
1909	prt_name(dhp, inp->in_data.in_def.in_name, 0);
1910	return (0);
1911}
1912
1913/* ARGSUSED1 */
1914int
1915fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1916{
1917	ifmt_t *f = (ifmt_t *)&instr;
1918	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1919
1920	if (f->f3.rd == 0xf) {
1921		/* jpriv */
1922		prt_address(dhp, instr, 1);
1923	}
1924
1925	return (0);
1926}
1927
1928/* ARGSUSED3 */
1929int
1930fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1931{
1932	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1933	ifmt_t *f = (ifmt_t *)&instr;
1934	const char **regs = NULL;
1935
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);
1943
1944		if (f->f3c.i == 0)
1945			prt_field("rs2", f->f3.rs2, 5);
1946		else
1947			prt_field("simm11", f->f3c.simm11, 11);
1948
1949		prt_field("rd", f->f3.rd, 5);
1950	}
1951
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);
1958	}
1959
1960	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1961
1962	bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1963
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);
1969
1970	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1971
1972	return (0);
1973}
1974
1975/* ARGSUSED3 */
1976int
1977fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1978{
1979	dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1980	ifmt_t *f = (ifmt_t *)&instr;
1981
1982	prt_name(dhp, inp->in_data.in_def.in_name, 1);
1983
1984	bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1985
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);
1991
1992	bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1993
1994	return (0);
1995}
1996
1997/* ARGSUSED3 */
1998int
1999fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2000{
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;
2004
2005	flags |= FLG_NOIMM;
2006
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);
2014	}
2015
2016	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2017	prt_aluargs(dhp, instr, flags);
2018
2019	return (0);
2020}
2021
2022int
2023fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2024{
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"
2028	};
2029
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"
2033	};
2034
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];
2039
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);
2046
2047	int p_cc = 0;
2048
2049	is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2050
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);
2055
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;
2067
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;
2076
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);
2081		}
2082	}
2083
2084	name[0] = '\0';
2085	(void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
2086
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));
2092	}
2093
2094	prt_name(dhp, name, 1);
2095
2096	if (is_cmp != 0)
2097		ccstr = fcc_names[f->fcmp.cc];
2098
2099	if (is_fmov != 0)
2100		ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3]
2101		    : icc_names[f->fmv.cc & 0x3];
2102
2103	if (ccstr == NULL)
2104		return (-1);
2105
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));
2109
2110	if (p_cc != 0)
2111		bprintf(dhp, "%s, ", ccstr);
2112
2113	prt_aluargs(dhp, instr, flags);
2114
2115	return (0);
2116}
2117
2118int
2119fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2120{
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;
2124
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);
2129
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);
2136		}
2137	}
2138
2139	prt_name(dhp, inp->in_data.in_def.in_name, 1);
2140
2141	if (idx == 0x081) {
2142		/* siam */
2143		bprintf(dhp, "%d", instr & 0x7L);
2144		return (0);
2145	}
2146
2147	prt_aluargs(dhp, instr, flags);
2148
2149	return (0);
2150}
2151
2152/* ARGSUSED3 */
2153int
2154fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2155{
2156	ifmt_t *f = (ifmt_t *)&instr;
2157	int flags = inp->in_data.in_def.in_flags;
2158
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));
2165
2166	return (0);
2167}
2168/*
2169 * put name into the output buffer
2170 * if add_space !=0, append a space after it
2171 */
2172static void
2173prt_name(dis_handle_t *dhp, const char *name, int add_space)
2174{
2175	bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name);
2176}
2177
2178/*
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)
2183 */
2184#if defined(DIS_STANDALONE)
2185/* ARGSUSED */
2186static void
2187prt_field(const char *field, uint32_t val, int len)
2188{
2189
2190}
2191
2192#else
2193static void
2194prt_field(const char *field, uint32_t val, int len)
2195{
2196	(void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val);
2197	prt_binary(val, len);
2198	(void) fprintf(stderr, ")\n");
2199}
2200#endif /* DIS_STANDALONE */
2201
2202/*
2203 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed
2204 * integer
2205 */
2206static int32_t
2207sign_extend(int32_t val, uint32_t bits)
2208{
2209	uint32_t mask;
2210
2211	ASSERT(bits > 0);
2212	mask = 1L << (bits - 1);	/* 2**(bits - 1) */
2213	return (-(val & mask) + (val & ~mask));
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 */
2225static void
2226prt_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 */
2267static const char *
2268get_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 */
2337static void
2338prt_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 */
2367static void
2368prt_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 */
2439static void
2440prt_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
2495static const char *
2496get_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 */
2761static void
2762bprintf(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) dis_vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen -
2772	    curlen, fmt, ap);
2773	va_end(ap);
2774}
2775