xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/sparc-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Print SPARC instructions.
2*e992f068Schristos    Copyright (C) 1989-2022 Free Software Foundation, Inc.
375fd0b74Schristos 
475fd0b74Schristos    This file is part of the GNU opcodes library.
575fd0b74Schristos 
675fd0b74Schristos    This library is free software; you can redistribute it and/or modify
775fd0b74Schristos    it under the terms of the GNU General Public License as published by
875fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
975fd0b74Schristos    any later version.
1075fd0b74Schristos 
1175fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1275fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1375fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1475fd0b74Schristos    License for more details.
1575fd0b74Schristos 
1675fd0b74Schristos    You should have received a copy of the GNU General Public License
1775fd0b74Schristos    along with this program; if not, write to the Free Software
1875fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
1975fd0b74Schristos    MA 02110-1301, USA.  */
2075fd0b74Schristos 
2175fd0b74Schristos #include "sysdep.h"
2275fd0b74Schristos #include <stdio.h>
2375fd0b74Schristos #include "opcode/sparc.h"
2475fd0b74Schristos #include "dis-asm.h"
2575fd0b74Schristos #include "libiberty.h"
2675fd0b74Schristos #include "opintl.h"
2775fd0b74Schristos 
2875fd0b74Schristos /* Bitmask of v9 architectures.  */
2975fd0b74Schristos #define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \
3075fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9A) \
3175fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9B) \
3275fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9C) \
3375fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9D) \
3475fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9E) \
3575fd0b74Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9V) \
36ede78133Schristos 		 | (1 << SPARC_OPCODE_ARCH_V9M) \
37ede78133Schristos 		 | (1 << SPARC_OPCODE_ARCH_M8))
3875fd0b74Schristos /* 1 if INSN is for v9 only.  */
3975fd0b74Schristos #define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9))
4075fd0b74Schristos /* 1 if INSN is for v9.  */
4175fd0b74Schristos #define V9_P(insn) (((insn)->architecture & MASK_V9) != 0)
4275fd0b74Schristos 
4375fd0b74Schristos /* The sorted opcode table.  */
4475fd0b74Schristos static const sparc_opcode **sorted_opcodes;
4575fd0b74Schristos 
4675fd0b74Schristos /* For faster lookup, after insns are sorted they are hashed.  */
4775fd0b74Schristos /* ??? I think there is room for even more improvement.  */
4875fd0b74Schristos 
4975fd0b74Schristos #define HASH_SIZE 256
5075fd0b74Schristos /* It is important that we only look at insn code bits as that is how the
5175fd0b74Schristos    opcode table is hashed.  OPCODE_BITS is a table of valid bits for each
5275fd0b74Schristos    of the main types (0,1,2,3).  */
5375fd0b74Schristos static int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 };
5475fd0b74Schristos #define HASH_INSN(INSN) \
5575fd0b74Schristos   ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19))
5675fd0b74Schristos typedef struct sparc_opcode_hash
5775fd0b74Schristos {
5875fd0b74Schristos   struct sparc_opcode_hash *next;
5975fd0b74Schristos   const sparc_opcode *opcode;
6075fd0b74Schristos } sparc_opcode_hash;
6175fd0b74Schristos 
6275fd0b74Schristos static sparc_opcode_hash *opcode_hash_table[HASH_SIZE];
6375fd0b74Schristos 
6475fd0b74Schristos /* Sign-extend a value which is N bits long.  */
6575fd0b74Schristos #define	SEX(value, bits) \
66012573ebSchristos   ((int) (((value & ((1u << (bits - 1) << 1) - 1))	\
67012573ebSchristos 	   ^ (1u << (bits - 1))) - (1u << (bits - 1))))
6875fd0b74Schristos 
6975fd0b74Schristos static  char *reg_names[] =
7075fd0b74Schristos { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
7175fd0b74Schristos   "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
7275fd0b74Schristos   "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
7375fd0b74Schristos   "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
7475fd0b74Schristos   "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
7575fd0b74Schristos   "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
7675fd0b74Schristos   "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
7775fd0b74Schristos   "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
7875fd0b74Schristos   "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
7975fd0b74Schristos   "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
8075fd0b74Schristos   "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
8175fd0b74Schristos   "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
8275fd0b74Schristos /* psr, wim, tbr, fpsr, cpsr are v8 only.  */
8375fd0b74Schristos   "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
8475fd0b74Schristos };
8575fd0b74Schristos 
8675fd0b74Schristos #define	freg_names	(&reg_names[4 * 8])
8775fd0b74Schristos 
8875fd0b74Schristos /* These are ordered according to there register number in
8975fd0b74Schristos    rdpr and wrpr insns.  */
9075fd0b74Schristos static char *v9_priv_reg_names[] =
9175fd0b74Schristos {
9275fd0b74Schristos   "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
9375fd0b74Schristos   "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
9475fd0b74Schristos   "wstate", "fq", "gl"
9575fd0b74Schristos   /* "ver" and "pmcdper" - special cased */
9675fd0b74Schristos };
9775fd0b74Schristos 
9875fd0b74Schristos /* These are ordered according to there register number in
9975fd0b74Schristos    rdhpr and wrhpr insns.  */
10075fd0b74Schristos static char *v9_hpriv_reg_names[] =
10175fd0b74Schristos {
10275fd0b74Schristos   "hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver",
10375fd0b74Schristos   "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13",
10475fd0b74Schristos   "resv14", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
10575fd0b74Schristos   "resv21", "resv22", "hmcdper", "hmcddfr", "resv25", "resv26", "hva_mask_nz",
10675fd0b74Schristos   "hstick_offset", "hstick_enable", "resv30", "hstick_cmpr"
10775fd0b74Schristos };
10875fd0b74Schristos 
10975fd0b74Schristos /* These are ordered according to there register number in
11075fd0b74Schristos    rd and wr insns (-16).  */
11175fd0b74Schristos static char *v9a_asr_reg_names[] =
11275fd0b74Schristos {
11375fd0b74Schristos   "pcr", "pic", "dcr", "gsr", "softint_set", "softint_clear",
11475fd0b74Schristos   "softint", "tick_cmpr", "stick", "stick_cmpr", "cfr",
11575fd0b74Schristos   "pause", "mwait"
11675fd0b74Schristos };
11775fd0b74Schristos 
11875fd0b74Schristos /* Macros used to extract instruction fields.  Not all fields have
11975fd0b74Schristos    macros defined here, only those which are actually used.  */
12075fd0b74Schristos 
12175fd0b74Schristos #define X_RD(i)      (((i) >> 25) & 0x1f)
12275fd0b74Schristos #define X_RS1(i)     (((i) >> 14) & 0x1f)
12375fd0b74Schristos #define X_LDST_I(i)  (((i) >> 13) & 1)
12475fd0b74Schristos #define X_ASI(i)     (((i) >> 5) & 0xff)
12575fd0b74Schristos #define X_RS2(i)     (((i) >> 0) & 0x1f)
12675fd0b74Schristos #define X_RS3(i)     (((i) >> 9) & 0x1f)
12775fd0b74Schristos #define X_IMM(i,n)   (((i) >> 0) & ((1 << (n)) - 1))
12875fd0b74Schristos #define X_SIMM(i,n)  SEX (X_IMM ((i), (n)), (n))
12975fd0b74Schristos #define X_DISP22(i)  (((i) >> 0) & 0x3fffff)
13075fd0b74Schristos #define X_IMM22(i)   X_DISP22 (i)
13175fd0b74Schristos #define X_DISP30(i)  (((i) >> 0) & 0x3fffffff)
132ede78133Schristos #define X_IMM2(i)    (((i & 0x10) >> 3) | (i & 0x1))
13375fd0b74Schristos 
13475fd0b74Schristos /* These are for v9.  */
13575fd0b74Schristos #define X_DISP16(i)  (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
13675fd0b74Schristos #define X_DISP10(i)  (((((i) >> 19) & 3) << 8) | (((i) >> 5) & 0xff))
13775fd0b74Schristos #define X_DISP19(i)  (((i) >> 0) & 0x7ffff)
13875fd0b74Schristos #define X_MEMBAR(i)  ((i) & 0x7f)
13975fd0b74Schristos 
14075fd0b74Schristos /* Here is the union which was used to extract instruction fields
14175fd0b74Schristos    before the shift and mask macros were written.
14275fd0b74Schristos 
14375fd0b74Schristos    union sparc_insn
14475fd0b74Schristos      {
14575fd0b74Schristos        unsigned long int code;
14675fd0b74Schristos        struct
14775fd0b74Schristos 	 {
14875fd0b74Schristos 	   unsigned int anop:2;
14975fd0b74Schristos 	   #define	op	ldst.anop
15075fd0b74Schristos 	   unsigned int anrd:5;
15175fd0b74Schristos 	   #define	rd	ldst.anrd
15275fd0b74Schristos 	   unsigned int op3:6;
15375fd0b74Schristos 	   unsigned int anrs1:5;
15475fd0b74Schristos 	   #define	rs1	ldst.anrs1
15575fd0b74Schristos 	   unsigned int i:1;
15675fd0b74Schristos 	   unsigned int anasi:8;
15775fd0b74Schristos 	   #define	asi	ldst.anasi
15875fd0b74Schristos 	   unsigned int anrs2:5;
15975fd0b74Schristos 	   #define	rs2	ldst.anrs2
16075fd0b74Schristos 	   #define	shcnt	rs2
16175fd0b74Schristos 	 } ldst;
16275fd0b74Schristos        struct
16375fd0b74Schristos 	 {
16475fd0b74Schristos 	   unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
16575fd0b74Schristos 	   unsigned int IMM13:13;
16675fd0b74Schristos 	   #define	imm13	IMM13.IMM13
16775fd0b74Schristos 	 } IMM13;
16875fd0b74Schristos        struct
16975fd0b74Schristos 	 {
17075fd0b74Schristos 	   unsigned int anop:2;
17175fd0b74Schristos 	   unsigned int a:1;
17275fd0b74Schristos 	   unsigned int cond:4;
17375fd0b74Schristos 	   unsigned int op2:3;
17475fd0b74Schristos 	   unsigned int DISP22:22;
17575fd0b74Schristos 	   #define	disp22	branch.DISP22
17675fd0b74Schristos 	   #define	imm22	disp22
17775fd0b74Schristos 	 } branch;
17875fd0b74Schristos        struct
17975fd0b74Schristos 	 {
18075fd0b74Schristos 	   unsigned int anop:2;
18175fd0b74Schristos 	   unsigned int a:1;
18275fd0b74Schristos 	   unsigned int z:1;
18375fd0b74Schristos 	   unsigned int rcond:3;
18475fd0b74Schristos 	   unsigned int op2:3;
18575fd0b74Schristos 	   unsigned int DISP16HI:2;
18675fd0b74Schristos 	   unsigned int p:1;
18775fd0b74Schristos 	   unsigned int _rs1:5;
18875fd0b74Schristos 	   unsigned int DISP16LO:14;
18975fd0b74Schristos 	 } branch16;
19075fd0b74Schristos        struct
19175fd0b74Schristos 	 {
19275fd0b74Schristos 	   unsigned int anop:2;
19375fd0b74Schristos 	   unsigned int adisp30:30;
19475fd0b74Schristos 	   #define	disp30	call.adisp30
19575fd0b74Schristos 	 } call;
19675fd0b74Schristos      };  */
19775fd0b74Schristos 
19875fd0b74Schristos /* Nonzero if INSN is the opcode for a delayed branch.  */
19975fd0b74Schristos 
20075fd0b74Schristos static int
is_delayed_branch(unsigned long insn)20175fd0b74Schristos is_delayed_branch (unsigned long insn)
20275fd0b74Schristos {
20375fd0b74Schristos   sparc_opcode_hash *op;
20475fd0b74Schristos 
20575fd0b74Schristos   for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
20675fd0b74Schristos     {
20775fd0b74Schristos       const sparc_opcode *opcode = op->opcode;
20875fd0b74Schristos 
20975fd0b74Schristos       if ((opcode->match & insn) == opcode->match
21075fd0b74Schristos 	  && (opcode->lose & insn) == 0)
21175fd0b74Schristos 	return opcode->flags & F_DELAYED;
21275fd0b74Schristos     }
21375fd0b74Schristos   return 0;
21475fd0b74Schristos }
21575fd0b74Schristos 
21675fd0b74Schristos /* extern void qsort (); */
21775fd0b74Schristos 
21875fd0b74Schristos /* Records current mask of SPARC_OPCODE_ARCH_FOO values, used to pass value
21975fd0b74Schristos    to compare_opcodes.  */
22075fd0b74Schristos static unsigned int current_arch_mask;
22175fd0b74Schristos 
22275fd0b74Schristos /* Given BFD mach number, return a mask of SPARC_OPCODE_ARCH_FOO values.  */
22375fd0b74Schristos 
22475fd0b74Schristos static int
compute_arch_mask(unsigned long mach)22575fd0b74Schristos compute_arch_mask (unsigned long mach)
22675fd0b74Schristos {
22775fd0b74Schristos   switch (mach)
22875fd0b74Schristos     {
22975fd0b74Schristos     case 0 :
23075fd0b74Schristos     case bfd_mach_sparc :
23175fd0b74Schristos       return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
23275fd0b74Schristos               | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_LEON));
23375fd0b74Schristos     case bfd_mach_sparc_sparclet :
23475fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET);
23575fd0b74Schristos     case bfd_mach_sparc_sparclite :
23675fd0b74Schristos     case bfd_mach_sparc_sparclite_le :
23775fd0b74Schristos       /* sparclites insns are recognized by default (because that's how
23875fd0b74Schristos 	 they've always been treated, for better or worse).  Kludge this by
23975fd0b74Schristos 	 indicating generic v8 is also selected.  */
24075fd0b74Schristos       return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
24175fd0b74Schristos 	      | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8));
24275fd0b74Schristos     case bfd_mach_sparc_v8plus :
24375fd0b74Schristos     case bfd_mach_sparc_v9 :
24475fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
24575fd0b74Schristos     case bfd_mach_sparc_v8plusa :
24675fd0b74Schristos     case bfd_mach_sparc_v9a :
24775fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A);
24875fd0b74Schristos     case bfd_mach_sparc_v8plusb :
24975fd0b74Schristos     case bfd_mach_sparc_v9b :
25075fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B);
25175fd0b74Schristos     case bfd_mach_sparc_v8plusc :
25275fd0b74Schristos     case bfd_mach_sparc_v9c :
25375fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9C);
25475fd0b74Schristos     case bfd_mach_sparc_v8plusd :
25575fd0b74Schristos     case bfd_mach_sparc_v9d :
25675fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9D);
25775fd0b74Schristos     case bfd_mach_sparc_v8pluse :
25875fd0b74Schristos     case bfd_mach_sparc_v9e :
25975fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9E);
26075fd0b74Schristos     case bfd_mach_sparc_v8plusv :
26175fd0b74Schristos     case bfd_mach_sparc_v9v :
26275fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9V);
26375fd0b74Schristos     case bfd_mach_sparc_v8plusm :
26475fd0b74Schristos     case bfd_mach_sparc_v9m :
26575fd0b74Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9M);
266ede78133Schristos     case bfd_mach_sparc_v8plusm8 :
267ede78133Schristos     case bfd_mach_sparc_v9m8 :
268ede78133Schristos       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_M8);
26975fd0b74Schristos     }
27075fd0b74Schristos   abort ();
27175fd0b74Schristos }
27275fd0b74Schristos 
27375fd0b74Schristos /* Compare opcodes A and B.  */
27475fd0b74Schristos 
27575fd0b74Schristos static int
compare_opcodes(const void * a,const void * b)27675fd0b74Schristos compare_opcodes (const void * a, const void * b)
27775fd0b74Schristos {
27875fd0b74Schristos   sparc_opcode *op0 = * (sparc_opcode **) a;
27975fd0b74Schristos   sparc_opcode *op1 = * (sparc_opcode **) b;
28075fd0b74Schristos   unsigned long int match0 = op0->match, match1 = op1->match;
28175fd0b74Schristos   unsigned long int lose0 = op0->lose, lose1 = op1->lose;
28275fd0b74Schristos   register unsigned int i;
28375fd0b74Schristos 
28475fd0b74Schristos   /* If one (and only one) insn isn't supported by the current architecture,
28575fd0b74Schristos      prefer the one that is.  If neither are supported, but they're both for
28675fd0b74Schristos      the same architecture, continue processing.  Otherwise (both unsupported
28775fd0b74Schristos      and for different architectures), prefer lower numbered arch's (fudged
28875fd0b74Schristos      by comparing the bitmasks).  */
28975fd0b74Schristos   if (op0->architecture & current_arch_mask)
29075fd0b74Schristos     {
29175fd0b74Schristos       if (! (op1->architecture & current_arch_mask))
29275fd0b74Schristos 	return -1;
29375fd0b74Schristos     }
29475fd0b74Schristos   else
29575fd0b74Schristos     {
29675fd0b74Schristos       if (op1->architecture & current_arch_mask)
29775fd0b74Schristos 	return 1;
29875fd0b74Schristos       else if (op0->architecture != op1->architecture)
29975fd0b74Schristos 	return op0->architecture - op1->architecture;
30075fd0b74Schristos     }
30175fd0b74Schristos 
30275fd0b74Schristos   /* If a bit is set in both match and lose, there is something
30375fd0b74Schristos      wrong with the opcode table.  */
30475fd0b74Schristos   if (match0 & lose0)
30575fd0b74Schristos     {
306ede78133Schristos       opcodes_error_handler
30775fd0b74Schristos 	/* xgettext:c-format */
308ede78133Schristos 	(_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
30975fd0b74Schristos 	 op0->name, match0, lose0);
31075fd0b74Schristos       op0->lose &= ~op0->match;
31175fd0b74Schristos       lose0 = op0->lose;
31275fd0b74Schristos     }
31375fd0b74Schristos 
31475fd0b74Schristos   if (match1 & lose1)
31575fd0b74Schristos     {
316ede78133Schristos       opcodes_error_handler
31775fd0b74Schristos 	/* xgettext:c-format */
318ede78133Schristos 	(_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
31975fd0b74Schristos 	 op1->name, match1, lose1);
32075fd0b74Schristos       op1->lose &= ~op1->match;
32175fd0b74Schristos       lose1 = op1->lose;
32275fd0b74Schristos     }
32375fd0b74Schristos 
32475fd0b74Schristos   /* Because the bits that are variable in one opcode are constant in
32575fd0b74Schristos      another, it is important to order the opcodes in the right order.  */
32675fd0b74Schristos   for (i = 0; i < 32; ++i)
32775fd0b74Schristos     {
328012573ebSchristos       unsigned long int x = 1ul << i;
32975fd0b74Schristos       int x0 = (match0 & x) != 0;
33075fd0b74Schristos       int x1 = (match1 & x) != 0;
33175fd0b74Schristos 
33275fd0b74Schristos       if (x0 != x1)
33375fd0b74Schristos 	return x1 - x0;
33475fd0b74Schristos     }
33575fd0b74Schristos 
33675fd0b74Schristos   for (i = 0; i < 32; ++i)
33775fd0b74Schristos     {
338012573ebSchristos       unsigned long int x = 1ul << i;
33975fd0b74Schristos       int x0 = (lose0 & x) != 0;
34075fd0b74Schristos       int x1 = (lose1 & x) != 0;
34175fd0b74Schristos 
34275fd0b74Schristos       if (x0 != x1)
34375fd0b74Schristos 	return x1 - x0;
34475fd0b74Schristos     }
34575fd0b74Schristos 
34675fd0b74Schristos   /* They are functionally equal.  So as long as the opcode table is
34775fd0b74Schristos      valid, we can put whichever one first we want, on aesthetic grounds.  */
34875fd0b74Schristos 
34975fd0b74Schristos   /* Our first aesthetic ground is that aliases defer to real insns.  */
35075fd0b74Schristos   {
35175fd0b74Schristos     int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
35275fd0b74Schristos 
35375fd0b74Schristos     if (alias_diff != 0)
35475fd0b74Schristos       /* Put the one that isn't an alias first.  */
35575fd0b74Schristos       return alias_diff;
35675fd0b74Schristos   }
35775fd0b74Schristos 
35875fd0b74Schristos   /* Except for aliases, two "identical" instructions had
35975fd0b74Schristos      better have the same opcode.  This is a sanity check on the table.  */
36075fd0b74Schristos   i = strcmp (op0->name, op1->name);
36175fd0b74Schristos   if (i)
36275fd0b74Schristos     {
36375fd0b74Schristos       if (op0->flags & F_ALIAS)
36475fd0b74Schristos 	{
36575fd0b74Schristos 	  if (op0->flags & F_PREFERRED)
36675fd0b74Schristos 	    return -1;
36775fd0b74Schristos 	  if (op1->flags & F_PREFERRED)
36875fd0b74Schristos 	    return 1;
36975fd0b74Schristos 
37075fd0b74Schristos 	  /* If they're both aliases, and neither is marked as preferred,
37175fd0b74Schristos 	     be arbitrary.  */
37275fd0b74Schristos 	  return i;
37375fd0b74Schristos 	}
37475fd0b74Schristos       else
375ede78133Schristos 	opcodes_error_handler
37675fd0b74Schristos 	  /* xgettext:c-format */
377ede78133Schristos 	  (_("internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
37875fd0b74Schristos 	   op0->name, op1->name);
37975fd0b74Schristos     }
38075fd0b74Schristos 
38175fd0b74Schristos   /* Fewer arguments are preferred.  */
38275fd0b74Schristos   {
38375fd0b74Schristos     int length_diff = strlen (op0->args) - strlen (op1->args);
38475fd0b74Schristos 
38575fd0b74Schristos     if (length_diff != 0)
38675fd0b74Schristos       /* Put the one with fewer arguments first.  */
38775fd0b74Schristos       return length_diff;
38875fd0b74Schristos   }
38975fd0b74Schristos 
39075fd0b74Schristos   /* Put 1+i before i+1.  */
39175fd0b74Schristos   {
39275fd0b74Schristos     char *p0 = (char *) strchr (op0->args, '+');
39375fd0b74Schristos     char *p1 = (char *) strchr (op1->args, '+');
39475fd0b74Schristos 
39575fd0b74Schristos     if (p0 && p1)
39675fd0b74Schristos       {
39775fd0b74Schristos 	/* There is a plus in both operands.  Note that a plus
39875fd0b74Schristos 	   sign cannot be the first character in args,
39975fd0b74Schristos 	   so the following [-1]'s are valid.  */
40075fd0b74Schristos 	if (p0[-1] == 'i' && p1[1] == 'i')
40175fd0b74Schristos 	  /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
40275fd0b74Schristos 	  return 1;
40375fd0b74Schristos 	if (p0[1] == 'i' && p1[-1] == 'i')
40475fd0b74Schristos 	  /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
40575fd0b74Schristos 	  return -1;
40675fd0b74Schristos       }
40775fd0b74Schristos   }
40875fd0b74Schristos 
40975fd0b74Schristos   /* Put 1,i before i,1.  */
41075fd0b74Schristos   {
41175fd0b74Schristos     int i0 = strncmp (op0->args, "i,1", 3) == 0;
41275fd0b74Schristos     int i1 = strncmp (op1->args, "i,1", 3) == 0;
41375fd0b74Schristos 
41475fd0b74Schristos     if (i0 ^ i1)
41575fd0b74Schristos       return i0 - i1;
41675fd0b74Schristos   }
41775fd0b74Schristos 
41875fd0b74Schristos   /* They are, as far as we can tell, identical.
41975fd0b74Schristos      Since qsort may have rearranged the table partially, there is
42075fd0b74Schristos      no way to tell which one was first in the opcode table as
42175fd0b74Schristos      written, so just say there are equal.  */
42275fd0b74Schristos   /* ??? This is no longer true now that we sort a vector of pointers,
42375fd0b74Schristos      not the table itself.  */
42475fd0b74Schristos   return 0;
42575fd0b74Schristos }
42675fd0b74Schristos 
42775fd0b74Schristos /* Build a hash table from the opcode table.
42875fd0b74Schristos    OPCODE_TABLE is a sorted list of pointers into the opcode table.  */
42975fd0b74Schristos 
43075fd0b74Schristos static void
build_hash_table(const sparc_opcode ** opcode_table,sparc_opcode_hash ** hash_table,int num_opcodes)43175fd0b74Schristos build_hash_table (const sparc_opcode **opcode_table,
43275fd0b74Schristos 		  sparc_opcode_hash **hash_table,
43375fd0b74Schristos 		  int num_opcodes)
43475fd0b74Schristos {
43575fd0b74Schristos   int i;
43675fd0b74Schristos   int hash_count[HASH_SIZE];
43775fd0b74Schristos   static sparc_opcode_hash *hash_buf = NULL;
43875fd0b74Schristos 
43975fd0b74Schristos   /* Start at the end of the table and work backwards so that each
44075fd0b74Schristos      chain is sorted.  */
44175fd0b74Schristos 
44275fd0b74Schristos   memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0]));
44375fd0b74Schristos   memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0]));
44475fd0b74Schristos   free (hash_buf);
44575fd0b74Schristos   hash_buf = xmalloc (sizeof (* hash_buf) * num_opcodes);
44675fd0b74Schristos   for (i = num_opcodes - 1; i >= 0; --i)
44775fd0b74Schristos     {
44875fd0b74Schristos       int hash = HASH_INSN (opcode_table[i]->match);
44975fd0b74Schristos       sparc_opcode_hash *h = &hash_buf[i];
45075fd0b74Schristos 
45175fd0b74Schristos       h->next = hash_table[hash];
45275fd0b74Schristos       h->opcode = opcode_table[i];
45375fd0b74Schristos       hash_table[hash] = h;
45475fd0b74Schristos       ++hash_count[hash];
45575fd0b74Schristos     }
45675fd0b74Schristos 
45775fd0b74Schristos #if 0 /* for debugging */
45875fd0b74Schristos   {
45975fd0b74Schristos     int min_count = num_opcodes, max_count = 0;
46075fd0b74Schristos     int total;
46175fd0b74Schristos 
46275fd0b74Schristos     for (i = 0; i < HASH_SIZE; ++i)
46375fd0b74Schristos       {
46475fd0b74Schristos         if (hash_count[i] < min_count)
46575fd0b74Schristos 	  min_count = hash_count[i];
46675fd0b74Schristos 	if (hash_count[i] > max_count)
46775fd0b74Schristos 	  max_count = hash_count[i];
46875fd0b74Schristos 	total += hash_count[i];
46975fd0b74Schristos       }
47075fd0b74Schristos 
47175fd0b74Schristos     printf ("Opcode hash table stats: min %d, max %d, ave %f\n",
47275fd0b74Schristos 	    min_count, max_count, (double) total / HASH_SIZE);
47375fd0b74Schristos   }
47475fd0b74Schristos #endif
47575fd0b74Schristos }
47675fd0b74Schristos 
47775fd0b74Schristos /* Print one instruction from MEMADDR on INFO->STREAM.
47875fd0b74Schristos 
47975fd0b74Schristos    We suffix the instruction with a comment that gives the absolute
48075fd0b74Schristos    address involved, as well as its symbolic form, if the instruction
48175fd0b74Schristos    is preceded by a findable `sethi' and it either adds an immediate
48275fd0b74Schristos    displacement to that register, or it is an `add' or `or' instruction
48375fd0b74Schristos    on that register.  */
48475fd0b74Schristos 
48575fd0b74Schristos int
print_insn_sparc(bfd_vma memaddr,disassemble_info * info)48675fd0b74Schristos print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
48775fd0b74Schristos {
48875fd0b74Schristos   FILE *stream = info->stream;
48975fd0b74Schristos   bfd_byte buffer[4];
49075fd0b74Schristos   unsigned long insn;
49175fd0b74Schristos   sparc_opcode_hash *op;
49275fd0b74Schristos   /* Nonzero of opcode table has been initialized.  */
49375fd0b74Schristos   static int opcodes_initialized = 0;
49475fd0b74Schristos   /* bfd mach number of last call.  */
49575fd0b74Schristos   static unsigned long current_mach = 0;
49675fd0b74Schristos   bfd_vma (*getword) (const void *);
49775fd0b74Schristos 
49875fd0b74Schristos   if (!opcodes_initialized
49975fd0b74Schristos       || info->mach != current_mach)
50075fd0b74Schristos     {
50175fd0b74Schristos       int i;
50275fd0b74Schristos 
50375fd0b74Schristos       current_arch_mask = compute_arch_mask (info->mach);
50475fd0b74Schristos 
50575fd0b74Schristos       if (!opcodes_initialized)
50675fd0b74Schristos 	sorted_opcodes =
50775fd0b74Schristos 	  xmalloc (sparc_num_opcodes * sizeof (sparc_opcode *));
50875fd0b74Schristos       /* Reset the sorted table so we can resort it.  */
50975fd0b74Schristos       for (i = 0; i < sparc_num_opcodes; ++i)
51075fd0b74Schristos 	sorted_opcodes[i] = &sparc_opcodes[i];
51175fd0b74Schristos       qsort ((char *) sorted_opcodes, sparc_num_opcodes,
51275fd0b74Schristos 	     sizeof (sorted_opcodes[0]), compare_opcodes);
51375fd0b74Schristos 
51475fd0b74Schristos       build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);
51575fd0b74Schristos       current_mach = info->mach;
51675fd0b74Schristos       opcodes_initialized = 1;
51775fd0b74Schristos     }
51875fd0b74Schristos 
51975fd0b74Schristos   {
52075fd0b74Schristos     int status =
52175fd0b74Schristos       (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
52275fd0b74Schristos 
52375fd0b74Schristos     if (status != 0)
52475fd0b74Schristos       {
52575fd0b74Schristos 	(*info->memory_error_func) (status, memaddr, info);
52675fd0b74Schristos 	return -1;
52775fd0b74Schristos       }
52875fd0b74Schristos   }
52975fd0b74Schristos 
53075fd0b74Schristos   /* On SPARClite variants such as DANlite (sparc86x), instructions
53175fd0b74Schristos      are always big-endian even when the machine is in little-endian mode.  */
53275fd0b74Schristos   if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite)
53375fd0b74Schristos     getword = bfd_getb32;
53475fd0b74Schristos   else
53575fd0b74Schristos     getword = bfd_getl32;
53675fd0b74Schristos 
53775fd0b74Schristos   insn = getword (buffer);
53875fd0b74Schristos 
53975fd0b74Schristos   info->insn_info_valid = 1;			/* We do return this info.  */
54075fd0b74Schristos   info->insn_type = dis_nonbranch;		/* Assume non branch insn.  */
54175fd0b74Schristos   info->branch_delay_insns = 0;			/* Assume no delay.  */
54275fd0b74Schristos   info->target = 0;				/* Assume no target known.  */
54375fd0b74Schristos 
54475fd0b74Schristos   for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
54575fd0b74Schristos     {
54675fd0b74Schristos       const sparc_opcode *opcode = op->opcode;
54775fd0b74Schristos 
54875fd0b74Schristos       /* If the insn isn't supported by the current architecture, skip it.  */
54975fd0b74Schristos       if (! (opcode->architecture & current_arch_mask))
55075fd0b74Schristos 	continue;
55175fd0b74Schristos 
55275fd0b74Schristos       if ((opcode->match & insn) == opcode->match
55375fd0b74Schristos 	  && (opcode->lose & insn) == 0)
55475fd0b74Schristos 	{
55575fd0b74Schristos 	  /* Nonzero means that we have found an instruction which has
55675fd0b74Schristos 	     the effect of adding or or'ing the imm13 field to rs1.  */
55775fd0b74Schristos 	  int imm_added_to_rs1 = 0;
55875fd0b74Schristos 	  int imm_ored_to_rs1 = 0;
55975fd0b74Schristos 
56075fd0b74Schristos 	  /* Nonzero means that we have found a plus sign in the args
56175fd0b74Schristos 	     field of the opcode table.  */
56275fd0b74Schristos 	  int found_plus = 0;
56375fd0b74Schristos 
56475fd0b74Schristos 	  /* Nonzero means we have an annulled branch.  */
56575fd0b74Schristos 	  int is_annulled = 0;
56675fd0b74Schristos 
56775fd0b74Schristos 	  /* Do we have an `add' or `or' instruction combining an
56875fd0b74Schristos              immediate with rs1?  */
56975fd0b74Schristos 	  if (opcode->match == 0x80102000) /* or */
57075fd0b74Schristos 	    imm_ored_to_rs1 = 1;
57175fd0b74Schristos 	  if (opcode->match == 0x80002000) /* add */
57275fd0b74Schristos 	    imm_added_to_rs1 = 1;
57375fd0b74Schristos 
57475fd0b74Schristos 	  if (X_RS1 (insn) != X_RD (insn)
57575fd0b74Schristos 	      && strchr (opcode->args, 'r') != 0)
57675fd0b74Schristos 	      /* Can't do simple format if source and dest are different.  */
57775fd0b74Schristos 	      continue;
57875fd0b74Schristos 	  if (X_RS2 (insn) != X_RD (insn)
57975fd0b74Schristos 	      && strchr (opcode->args, 'O') != 0)
58075fd0b74Schristos 	      /* Can't do simple format if source and dest are different.  */
58175fd0b74Schristos 	      continue;
58275fd0b74Schristos 
58375fd0b74Schristos 	  (*info->fprintf_func) (stream, "%s", opcode->name);
58475fd0b74Schristos 
58575fd0b74Schristos 	  {
58675fd0b74Schristos 	    const char *s;
58775fd0b74Schristos 
58875fd0b74Schristos 	    if (opcode->args[0] != ',')
58975fd0b74Schristos 	      (*info->fprintf_func) (stream, " ");
59075fd0b74Schristos 
59175fd0b74Schristos 	    for (s = opcode->args; *s != '\0'; ++s)
59275fd0b74Schristos 	      {
59375fd0b74Schristos 		while (*s == ',')
59475fd0b74Schristos 		  {
59575fd0b74Schristos 		    (*info->fprintf_func) (stream, ",");
59675fd0b74Schristos 		    ++s;
59775fd0b74Schristos 		    switch (*s)
59875fd0b74Schristos 		      {
59975fd0b74Schristos 		      case 'a':
60075fd0b74Schristos 			(*info->fprintf_func) (stream, "a");
60175fd0b74Schristos 			is_annulled = 1;
60275fd0b74Schristos 			++s;
60375fd0b74Schristos 			continue;
60475fd0b74Schristos 		      case 'N':
60575fd0b74Schristos 			(*info->fprintf_func) (stream, "pn");
60675fd0b74Schristos 			++s;
60775fd0b74Schristos 			continue;
60875fd0b74Schristos 
60975fd0b74Schristos 		      case 'T':
61075fd0b74Schristos 			(*info->fprintf_func) (stream, "pt");
61175fd0b74Schristos 			++s;
61275fd0b74Schristos 			continue;
61375fd0b74Schristos 
61475fd0b74Schristos 		      default:
61575fd0b74Schristos 			break;
61675fd0b74Schristos 		      }
61775fd0b74Schristos 		  }
61875fd0b74Schristos 
61975fd0b74Schristos 		(*info->fprintf_func) (stream, " ");
62075fd0b74Schristos 
62175fd0b74Schristos 		switch (*s)
62275fd0b74Schristos 		  {
62375fd0b74Schristos 		  case '+':
62475fd0b74Schristos 		    found_plus = 1;
62575fd0b74Schristos 		    /* Fall through.  */
62675fd0b74Schristos 
62775fd0b74Schristos 		  default:
62875fd0b74Schristos 		    (*info->fprintf_func) (stream, "%c", *s);
62975fd0b74Schristos 		    break;
63075fd0b74Schristos 
63175fd0b74Schristos 		  case '#':
63275fd0b74Schristos 		    (*info->fprintf_func) (stream, "0");
63375fd0b74Schristos 		    break;
63475fd0b74Schristos 
63575fd0b74Schristos #define	reg(n)	(*info->fprintf_func) (stream, "%%%s", reg_names[n])
63675fd0b74Schristos 		  case '1':
63775fd0b74Schristos 		  case 'r':
63875fd0b74Schristos 		    reg (X_RS1 (insn));
63975fd0b74Schristos 		    break;
64075fd0b74Schristos 
64175fd0b74Schristos 		  case '2':
64275fd0b74Schristos 		  case 'O':
64375fd0b74Schristos 		    reg (X_RS2 (insn));
64475fd0b74Schristos 		    break;
64575fd0b74Schristos 
64675fd0b74Schristos 		  case 'd':
64775fd0b74Schristos 		    reg (X_RD (insn));
64875fd0b74Schristos 		    break;
64975fd0b74Schristos #undef	reg
65075fd0b74Schristos 
65175fd0b74Schristos #define	freg(n)		(*info->fprintf_func) (stream, "%%%s", freg_names[n])
65275fd0b74Schristos #define	fregx(n)	(*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
65375fd0b74Schristos 		  case 'e':
65475fd0b74Schristos 		    freg (X_RS1 (insn));
65575fd0b74Schristos 		    break;
65675fd0b74Schristos 		  case 'v':	/* Double/even.  */
65775fd0b74Schristos 		  case 'V':	/* Quad/multiple of 4.  */
658ede78133Schristos                   case ';':	/* Double/even multiple of 8 doubles.  */
65975fd0b74Schristos 		    fregx (X_RS1 (insn));
66075fd0b74Schristos 		    break;
66175fd0b74Schristos 
66275fd0b74Schristos 		  case 'f':
66375fd0b74Schristos 		    freg (X_RS2 (insn));
66475fd0b74Schristos 		    break;
66575fd0b74Schristos 		  case 'B':	/* Double/even.  */
66675fd0b74Schristos 		  case 'R':	/* Quad/multiple of 4.  */
667ede78133Schristos                   case ':':	/* Double/even multiple of 8 doubles.  */
66875fd0b74Schristos 		    fregx (X_RS2 (insn));
66975fd0b74Schristos 		    break;
67075fd0b74Schristos 
67175fd0b74Schristos 		  case '4':
67275fd0b74Schristos 		    freg (X_RS3 (insn));
67375fd0b74Schristos 		    break;
67475fd0b74Schristos 		  case '5':	/* Double/even.  */
67575fd0b74Schristos 		    fregx (X_RS3 (insn));
67675fd0b74Schristos 		    break;
67775fd0b74Schristos 
67875fd0b74Schristos 		  case 'g':
67975fd0b74Schristos 		    freg (X_RD (insn));
68075fd0b74Schristos 		    break;
68175fd0b74Schristos 		  case 'H':	/* Double/even.  */
68275fd0b74Schristos 		  case 'J':	/* Quad/multiple of 4.  */
68375fd0b74Schristos 		  case '}':     /* Double/even.  */
68475fd0b74Schristos 		    fregx (X_RD (insn));
68575fd0b74Schristos 		    break;
686ede78133Schristos 
687ede78133Schristos                   case '^':	/* Double/even multiple of 8 doubles.  */
688ede78133Schristos                     fregx (X_RD (insn) & ~0x6);
689ede78133Schristos                     break;
690ede78133Schristos 
691ede78133Schristos                   case '\'':	/* Double/even in FPCMPSHL.  */
692ede78133Schristos                     fregx (X_RS2 (insn | 0x11));
693ede78133Schristos                     break;
694ede78133Schristos 
69575fd0b74Schristos #undef	freg
69675fd0b74Schristos #undef	fregx
69775fd0b74Schristos 
69875fd0b74Schristos #define	creg(n)	(*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
69975fd0b74Schristos 		  case 'b':
70075fd0b74Schristos 		    creg (X_RS1 (insn));
70175fd0b74Schristos 		    break;
70275fd0b74Schristos 
70375fd0b74Schristos 		  case 'c':
70475fd0b74Schristos 		    creg (X_RS2 (insn));
70575fd0b74Schristos 		    break;
70675fd0b74Schristos 
70775fd0b74Schristos 		  case 'D':
70875fd0b74Schristos 		    creg (X_RD (insn));
70975fd0b74Schristos 		    break;
71075fd0b74Schristos #undef	creg
71175fd0b74Schristos 
71275fd0b74Schristos 		  case 'h':
71375fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%hi(%#x)",
714012573ebSchristos 					   (unsigned) X_IMM22 (insn) << 10);
71575fd0b74Schristos 		    break;
71675fd0b74Schristos 
71775fd0b74Schristos 		  case 'i':	/* 13 bit immediate.  */
71875fd0b74Schristos 		  case 'I':	/* 11 bit immediate.  */
71975fd0b74Schristos 		  case 'j':	/* 10 bit immediate.  */
72075fd0b74Schristos 		    {
72175fd0b74Schristos 		      int imm;
72275fd0b74Schristos 
72375fd0b74Schristos 		      if (*s == 'i')
72475fd0b74Schristos 		        imm = X_SIMM (insn, 13);
72575fd0b74Schristos 		      else if (*s == 'I')
72675fd0b74Schristos 			imm = X_SIMM (insn, 11);
72775fd0b74Schristos 		      else
72875fd0b74Schristos 			imm = X_SIMM (insn, 10);
72975fd0b74Schristos 
73075fd0b74Schristos 		      /* Check to see whether we have a 1+i, and take
73175fd0b74Schristos 			 note of that fact.
73275fd0b74Schristos 
73375fd0b74Schristos 			 Note: because of the way we sort the table,
73475fd0b74Schristos 			 we will be matching 1+i rather than i+1,
73575fd0b74Schristos 			 so it is OK to assume that i is after +,
73675fd0b74Schristos 			 not before it.  */
73775fd0b74Schristos 		      if (found_plus)
73875fd0b74Schristos 			imm_added_to_rs1 = 1;
73975fd0b74Schristos 
74075fd0b74Schristos 		      if (imm <= 9)
74175fd0b74Schristos 			(*info->fprintf_func) (stream, "%d", imm);
74275fd0b74Schristos 		      else
74375fd0b74Schristos 			(*info->fprintf_func) (stream, "%#x", imm);
74475fd0b74Schristos 		    }
74575fd0b74Schristos 		    break;
74675fd0b74Schristos 
74775fd0b74Schristos 		  case ')':	/* 5 bit unsigned immediate from RS3.  */
74875fd0b74Schristos 		    (info->fprintf_func) (stream, "%#x", (unsigned int) X_RS3 (insn));
74975fd0b74Schristos 		    break;
75075fd0b74Schristos 
75175fd0b74Schristos 		  case 'X':	/* 5 bit unsigned immediate.  */
75275fd0b74Schristos 		  case 'Y':	/* 6 bit unsigned immediate.  */
75375fd0b74Schristos 		    {
75475fd0b74Schristos 		      int imm = X_IMM (insn, *s == 'X' ? 5 : 6);
75575fd0b74Schristos 
75675fd0b74Schristos 		      if (imm <= 9)
75775fd0b74Schristos 			(info->fprintf_func) (stream, "%d", imm);
75875fd0b74Schristos 		      else
75975fd0b74Schristos 			(info->fprintf_func) (stream, "%#x", (unsigned) imm);
76075fd0b74Schristos 		    }
76175fd0b74Schristos 		    break;
76275fd0b74Schristos 
76375fd0b74Schristos 		  case '3':
76475fd0b74Schristos 		    (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3));
76575fd0b74Schristos 		    break;
76675fd0b74Schristos 
76775fd0b74Schristos 		  case 'K':
76875fd0b74Schristos 		    {
76975fd0b74Schristos 		      int mask = X_MEMBAR (insn);
77075fd0b74Schristos 		      int bit = 0x40, printed_one = 0;
77175fd0b74Schristos 		      const char *name;
77275fd0b74Schristos 
77375fd0b74Schristos 		      if (mask == 0)
77475fd0b74Schristos 			(info->fprintf_func) (stream, "0");
77575fd0b74Schristos 		      else
77675fd0b74Schristos 			while (bit)
77775fd0b74Schristos 			  {
77875fd0b74Schristos 			    if (mask & bit)
77975fd0b74Schristos 			      {
78075fd0b74Schristos 				if (printed_one)
78175fd0b74Schristos 				  (info->fprintf_func) (stream, "|");
78275fd0b74Schristos 				name = sparc_decode_membar (bit);
78375fd0b74Schristos 				(info->fprintf_func) (stream, "%s", name);
78475fd0b74Schristos 				printed_one = 1;
78575fd0b74Schristos 			      }
78675fd0b74Schristos 			    bit >>= 1;
78775fd0b74Schristos 			  }
78875fd0b74Schristos 		      break;
78975fd0b74Schristos 		    }
79075fd0b74Schristos 
79175fd0b74Schristos 		  case '=':
79275fd0b74Schristos 		    info->target = memaddr + SEX (X_DISP10 (insn), 10) * 4;
79375fd0b74Schristos 		    (*info->print_address_func) (info->target, info);
79475fd0b74Schristos 		    break;
79575fd0b74Schristos 
79675fd0b74Schristos 		  case 'k':
79775fd0b74Schristos 		    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
79875fd0b74Schristos 		    (*info->print_address_func) (info->target, info);
79975fd0b74Schristos 		    break;
80075fd0b74Schristos 
80175fd0b74Schristos 		  case 'G':
80275fd0b74Schristos 		    info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;
80375fd0b74Schristos 		    (*info->print_address_func) (info->target, info);
80475fd0b74Schristos 		    break;
80575fd0b74Schristos 
80675fd0b74Schristos 		  case '6':
80775fd0b74Schristos 		  case '7':
80875fd0b74Schristos 		  case '8':
80975fd0b74Schristos 		  case '9':
81075fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
81175fd0b74Schristos 		    break;
81275fd0b74Schristos 
81375fd0b74Schristos 		  case 'z':
81475fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%icc");
81575fd0b74Schristos 		    break;
81675fd0b74Schristos 
81775fd0b74Schristos 		  case 'Z':
81875fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%xcc");
81975fd0b74Schristos 		    break;
82075fd0b74Schristos 
82175fd0b74Schristos 		  case 'E':
82275fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%ccr");
82375fd0b74Schristos 		    break;
82475fd0b74Schristos 
82575fd0b74Schristos 		  case 's':
82675fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%fprs");
82775fd0b74Schristos 		    break;
82875fd0b74Schristos 
82975fd0b74Schristos 		  case '{':
83075fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%mcdper");
83175fd0b74Schristos 		    break;
83275fd0b74Schristos 
833ede78133Schristos                   case '&':
834ede78133Schristos                     (*info->fprintf_func) (stream, "%%entropy");
835ede78133Schristos                     break;
836ede78133Schristos 
83775fd0b74Schristos 		  case 'o':
83875fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%asi");
83975fd0b74Schristos 		    break;
84075fd0b74Schristos 
84175fd0b74Schristos 		  case 'W':
84275fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%tick");
84375fd0b74Schristos 		    break;
84475fd0b74Schristos 
84575fd0b74Schristos 		  case 'P':
84675fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%pc");
84775fd0b74Schristos 		    break;
84875fd0b74Schristos 
84975fd0b74Schristos 		  case '?':
85075fd0b74Schristos 		    if (X_RS1 (insn) == 31)
85175fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%ver");
85275fd0b74Schristos 		    else if (X_RS1 (insn) == 23)
85375fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%pmcdper");
85475fd0b74Schristos 		    else if ((unsigned) X_RS1 (insn) < 17)
85575fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
85675fd0b74Schristos 					     v9_priv_reg_names[X_RS1 (insn)]);
85775fd0b74Schristos 		    else
85875fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
85975fd0b74Schristos 		    break;
86075fd0b74Schristos 
86175fd0b74Schristos 		  case '!':
86275fd0b74Schristos                     if (X_RD (insn) == 31)
86375fd0b74Schristos                       (*info->fprintf_func) (stream, "%%ver");
86475fd0b74Schristos 		    else if (X_RD (insn) == 23)
86575fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%pmcdper");
86675fd0b74Schristos 		    else if ((unsigned) X_RD (insn) < 17)
86775fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
86875fd0b74Schristos 					     v9_priv_reg_names[X_RD (insn)]);
86975fd0b74Schristos 		    else
87075fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
87175fd0b74Schristos 		    break;
87275fd0b74Schristos 
87375fd0b74Schristos 		  case '$':
87475fd0b74Schristos 		    if ((unsigned) X_RS1 (insn) < 32)
87575fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
87675fd0b74Schristos 					     v9_hpriv_reg_names[X_RS1 (insn)]);
87775fd0b74Schristos 		    else
87875fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
87975fd0b74Schristos 		    break;
88075fd0b74Schristos 
88175fd0b74Schristos 		  case '%':
88275fd0b74Schristos 		    if ((unsigned) X_RD (insn) < 32)
88375fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
88475fd0b74Schristos 					     v9_hpriv_reg_names[X_RD (insn)]);
88575fd0b74Schristos 		    else
88675fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
88775fd0b74Schristos 		    break;
88875fd0b74Schristos 
88975fd0b74Schristos 		  case '/':
89075fd0b74Schristos 		    if (X_RS1 (insn) < 16 || X_RS1 (insn) > 28)
89175fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
89275fd0b74Schristos 		    else
89375fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
89475fd0b74Schristos 					     v9a_asr_reg_names[X_RS1 (insn)-16]);
89575fd0b74Schristos 		    break;
89675fd0b74Schristos 
89775fd0b74Schristos 		  case '_':
89875fd0b74Schristos 		    if (X_RD (insn) < 16 || X_RD (insn) > 28)
89975fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%reserved");
90075fd0b74Schristos 		    else
90175fd0b74Schristos 		      (*info->fprintf_func) (stream, "%%%s",
90275fd0b74Schristos 					     v9a_asr_reg_names[X_RD (insn)-16]);
90375fd0b74Schristos 		    break;
90475fd0b74Schristos 
90575fd0b74Schristos 		  case '*':
90675fd0b74Schristos 		    {
90775fd0b74Schristos 		      const char *name = sparc_decode_prefetch (X_RD (insn));
90875fd0b74Schristos 
90975fd0b74Schristos 		      if (name)
91075fd0b74Schristos 			(*info->fprintf_func) (stream, "%s", name);
91175fd0b74Schristos 		      else
91275fd0b74Schristos 			(*info->fprintf_func) (stream, "%ld", X_RD (insn));
91375fd0b74Schristos 		      break;
91475fd0b74Schristos 		    }
91575fd0b74Schristos 
91675fd0b74Schristos 		  case 'M':
91775fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn));
91875fd0b74Schristos 		    break;
91975fd0b74Schristos 
92075fd0b74Schristos 		  case 'm':
92175fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn));
92275fd0b74Schristos 		    break;
92375fd0b74Schristos 
92475fd0b74Schristos 		  case 'L':
92575fd0b74Schristos 		    info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4;
92675fd0b74Schristos 		    (*info->print_address_func) (info->target, info);
92775fd0b74Schristos 		    break;
92875fd0b74Schristos 
92975fd0b74Schristos 		  case 'n':
93075fd0b74Schristos 		    (*info->fprintf_func)
93175fd0b74Schristos 		      (stream, "%#x", SEX (X_DISP22 (insn), 22));
93275fd0b74Schristos 		    break;
93375fd0b74Schristos 
93475fd0b74Schristos 		  case 'l':
93575fd0b74Schristos 		    info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4;
93675fd0b74Schristos 		    (*info->print_address_func) (info->target, info);
93775fd0b74Schristos 		    break;
93875fd0b74Schristos 
93975fd0b74Schristos 		  case 'A':
94075fd0b74Schristos 		    {
94175fd0b74Schristos 		      const char *name = sparc_decode_asi (X_ASI (insn));
94275fd0b74Schristos 
94375fd0b74Schristos 		      if (name)
94475fd0b74Schristos 			(*info->fprintf_func) (stream, "%s", name);
94575fd0b74Schristos 		      else
94675fd0b74Schristos 			(*info->fprintf_func) (stream, "(%ld)", X_ASI (insn));
94775fd0b74Schristos 		      break;
94875fd0b74Schristos 		    }
94975fd0b74Schristos 
95075fd0b74Schristos 		  case 'C':
95175fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%csr");
95275fd0b74Schristos 		    break;
95375fd0b74Schristos 
95475fd0b74Schristos 		  case 'F':
95575fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%fsr");
95675fd0b74Schristos 		    break;
95775fd0b74Schristos 
95875fd0b74Schristos 		  case '(':
95975fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%efsr");
96075fd0b74Schristos 		    break;
96175fd0b74Schristos 
96275fd0b74Schristos 		  case 'p':
96375fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%psr");
96475fd0b74Schristos 		    break;
96575fd0b74Schristos 
96675fd0b74Schristos 		  case 'q':
96775fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%fq");
96875fd0b74Schristos 		    break;
96975fd0b74Schristos 
97075fd0b74Schristos 		  case 'Q':
97175fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%cq");
97275fd0b74Schristos 		    break;
97375fd0b74Schristos 
97475fd0b74Schristos 		  case 't':
97575fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%tbr");
97675fd0b74Schristos 		    break;
97775fd0b74Schristos 
97875fd0b74Schristos 		  case 'w':
97975fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%wim");
98075fd0b74Schristos 		    break;
98175fd0b74Schristos 
98275fd0b74Schristos 		  case 'x':
98375fd0b74Schristos 		    (*info->fprintf_func) (stream, "%ld",
98475fd0b74Schristos 					   ((X_LDST_I (insn) << 8)
98575fd0b74Schristos 					    + X_ASI (insn)));
98675fd0b74Schristos 		    break;
98775fd0b74Schristos 
988ede78133Schristos                   case '|': /* 2-bit immediate  */
989ede78133Schristos                     (*info->fprintf_func) (stream, "%ld", X_IMM2 (insn));
990ede78133Schristos                     break;
991ede78133Schristos 
99275fd0b74Schristos 		  case 'y':
99375fd0b74Schristos 		    (*info->fprintf_func) (stream, "%%y");
99475fd0b74Schristos 		    break;
99575fd0b74Schristos 
99675fd0b74Schristos 		  case 'u':
99775fd0b74Schristos 		  case 'U':
99875fd0b74Schristos 		    {
99975fd0b74Schristos 		      int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);
100075fd0b74Schristos 		      const char *name = sparc_decode_sparclet_cpreg (val);
100175fd0b74Schristos 
100275fd0b74Schristos 		      if (name)
100375fd0b74Schristos 			(*info->fprintf_func) (stream, "%s", name);
100475fd0b74Schristos 		      else
100575fd0b74Schristos 			(*info->fprintf_func) (stream, "%%cpreg(%d)", val);
100675fd0b74Schristos 		      break;
100775fd0b74Schristos 		    }
100875fd0b74Schristos 		  }
100975fd0b74Schristos 	      }
101075fd0b74Schristos 	  }
101175fd0b74Schristos 
101275fd0b74Schristos 	  /* If we are adding or or'ing something to rs1, then
101375fd0b74Schristos 	     check to see whether the previous instruction was
101475fd0b74Schristos 	     a sethi to the same register as in the sethi.
101575fd0b74Schristos 	     If so, attempt to print the result of the add or
101675fd0b74Schristos 	     or (in this context add and or do the same thing)
101775fd0b74Schristos 	     and its symbolic value.  */
101875fd0b74Schristos 	  if (imm_ored_to_rs1 || imm_added_to_rs1)
101975fd0b74Schristos 	    {
102075fd0b74Schristos 	      unsigned long prev_insn;
102175fd0b74Schristos 	      int errcode;
102275fd0b74Schristos 
102375fd0b74Schristos 	      if (memaddr >= 4)
102475fd0b74Schristos 		errcode =
102575fd0b74Schristos 		  (*info->read_memory_func)
102675fd0b74Schristos 		  (memaddr - 4, buffer, sizeof (buffer), info);
102775fd0b74Schristos 	      else
102875fd0b74Schristos 		errcode = 1;
102975fd0b74Schristos 
103075fd0b74Schristos 	      prev_insn = getword (buffer);
103175fd0b74Schristos 
103275fd0b74Schristos 	      if (errcode == 0)
103375fd0b74Schristos 		{
103475fd0b74Schristos 		  /* If it is a delayed branch, we need to look at the
103575fd0b74Schristos 		     instruction before the delayed branch.  This handles
103675fd0b74Schristos 		     sequences such as:
103775fd0b74Schristos 
103875fd0b74Schristos 		     sethi %o1, %hi(_foo), %o1
103975fd0b74Schristos 		     call _printf
104075fd0b74Schristos 		     or %o1, %lo(_foo), %o1  */
104175fd0b74Schristos 
104275fd0b74Schristos 		  if (is_delayed_branch (prev_insn))
104375fd0b74Schristos 		    {
104475fd0b74Schristos 		      if (memaddr >= 8)
104575fd0b74Schristos 			errcode = (*info->read_memory_func)
104675fd0b74Schristos 			  (memaddr - 8, buffer, sizeof (buffer), info);
104775fd0b74Schristos 		      else
104875fd0b74Schristos 			errcode = 1;
104975fd0b74Schristos 
105075fd0b74Schristos 		      prev_insn = getword (buffer);
105175fd0b74Schristos 		    }
105275fd0b74Schristos 		}
105375fd0b74Schristos 
105475fd0b74Schristos 	      /* If there was a problem reading memory, then assume
105575fd0b74Schristos 		 the previous instruction was not sethi.  */
105675fd0b74Schristos 	      if (errcode == 0)
105775fd0b74Schristos 		{
105875fd0b74Schristos 		  /* Is it sethi to the same register?  */
105975fd0b74Schristos 		  if ((prev_insn & 0xc1c00000) == 0x01000000
106075fd0b74Schristos 		      && X_RD (prev_insn) == X_RS1 (insn))
106175fd0b74Schristos 		    {
106275fd0b74Schristos 		      (*info->fprintf_func) (stream, "\t! ");
1063012573ebSchristos 		      info->target = (unsigned) X_IMM22 (prev_insn) << 10;
106475fd0b74Schristos 		      if (imm_added_to_rs1)
106575fd0b74Schristos 			info->target += X_SIMM (insn, 13);
106675fd0b74Schristos 		      else
106775fd0b74Schristos 			info->target |= X_SIMM (insn, 13);
106875fd0b74Schristos 		      (*info->print_address_func) (info->target, info);
106975fd0b74Schristos 		      info->insn_type = dis_dref;
107075fd0b74Schristos 		      info->data_size = 4;  /* FIXME!!! */
107175fd0b74Schristos 		    }
107275fd0b74Schristos 		}
107375fd0b74Schristos 	    }
107475fd0b74Schristos 
107575fd0b74Schristos 	  if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
107675fd0b74Schristos 	    {
107775fd0b74Schristos 	      /* FIXME -- check is_annulled flag.  */
107875fd0b74Schristos 	      (void) is_annulled;
107975fd0b74Schristos 	      if (opcode->flags & F_UNBR)
108075fd0b74Schristos 		info->insn_type = dis_branch;
108175fd0b74Schristos 	      if (opcode->flags & F_CONDBR)
108275fd0b74Schristos 		info->insn_type = dis_condbranch;
108375fd0b74Schristos 	      if (opcode->flags & F_JSR)
108475fd0b74Schristos 		info->insn_type = dis_jsr;
108575fd0b74Schristos 	      if (opcode->flags & F_DELAYED)
108675fd0b74Schristos 		info->branch_delay_insns = 1;
108775fd0b74Schristos 	    }
108875fd0b74Schristos 
108975fd0b74Schristos 	  return sizeof (buffer);
109075fd0b74Schristos 	}
109175fd0b74Schristos     }
109275fd0b74Schristos 
109375fd0b74Schristos   info->insn_type = dis_noninsn;	/* Mark as non-valid instruction.  */
109475fd0b74Schristos   (*info->fprintf_func) (stream, _("unknown"));
109575fd0b74Schristos   return sizeof (buffer);
109675fd0b74Schristos }
1097