* sparc-dis.c (HASH_SIZE, HASH_INSN): Define.
(opcode_bits, opcode_hash_table, sparc64_p): New variables. (opcodes_initialized): Renamed from opcodes_sorted. (build_hash_table): New function. (is_delayed_branch): Use hash table. (print_insn): Renamed from print_insn_sparc, made static. Build and use hash table. (print_insn_sparc, print_insn_sparc64): New functions. (compare_opcodes): If !sparc64, move sparc64 opcodes to end, and vice-versa if sparc64. * sparc-opc.c (all non-v9 insns): Use flag F_NOTV9 instead of F_ALIAS.
This commit is contained in:
parent
97eab8a17c
commit
f069afb4eb
3 changed files with 557 additions and 283 deletions
|
@ -1,3 +1,42 @@
|
|||
Wed Aug 2 08:23:38 1995 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* sparc-dis.c (HASH_SIZE, HASH_INSN): Define.
|
||||
(opcode_bits, opcode_hash_table, sparc64_p): New variables.
|
||||
(opcodes_initialized): Renamed from opcodes_sorted.
|
||||
(build_hash_table): New function.
|
||||
(is_delayed_branch): Use hash table.
|
||||
(print_insn): Renamed from print_insn_sparc, made static.
|
||||
Build and use hash table.
|
||||
(print_insn_sparc, print_insn_sparc64): New functions.
|
||||
(compare_opcodes): If !sparc64, move sparc64 opcodes to end,
|
||||
and vice-versa if sparc64.
|
||||
* sparc-opc.c (all non-v9 insns): Use flag F_NOTV9 instead of F_ALIAS.
|
||||
|
||||
Tue Aug 1 00:12:49 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* sh-dis.c (print_insn_shx): Remove unused local dslot. Use
|
||||
print_address_func for A_BDISP12 and A_BDISP8. Correct test which
|
||||
avoids printing a delay slot in a delay slot.
|
||||
* sh-opc.h (sh_table): Fully bracket last entry.
|
||||
|
||||
Mon Jul 31 12:04:47 1995 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* sparc-opc.c (sllx, srax, srlx): Fix disassembly.
|
||||
|
||||
Wed Jul 12 00:59:34 1995 Ken Raeburn <raeburn@kr-pc.cygnus.com>
|
||||
|
||||
* configure.in: Get host_makefile_frag from ${srcdir}.
|
||||
|
||||
* configure.in: Autoconfiscated. Check for string[s].h. Create
|
||||
config.h from config.in. Don't set up sysdep.h link.
|
||||
* sysdep.h: New file.
|
||||
* configure, config.in: New files, generated from configure.in.
|
||||
* Makefile.in: Updated to be processed autoconf-style.
|
||||
(distclean): Keep sysdep.h. Remove config.log and config.cache.
|
||||
(Makefile): Depend on config.status.
|
||||
(config.status): New rule.
|
||||
* configure.bat: Update Makefile substitutions.
|
||||
|
||||
Tue Jul 11 14:23:37 1995 Jeff Spiegel <jeffs@lsil.com>
|
||||
|
||||
* mips-opc.c (L1): Define.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Print SPARC instructions.
|
||||
Copyright 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
Copyright 1989, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -13,14 +13,38 @@ GNU General Public License for more details.
|
|||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "opcode/sparc.h"
|
||||
#include "dis-asm.h"
|
||||
#include "libiberty.h"
|
||||
#include <string.h>
|
||||
|
||||
/* For faster lookup, after insns are sorted they are hashed. */
|
||||
/* ??? I think there is room for even more improvement. */
|
||||
|
||||
#define HASH_SIZE 256
|
||||
/* It is important that we only look at insn code bits as that is how the
|
||||
opcode table is hashed. OPCODE_BITS is a table of valid bits for each
|
||||
of the main types (0,1,2,3). */
|
||||
static int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 };
|
||||
#define HASH_INSN(INSN) \
|
||||
((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19))
|
||||
struct opcode_hash {
|
||||
struct opcode_hash *next;
|
||||
struct sparc_opcode *opcode;
|
||||
};
|
||||
static struct opcode_hash *opcode_hash_table[HASH_SIZE];
|
||||
static void build_hash_table ();
|
||||
|
||||
/* Sign-extend a value which is N bits long. */
|
||||
#define SEX(value, bits) \
|
||||
((((int)(value)) << ((8 * sizeof (int)) - bits)) \
|
||||
>> ((8 * sizeof (int)) - bits) )
|
||||
|
||||
static char *reg_names[] =
|
||||
{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
|
||||
{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
|
||||
"o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
|
||||
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
|
||||
"i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
|
||||
|
@ -28,123 +52,166 @@ static char *reg_names[] =
|
|||
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
||||
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
|
||||
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
|
||||
"y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
|
||||
#ifndef NO_V9
|
||||
"f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
|
||||
"f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
|
||||
"f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
|
||||
"f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
|
||||
/* psr, wim, tbr, fpsr, cpsr are v8 only. */
|
||||
#endif
|
||||
"y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
|
||||
};
|
||||
|
||||
#define freg_names (®_names[4 * 8])
|
||||
|
||||
/* FIXME--need to deal with byte order (probably using masking and
|
||||
shifting rather than bitfields is easiest). */
|
||||
|
||||
union sparc_insn
|
||||
{
|
||||
unsigned long int code;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
#define op ldst.anop
|
||||
unsigned int anrd:5;
|
||||
#define rd ldst.anrd
|
||||
unsigned int op3:6;
|
||||
unsigned int anrs1:5;
|
||||
#define rs1 ldst.anrs1
|
||||
unsigned int i:1;
|
||||
unsigned int anasi:8;
|
||||
#define asi ldst.anasi
|
||||
unsigned int anrs2:5;
|
||||
#define rs2 ldst.anrs2
|
||||
#define shcnt rs2
|
||||
} ldst;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
|
||||
unsigned int IMM13:13;
|
||||
#define imm13 IMM13.IMM13
|
||||
} IMM13;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
unsigned int a:1;
|
||||
unsigned int cond:4;
|
||||
unsigned int op2:3;
|
||||
unsigned int DISP22:22;
|
||||
#define disp22 branch.DISP22
|
||||
} branch;
|
||||
#ifndef NO_V9
|
||||
struct
|
||||
{
|
||||
unsigned int _OP:2, _RD:5, op3:6, _RS1:5;
|
||||
unsigned int DISP14:14;
|
||||
#define disp14 DISP14.DISP14
|
||||
} DISP14;
|
||||
struct
|
||||
{
|
||||
unsigned int _OP:2;
|
||||
unsigned int a:1;
|
||||
unsigned int cond:4;
|
||||
unsigned int op2:3;
|
||||
unsigned int p:1;
|
||||
unsigned int DISP21:21;
|
||||
#define disp21 branch2.DISP21
|
||||
} branch2;
|
||||
#endif /* NO_V9 */
|
||||
/* These are ordered according to there register number in
|
||||
rdpr and wrpr insns. */
|
||||
static char *v9_priv_reg_names[] =
|
||||
{
|
||||
"tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
|
||||
"pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
|
||||
"wstate", "fq"
|
||||
/* "ver" - special cased */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define imm22 disp22
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
unsigned int adisp30:30;
|
||||
#define disp30 call.adisp30
|
||||
} call;
|
||||
};
|
||||
/* Macros used to extract instruction fields. Not all fields have
|
||||
macros defined here, only those which are actually used. */
|
||||
|
||||
#define X_RD(i) (((i) >> 25) & 0x1f)
|
||||
#define X_RS1(i) (((i) >> 14) & 0x1f)
|
||||
#define X_LDST_I(i) (((i) >> 13) & 1)
|
||||
#define X_ASI(i) (((i) >> 5) & 0xff)
|
||||
#define X_RS2(i) (((i) >> 0) & 0x1f)
|
||||
#define X_IMM13(i) (((i) >> 0) & 0x1fff)
|
||||
#define X_DISP22(i) (((i) >> 0) & 0x3fffff)
|
||||
#define X_IMM22(i) X_DISP22 (i)
|
||||
#define X_DISP30(i) (((i) >> 0) & 0x3fffffff)
|
||||
|
||||
#ifndef NO_V9
|
||||
#define X_DISP16(i) (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
|
||||
#endif
|
||||
|
||||
/* Here is the union which was used to extract instruction fields
|
||||
before the shift and mask macros were written.
|
||||
|
||||
union sparc_insn
|
||||
{
|
||||
unsigned long int code;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
#define op ldst.anop
|
||||
unsigned int anrd:5;
|
||||
#define rd ldst.anrd
|
||||
unsigned int op3:6;
|
||||
unsigned int anrs1:5;
|
||||
#define rs1 ldst.anrs1
|
||||
unsigned int i:1;
|
||||
unsigned int anasi:8;
|
||||
#define asi ldst.anasi
|
||||
unsigned int anrs2:5;
|
||||
#define rs2 ldst.anrs2
|
||||
#define shcnt rs2
|
||||
} ldst;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
|
||||
unsigned int IMM13:13;
|
||||
#define imm13 IMM13.IMM13
|
||||
} IMM13;
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
unsigned int a:1;
|
||||
unsigned int cond:4;
|
||||
unsigned int op2:3;
|
||||
unsigned int DISP22:22;
|
||||
#define disp22 branch.DISP22
|
||||
#define imm22 disp22
|
||||
} branch;
|
||||
#ifndef NO_V9
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
unsigned int a:1;
|
||||
unsigned int z:1;
|
||||
unsigned int rcond:3;
|
||||
unsigned int op2:3;
|
||||
unsigned int DISP16HI:2;
|
||||
unsigned int p:1;
|
||||
unsigned int _rs1:5;
|
||||
unsigned int DISP16LO:14;
|
||||
} branch16;
|
||||
#endif
|
||||
struct
|
||||
{
|
||||
unsigned int anop:2;
|
||||
unsigned int adisp30:30;
|
||||
#define disp30 call.adisp30
|
||||
} call;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
/* Nonzero if INSN is the opcode for a delayed branch. */
|
||||
static int
|
||||
is_delayed_branch (insn)
|
||||
union sparc_insn insn;
|
||||
unsigned long insn;
|
||||
{
|
||||
unsigned int i;
|
||||
struct opcode_hash *op;
|
||||
|
||||
for (i = 0; i < NUMOPCODES; ++i)
|
||||
for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
|
||||
{
|
||||
const struct sparc_opcode *opcode = &sparc_opcodes[i];
|
||||
if ((opcode->match & insn.code) == opcode->match
|
||||
&& (opcode->lose & insn.code) == 0)
|
||||
CONST struct sparc_opcode *opcode = op->opcode;
|
||||
if ((opcode->match & insn) == opcode->match
|
||||
&& (opcode->lose & insn) == 0)
|
||||
return (opcode->flags & F_DELAYED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opcodes_sorted = 0;
|
||||
extern void qsort ();
|
||||
/* Nonzero of opcode table has been initialized. */
|
||||
static int opcodes_initialized = 0;
|
||||
|
||||
/* Print one instruction from MEMADDR on STREAM.
|
||||
/* Nonzero of the current architecture is sparc64.
|
||||
This is kept in a global because compare_opcodes uses it. */
|
||||
static int sparc64_p;
|
||||
|
||||
/* extern void qsort (); */
|
||||
static int compare_opcodes ();
|
||||
|
||||
/* Print one instruction from MEMADDR on INFO->STREAM.
|
||||
|
||||
We suffix the instruction with a comment that gives the absolute
|
||||
address involved, as well as its symbolic form, if the instruction
|
||||
is preceded by a findable `sethi' and it either adds an immediate
|
||||
displacement to that register, or it is an `add' or `or' instruction
|
||||
on that register. */
|
||||
int
|
||||
print_insn_sparc (memaddr, info)
|
||||
|
||||
static int
|
||||
print_insn (memaddr, info)
|
||||
bfd_vma memaddr;
|
||||
disassemble_info *info;
|
||||
{
|
||||
FILE *stream = info->stream;
|
||||
union sparc_insn insn;
|
||||
|
||||
bfd_byte buffer[4];
|
||||
unsigned long insn;
|
||||
register unsigned int i;
|
||||
register struct opcode_hash *op;
|
||||
|
||||
if (!opcodes_sorted)
|
||||
if (!opcodes_initialized)
|
||||
{
|
||||
static int compare_opcodes ();
|
||||
qsort ((char *) sparc_opcodes, NUMOPCODES,
|
||||
sizeof (sparc_opcodes[0]), compare_opcodes);
|
||||
opcodes_sorted = 1;
|
||||
build_hash_table (sparc_opcodes, opcode_hash_table, NUMOPCODES);
|
||||
opcodes_initialized = 1;
|
||||
}
|
||||
|
||||
{
|
||||
int status =
|
||||
(*info->read_memory_func) (memaddr, (char *) &insn, sizeof (insn), info);
|
||||
(*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, memaddr, info);
|
||||
|
@ -152,11 +219,19 @@ print_insn_sparc (memaddr, info)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMOPCODES; ++i)
|
||||
insn = bfd_getb32 (buffer);
|
||||
|
||||
info->insn_info_valid = 1; /* We do return this info */
|
||||
info->insn_type = dis_nonbranch; /* Assume non branch insn */
|
||||
info->branch_delay_insns = 0; /* Assume no delay */
|
||||
info->target = 0; /* Assume no target known */
|
||||
|
||||
for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
|
||||
{
|
||||
const struct sparc_opcode *opcode = &sparc_opcodes[i];
|
||||
if ((opcode->match & insn.code) == opcode->match
|
||||
&& (opcode->lose & insn.code) == 0)
|
||||
CONST struct sparc_opcode *opcode = op->opcode;
|
||||
|
||||
if ((opcode->match & insn) == opcode->match
|
||||
&& (opcode->lose & insn) == 0)
|
||||
{
|
||||
/* Nonzero means that we have found an instruction which has
|
||||
the effect of adding or or'ing the imm13 field to rs1. */
|
||||
|
@ -166,14 +241,17 @@ print_insn_sparc (memaddr, info)
|
|||
field of the opcode table. */
|
||||
int found_plus = 0;
|
||||
|
||||
/* Nonzero means we have an annulled branch. */
|
||||
int is_annulled = 0;
|
||||
|
||||
/* Do we have an `add' or `or' instruction where rs1 is the same
|
||||
as rsd, and which has the i bit set? */
|
||||
if ((opcode->match == 0x80102000 || opcode->match == 0x80002000)
|
||||
/* (or) (add) */
|
||||
&& insn.rs1 == insn.rd)
|
||||
&& X_RS1 (insn) == X_RD (insn))
|
||||
imm_added_to_rs1 = 1;
|
||||
|
||||
if (insn.rs1 != insn.rd
|
||||
if (X_RS1 (insn) != X_RD (insn)
|
||||
&& strchr (opcode->args, 'r') != 0)
|
||||
/* Can't do simple format if source and dest are different. */
|
||||
continue;
|
||||
|
@ -181,7 +259,7 @@ print_insn_sparc (memaddr, info)
|
|||
(*info->fprintf_func) (stream, opcode->name);
|
||||
|
||||
{
|
||||
register const char *s;
|
||||
register CONST char *s;
|
||||
|
||||
if (opcode->args[0] != ',')
|
||||
(*info->fprintf_func) (stream, " ");
|
||||
|
@ -194,6 +272,7 @@ print_insn_sparc (memaddr, info)
|
|||
switch (*s) {
|
||||
case 'a':
|
||||
(*info->fprintf_func) (stream, "a");
|
||||
is_annulled = 1;
|
||||
++s;
|
||||
continue;
|
||||
#ifndef NO_V9
|
||||
|
@ -206,7 +285,7 @@ print_insn_sparc (memaddr, info)
|
|||
(*info->fprintf_func) (stream, "pt");
|
||||
++s;
|
||||
continue;
|
||||
#endif /* NO_V9 */
|
||||
#endif /* NO_V9 */
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -232,62 +311,69 @@ print_insn_sparc (memaddr, info)
|
|||
#define reg(n) (*info->fprintf_func) (stream, "%%%s", reg_names[n])
|
||||
case '1':
|
||||
case 'r':
|
||||
reg (insn.rs1);
|
||||
reg (X_RS1 (insn));
|
||||
break;
|
||||
|
||||
case '2':
|
||||
reg (insn.rs2);
|
||||
reg (X_RS2 (insn));
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
reg (insn.rd);
|
||||
reg (X_RD (insn));
|
||||
break;
|
||||
#undef reg
|
||||
|
||||
#define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n])
|
||||
#define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n])
|
||||
#define fregx(n) (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
|
||||
case 'e':
|
||||
freg (X_RS1 (insn));
|
||||
break;
|
||||
case 'v': /* double/even */
|
||||
case 'V': /* quad/multiple of 4 */
|
||||
freg (insn.rs1);
|
||||
fregx (X_RS1 (insn));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
freg (X_RS2 (insn));
|
||||
break;
|
||||
case 'B': /* double/even */
|
||||
case 'R': /* quad/multiple of 4 */
|
||||
freg (insn.rs2);
|
||||
fregx (X_RS2 (insn));
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
freg (X_RD (insn));
|
||||
break;
|
||||
case 'H': /* double/even */
|
||||
case 'J': /* quad/multiple of 4 */
|
||||
freg (insn.rd);
|
||||
fregx (X_RD (insn));
|
||||
break;
|
||||
#undef freg
|
||||
#undef fregx
|
||||
|
||||
#define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
|
||||
case 'b':
|
||||
creg (insn.rs1);
|
||||
creg (X_RS1 (insn));
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
creg (insn.rs2);
|
||||
creg (X_RS2 (insn));
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
creg (insn.rd);
|
||||
creg (X_RD (insn));
|
||||
break;
|
||||
#undef creg
|
||||
|
||||
case 'h':
|
||||
(*info->fprintf_func) (stream, "%%hi(%#x)",
|
||||
(int) insn.imm22 << 10);
|
||||
(0xFFFFFFFF
|
||||
& ((int) X_IMM22 (insn) << 10)));
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
{
|
||||
/* We cannot trust the compiler to sign-extend
|
||||
when extracting the bitfield, hence the shifts. */
|
||||
int imm = ((int) insn.imm13 << 19) >> 19;
|
||||
int imm = SEX (X_IMM13 (insn), 13);
|
||||
|
||||
/* Check to see whether we have a 1+i, and take
|
||||
note of that fact.
|
||||
|
@ -310,14 +396,12 @@ print_insn_sparc (memaddr, info)
|
|||
case 'I': /* 11 bit immediate. */
|
||||
case 'j': /* 10 bit immediate. */
|
||||
{
|
||||
/* We cannot trust the compiler to sign-extend
|
||||
when extracting the bitfield, hence the shifts. */
|
||||
int imm;
|
||||
|
||||
if (*s == 'I')
|
||||
imm = ((int) insn.imm13 << 21) >> 21;
|
||||
imm = SEX (X_IMM13 (insn), 11);
|
||||
else
|
||||
imm = ((int) insn.imm13 << 22) >> 22;
|
||||
imm = SEX (X_IMM13 (insn), 10);
|
||||
|
||||
/* Check to see whether we have a 1+i, and take
|
||||
note of that fact.
|
||||
|
@ -336,37 +420,29 @@ print_insn_sparc (memaddr, info)
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case 'k':
|
||||
(*info->print_address_func)
|
||||
((bfd_vma) (memaddr
|
||||
+ (((int) insn.disp14 << 18) >> 18) * 4),
|
||||
info);
|
||||
info->target = memaddr + (SEX (X_DISP16 (insn), 16)) * 4;
|
||||
(*info->print_address_func) (info->target, info);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
(*info->print_address_func)
|
||||
((bfd_vma) (memaddr
|
||||
/* We use only 19 of the 21 bits. */
|
||||
+ (((int) insn.disp21 << 13) >> 13) * 4),
|
||||
info);
|
||||
info->target = memaddr + (SEX (X_DISP22 (insn), 19)) * 4;
|
||||
(*info->print_address_func) (info->target, info);
|
||||
break;
|
||||
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
(*info->fprintf_func) (stream, "fcc%c", *s - '6' + '0');
|
||||
(*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
(*info->fprintf_func) (stream, "icc");
|
||||
(*info->fprintf_func) (stream, "%%icc");
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
(*info->fprintf_func) (stream, "xcc");
|
||||
(*info->fprintf_func) (stream, "%%xcc");
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
|
@ -376,40 +452,64 @@ print_insn_sparc (memaddr, info)
|
|||
case 's':
|
||||
(*info->fprintf_func) (stream, "%%fprs");
|
||||
break;
|
||||
#endif /* NO_V9 */
|
||||
|
||||
case 'o':
|
||||
(*info->fprintf_func) (stream, "%%asi");
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
(*info->fprintf_func) (stream, "%%tick");
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
(*info->fprintf_func) (stream, "%%pc");
|
||||
break;
|
||||
|
||||
case '?':
|
||||
if (X_RS1 (insn) == 31)
|
||||
(*info->fprintf_func) (stream, "%%ver");
|
||||
else if ((unsigned) X_RS1 (insn) < 16)
|
||||
(*info->fprintf_func) (stream, "%%%s",
|
||||
v9_priv_reg_names[X_RS1 (insn)]);
|
||||
else
|
||||
(*info->fprintf_func) (stream, "%%reserved");
|
||||
break;
|
||||
|
||||
case '!':
|
||||
if ((unsigned) X_RD (insn) < 15)
|
||||
(*info->fprintf_func) (stream, "%%%s",
|
||||
v9_priv_reg_names[X_RD (insn)]);
|
||||
else
|
||||
(*info->fprintf_func) (stream, "%%reserved");
|
||||
break;
|
||||
break;
|
||||
#endif /* NO_V9 */
|
||||
|
||||
case 'M':
|
||||
(*info->fprintf_func) (stream, "%%asr%d", insn.rs1);
|
||||
(*info->fprintf_func) (stream, "%%asr%d", X_RS1 (insn));
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
(*info->fprintf_func) (stream, "%%asr%d", insn.rd);
|
||||
(*info->fprintf_func) (stream, "%%asr%d", X_RD (insn));
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
(*info->print_address_func)
|
||||
((bfd_vma) memaddr + insn.disp30 * 4,
|
||||
info);
|
||||
info->target = memaddr + X_DISP30 (insn) * 4;
|
||||
(*info->print_address_func) (info->target, info);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
(*info->fprintf_func)
|
||||
(stream, "%#x", (SEX (X_DISP22 (insn), 22)));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if ((insn.code >> 22) == 0)
|
||||
/* Special case for `unimp'. Don't try to turn
|
||||
it's operand into a function offset. */
|
||||
(*info->fprintf_func)
|
||||
(stream, "%#x",
|
||||
(int) (((int) insn.disp22 << 10) >> 10));
|
||||
else
|
||||
/* We cannot trust the compiler to sign-extend
|
||||
when extracting the bitfield, hence the shifts. */
|
||||
(*info->print_address_func)
|
||||
((bfd_vma) (memaddr
|
||||
+ (((int) insn.disp22 << 10) >> 10) * 4),
|
||||
info);
|
||||
info->target = memaddr + (SEX (X_DISP22 (insn), 22)) * 4;
|
||||
(*info->print_address_func) (info->target, info);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
(*info->fprintf_func) (stream, "(%d)", (int) insn.asi);
|
||||
(*info->fprintf_func) (stream, "(%d)", X_ASI (insn));
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
|
@ -440,6 +540,12 @@ print_insn_sparc (memaddr, info)
|
|||
(*info->fprintf_func) (stream, "%%wim");
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
(*info->fprintf_func) (stream, "%d",
|
||||
((X_LDST_I (insn) << 8)
|
||||
+ X_ASI (insn)));
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
(*info->fprintf_func) (stream, "%%y");
|
||||
break;
|
||||
|
@ -455,13 +561,13 @@ print_insn_sparc (memaddr, info)
|
|||
and its symbolic value. */
|
||||
if (imm_added_to_rs1)
|
||||
{
|
||||
union sparc_insn prev_insn;
|
||||
unsigned long prev_insn;
|
||||
int errcode;
|
||||
|
||||
errcode =
|
||||
(*info->read_memory_func)
|
||||
(memaddr - 4,
|
||||
(char *)&prev_insn, sizeof (prev_insn), info);
|
||||
(memaddr - 4, buffer, sizeof (buffer), info);
|
||||
prev_insn = bfd_getb32 (buffer);
|
||||
|
||||
if (errcode == 0)
|
||||
{
|
||||
|
@ -475,9 +581,11 @@ print_insn_sparc (memaddr, info)
|
|||
*/
|
||||
|
||||
if (is_delayed_branch (prev_insn))
|
||||
errcode = (*info->read_memory_func)
|
||||
(memaddr - 8, (char *)&prev_insn, sizeof (prev_insn),
|
||||
info);
|
||||
{
|
||||
errcode = (*info->read_memory_func)
|
||||
(memaddr - 8, buffer, sizeof (buffer), info);
|
||||
prev_insn = bfd_getb32 (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was a problem reading memory, then assume
|
||||
|
@ -485,26 +593,40 @@ print_insn_sparc (memaddr, info)
|
|||
if (errcode == 0)
|
||||
{
|
||||
/* Is it sethi to the same register? */
|
||||
if ((prev_insn.code & 0xc1c00000) == 0x01000000
|
||||
&& prev_insn.rd == insn.rs1)
|
||||
if ((prev_insn & 0xc1c00000) == 0x01000000
|
||||
&& X_RD (prev_insn) == X_RS1 (insn))
|
||||
{
|
||||
(*info->fprintf_func) (stream, "\t! ");
|
||||
/* We cannot trust the compiler to sign-extend
|
||||
when extracting the bitfield, hence the shifts. */
|
||||
(*info->print_address_func)
|
||||
(((int) prev_insn.imm22 << 10)
|
||||
| (insn.imm13 << 19) >> 19,
|
||||
info);
|
||||
info->target =
|
||||
(0xFFFFFFFF & (int) X_IMM22 (prev_insn) << 10)
|
||||
| SEX (X_IMM13 (insn), 13);
|
||||
(*info->print_address_func) (info->target, info);
|
||||
info->insn_type = dis_dref;
|
||||
info->data_size = 4; /* FIXME!!! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sizeof (insn);
|
||||
if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
|
||||
{
|
||||
/* FIXME -- check is_annulled flag */
|
||||
if (opcode->flags & F_UNBR)
|
||||
info->insn_type = dis_branch;
|
||||
if (opcode->flags & F_CONDBR)
|
||||
info->insn_type = dis_condbranch;
|
||||
if (opcode->flags & F_JSR)
|
||||
info->insn_type = dis_jsr;
|
||||
if (opcode->flags & F_DELAYED)
|
||||
info->branch_delay_insns = 1;
|
||||
}
|
||||
|
||||
return sizeof (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
(*info->fprintf_func) (stream, "%#8x", insn.code);
|
||||
return sizeof (insn);
|
||||
info->insn_type = dis_noninsn; /* Mark as non-valid instruction */
|
||||
(*info->fprintf_func) (stream, "%#8x", insn);
|
||||
return sizeof (buffer);
|
||||
}
|
||||
|
||||
/* Compare opcodes A and B. */
|
||||
|
@ -537,6 +659,20 @@ compare_opcodes (a, b)
|
|||
lose1 = op1->lose;
|
||||
}
|
||||
|
||||
/* If the current architecture isn't sparc64, move v9 insns to the end.
|
||||
Only do this when one isn't v9 and one is. If both are v9 we still
|
||||
need to properly sort them.
|
||||
This must be done before checking match and lose. */
|
||||
if (!sparc64_p
|
||||
&& (op0->architecture == v9) != (op1->architecture == v9))
|
||||
return (op0->architecture == v9) - (op1->architecture == v9);
|
||||
|
||||
/* If the current architecture is sparc64, move non-v9 insns to the end.
|
||||
This must be done before checking match and lose. */
|
||||
if (sparc64_p
|
||||
&& (op0->flags & F_NOTV9) != (op1->flags & F_NOTV9))
|
||||
return (op0->flags & F_NOTV9) - (op1->flags & F_NOTV9);
|
||||
|
||||
/* Because the bits that are variable in one opcode are constant in
|
||||
another, it is important to order the opcodes in the right order. */
|
||||
for (i = 0; i < 32; ++i)
|
||||
|
@ -614,3 +750,78 @@ compare_opcodes (a, b)
|
|||
written, so just say there are equal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build a hash table from the opcode table. */
|
||||
|
||||
static void
|
||||
build_hash_table (table, hash_table, num_opcodes)
|
||||
struct sparc_opcode *table;
|
||||
struct opcode_hash **hash_table;
|
||||
int num_opcodes;
|
||||
{
|
||||
int i;
|
||||
int hash_count[HASH_SIZE];
|
||||
|
||||
/* Start at the end of the table and work backwards so that each
|
||||
chain is sorted. */
|
||||
/* ??? Do we really need to sort them now? */
|
||||
|
||||
memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0]));
|
||||
memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0]));
|
||||
for (i = num_opcodes - 1; i >= 0; --i)
|
||||
{
|
||||
int hash = HASH_INSN (sparc_opcodes[i].match);
|
||||
struct opcode_hash *h = (struct opcode_hash *) xmalloc (sizeof (struct opcode_hash));
|
||||
h->next = hash_table[hash];
|
||||
h->opcode = &sparc_opcodes[i];
|
||||
hash_table[hash] = h;
|
||||
++hash_count[hash];
|
||||
}
|
||||
|
||||
#if 0 /* for debugging */
|
||||
{
|
||||
int min_count = num_opcodes, max_count = 0;
|
||||
int total;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; ++i)
|
||||
{
|
||||
if (hash_count[i] < min_count)
|
||||
min_count = hash_count[i];
|
||||
if (hash_count[i] > max_count)
|
||||
max_count = hash_count[i];
|
||||
total += hash_count[i];
|
||||
}
|
||||
|
||||
printf ("Opcode hash table stats: min %d, max %d, ave %f\n",
|
||||
min_count, max_count, (double) total / HASH_SIZE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_sparc (memaddr, info)
|
||||
bfd_vma memaddr;
|
||||
disassemble_info *info;
|
||||
{
|
||||
/* It's not clear that we'll ever switch cpus in a running program.
|
||||
It could theoretically happen in gdb so we handle it.
|
||||
??? There is currently a memory leak but it's not worth the trouble. */
|
||||
if (sparc64_p)
|
||||
opcodes_initialized = 0;
|
||||
sparc64_p = 0;
|
||||
return print_insn (memaddr, info);
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_sparc64 (memaddr, info)
|
||||
bfd_vma memaddr;
|
||||
disassemble_info *info;
|
||||
{
|
||||
/* It's not clear that we'll ever switch cpus in a running program.
|
||||
It could theoretically happen in gdb so we handle it.
|
||||
??? There is currently a memory leak but it's not worth the trouble. */
|
||||
if (!sparc64_p)
|
||||
opcodes_initialized = 0;
|
||||
sparc64_p = 1;
|
||||
return print_insn (memaddr, info);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* to sanitize this file, grep -v v9 < sparc.h > clean-sparc.h */
|
||||
|
||||
/* Table of opcodes for the sparc.
|
||||
Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
|
||||
Copyright 1989, 1991, 1992, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the BFD library.
|
||||
|
||||
|
@ -17,7 +15,8 @@ for more details.
|
|||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this software; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* FIXME-someday: perhaps the ,a's and such should be embedded in the
|
||||
instruction's name rather than the args. This would make gas faster, pinsn
|
||||
|
@ -30,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "ansidecl.h"
|
||||
#include "opcode/sparc.h"
|
||||
|
||||
CONST char *architecture_pname[] = {
|
||||
const char *architecture_pname[] = {
|
||||
"v6",
|
||||
"v7",
|
||||
"v8",
|
||||
|
@ -128,20 +127,18 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 },
|
||||
{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", F_ALIAS, v6 },
|
||||
{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", F_ALIAS, v6 }, /* ld [rs1+%g0],d */
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", F_ALIAS, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", F_ALIAS, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", F_ALIAS, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", F_ALIAS, v6 }, /* ld [rs1+0],d */
|
||||
{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6 },
|
||||
{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6 }, /* ld [rs1+%g0],d */
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6 }, /* ld [rs1+0],d */
|
||||
{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", F_NOTV9, v6 }, /* ld [rs1+%g0],d */
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", F_NOTV9, v6 }, /* ld [rs1+0],d */
|
||||
{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", F_NOTV9, v6 }, /* ld [rs1+%g0],d */
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", F_NOTV9, v6 },
|
||||
{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", F_NOTV9, v6 }, /* ld [rs1+0],d */
|
||||
|
||||
/* The v9 LDUW is the same as the old 'ld' opcode, it is not the same as the
|
||||
'ld' pseudo-op in v9. */
|
||||
|
@ -164,14 +161,13 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[i+1],H", 0, v6 },
|
||||
{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0, "[i],H", 0, v6 },
|
||||
{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0), "[1],H", 0, v6 }, /* ldd [rs1+0],d */
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0), "[1+2],D", F_ALIAS, v6 },
|
||||
{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0), "[1],D", F_ALIAS, v6 }, /* ldd [rs1+%g0],d */
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i],D", F_ALIAS, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1],D", F_ALIAS, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i],D", F_ALIAS, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1],D", F_ALIAS, v6 }, /* ldd [rs1+0],d */
|
||||
|
||||
{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0), "[1+2],D", F_NOTV9, v6 },
|
||||
{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0), "[1],D", F_NOTV9, v6 }, /* ldd [rs1+%g0],d */
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i],D", F_NOTV9, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1],D", F_NOTV9, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i],D", F_NOTV9, v6 },
|
||||
{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1],D", F_NOTV9, v6 }, /* ldd [rs1+0],d */
|
||||
|
||||
{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI(~0), "[1+2],J", 0, v9 },
|
||||
{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI_RS2(~0), "[1],J", 0, v9 }, /* ldd [rs1+%g0],d */
|
||||
|
@ -338,20 +334,19 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[i+1]", 0, v6 },
|
||||
{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0, "g,[i]", 0, v6 },
|
||||
{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0), "g,[1]", 0, v6 }, /* st d,[rs1+0] */
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0), "D,[1+2]", F_ALIAS, v6 },
|
||||
{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0), "D,[1]", F_ALIAS, v6 }, /* st d,[rs1+%g0] */
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[1+i]", F_ALIAS, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[i+1]", F_ALIAS, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "D,[i]", F_ALIAS, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "D,[1]", F_ALIAS, v6 }, /* st d,[rs1+0] */
|
||||
{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0), "C,[1+2]", 0, v6 },
|
||||
{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0), "C,[1]", 0, v6 }, /* st d,[rs1+%g0] */
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[1+i]", 0, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", 0, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", 0, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", 0, v6 }, /* st d,[rs1+0] */
|
||||
|
||||
{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0), "D,[1+2]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0), "D,[1]", F_NOTV9, v6 }, /* st d,[rs1+%g0] */
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[1+i]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[i+1]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "D,[i]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "D,[1]", F_NOTV9, v6 }, /* st d,[rs1+0] */
|
||||
{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0), "C,[1+2]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0), "C,[1]", F_NOTV9, v6 }, /* st d,[rs1+%g0] */
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[1+i]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", F_NOTV9, v6 },
|
||||
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", F_NOTV9, v6 }, /* st d,[rs1+0] */
|
||||
|
||||
{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0), "F,[1+2]", 0, v6 },
|
||||
{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0), "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */
|
||||
|
@ -408,36 +403,32 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[i+1]", 0, v6 },
|
||||
{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0, "d,[i]", 0, v6 },
|
||||
{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* std d,[rs1+0] */
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "q,[1+2]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "q,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[1+i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[i+1]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "q,[i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "q,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */
|
||||
|
||||
{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "q,[1+2]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "q,[1]", F_NOTV9, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[1+i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[i+1]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "q,[i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "q,[1]", F_NOTV9, v6 }, /* std d,[rs1+0] */
|
||||
{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0), "H,[1+2]", 0, v6 },
|
||||
{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0), "H,[1]", 0, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[1+i]", 0, v6 },
|
||||
{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[i+1]", 0, v6 },
|
||||
{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0, "H,[i]", 0, v6 },
|
||||
{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0), "H,[1]", 0, v6 }, /* std d,[rs1+0] */
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "Q,[1+2]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "Q,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[1+i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[i+1]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "Q,[i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "Q,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0), "D,[1+2]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0), "D,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[1+i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[i+1]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "D,[i]", F_ALIAS, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "D,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */
|
||||
|
||||
{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "Q,[1+2]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "Q,[1]", F_NOTV9, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[1+i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[i+1]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "Q,[i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "Q,[1]", F_NOTV9, v6 }, /* std d,[rs1+0] */
|
||||
{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0), "D,[1+2]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0), "D,[1]", F_NOTV9, v6 }, /* std d,[rs1+%g0] */
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[1+i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[i+1]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "D,[i]", F_NOTV9, v6 },
|
||||
{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "D,[1]", F_NOTV9, v6 }, /* std d,[rs1+0] */
|
||||
|
||||
{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0), "d,[1+2]A", 0, v6 },
|
||||
{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */
|
||||
|
@ -542,11 +533,11 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "1+i,d", F_JSR|F_DELAYED, v6 },
|
||||
{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "i+1,d", F_JSR|F_DELAYED, v6 },
|
||||
|
||||
{ "done", F3(2, 0x3e, 1)|RD(0), F3(~2, ~0x3e, ~1)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "retry", F3(2, 0x3e, 1)|RD(1), F3(~2, ~0x3e, ~1)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "saved", F3(2, 0x31, 1)|RD(0), F3(~2, ~0x31, ~1)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "restored", F3(2, 0x31, 1)|RD(1), F3(~2, ~0x31, ~1)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "sir", F3(2, 0x30, 0)|RD(0xf), F3(~2, ~0x30, ~0)|RD(~0xf)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "done", F3(2, 0x3e, 0)|RD(0), F3(~2, ~0x3e, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "retry", F3(2, 0x3e, 0)|RD(1), F3(~2, ~0x3e, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "saved", F3(2, 0x31, 0)|RD(0), F3(~2, ~0x31, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "restored", F3(2, 0x31, 0)|RD(1), F3(~2, ~0x31, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 },
|
||||
{ "sir", F3(2, 0x30, 1)|RD(0xf), F3(~2, ~0x30, ~1)|RD(~0xf)|RS1_G0, "i", 0, v9 },
|
||||
|
||||
{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", 0, v8 },
|
||||
{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0), "1", 0, v8 }, /* flush rs1+%g0 */
|
||||
|
@ -572,7 +563,7 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
|
||||
{ "flushw", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v9 },
|
||||
|
||||
{ "membar", F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|ASI(~0), "K", 0, v9 },
|
||||
{ "membar", F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|SIMM13(~0), "K", 0, v9 },
|
||||
{ "stbar", F3(2, 0x28, 0)|RS1(0xf), F3(~2, ~0x28, ~0)|RD_G0|RS1(~0xf)|SIMM13(~0), "", 0, v8 },
|
||||
|
||||
{ "prefetch", F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0), "[1+2],*", 0, v9 },
|
||||
|
@ -589,6 +580,7 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* prefetcha [rs1+0],d */
|
||||
|
||||
/* The 1<<12 is a long story. It is necessary. For more info, please contact rich@cygnus.com */
|
||||
/* FIXME: 'i' is wrong, need new letter for 5 bit unsigned constants. */
|
||||
{ "sll", F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "sll", F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12), "1,i,d", 0, v6 },
|
||||
{ "sra", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
|
||||
|
@ -596,12 +588,13 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "srl", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "srl", F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12), "1,i,d", 0, v6 },
|
||||
|
||||
/* FIXME: 'j' is wrong, need new letter for 6 bit unsigned constants. */
|
||||
{ "sllx", F3(2, 0x25, 0)|(1<<12), F3(~2, ~0x25, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 },
|
||||
{ "sllx", F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1), "1,i,d", 0, v9 },
|
||||
{ "sllx", F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1)|(0x3f<<6), "1,j,d", 0, v9 },
|
||||
{ "srax", F3(2, 0x27, 0)|(1<<12), F3(~2, ~0x27, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 },
|
||||
{ "srax", F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1), "1,i,d", 0, v9 },
|
||||
{ "srax", F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1)|(0x3f<<6), "1,j,d", 0, v9 },
|
||||
{ "srlx", F3(2, 0x26, 0)|(1<<12), F3(~2, ~0x26, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 },
|
||||
{ "srlx", F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1), "1,i,d", 0, v9 },
|
||||
{ "srlx", F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1)|(0x3f<<6), "1,j,d", 0, v9 },
|
||||
|
||||
{ "mulscc", F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "mulscc", F3(2, 0x24, 1), F3(~2, ~0x24, ~1), "1,i,d", 0, v6 },
|
||||
|
@ -654,18 +647,16 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0), "2", 0, v6 }, /* orcc %g0, rs2, %g0 */
|
||||
{ "tst", F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0), "1", 0, v6 }, /* orcc rs1, 0, %g0 */
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", 0, v8 }, /* wr r,r,%asrX */
|
||||
{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", 0, v6 }, /* wr r,r,%y */
|
||||
{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", 0, v8 }, /* wr r,i,%asrX */
|
||||
{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", 0, v6 }, /* wr r,i,%y */
|
||||
{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", F_ALIAS, v6 }, /* wr r,r,%psr */
|
||||
{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", F_ALIAS, v6 }, /* wr r,i,%psr */
|
||||
{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", F_ALIAS, v6 }, /* wr r,r,%wim */
|
||||
{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", F_ALIAS, v6 }, /* wr r,i,%wim */
|
||||
{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", F_ALIAS, v6 }, /* wr r,r,%tbr */
|
||||
{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", F_ALIAS, v6 }, /* wr r,i,%tbr */
|
||||
{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", F_NOTV9, v6 }, /* wr r,r,%psr */
|
||||
{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", F_NOTV9, v6 }, /* wr r,i,%psr */
|
||||
{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", F_NOTV9, v6 }, /* wr r,r,%wim */
|
||||
{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", F_NOTV9, v6 }, /* wr r,i,%wim */
|
||||
{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", F_NOTV9, v6 }, /* wr r,r,%tbr */
|
||||
{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", F_NOTV9, v6 }, /* wr r,i,%tbr */
|
||||
|
||||
{ "wr", F3(2, 0x30, 0)|RD(0), F3(~2, ~0x30, ~0)|RD(~0)|ASI(~0), "1,2,y", 0, v9 }, /* wr r,r,%y */
|
||||
{ "wr", F3(2, 0x30, 1)|RD(0), F3(~2, ~0x30, ~1)|RD(~0), "1,i,y", 0, v9 }, /* wr r,i,%y */
|
||||
|
@ -676,19 +667,17 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "wr", F3(2, 0x30, 0)|RD(6), F3(~2, ~0x30, ~0)|RD(~6)|ASI(~0), "1,2,s", 0, v9 }, /* wr r,i,%fprs */
|
||||
{ "wr", F3(2, 0x30, 1)|RD(6), F3(~2, ~0x30, ~1)|RD(~6), "1,i,s", 0, v9 }, /* wr r,i,%fprs */
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", 0, v8 }, /* rd %asrX,r */
|
||||
{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", 0, v6 }, /* rd %y,r */
|
||||
{ "rd", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS, v6 }, /* rd %psr,r */
|
||||
{ "rd", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS, v6 }, /* rd %wim,r */
|
||||
{ "rd", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS, v6 }, /* rd %tbr,r */
|
||||
{ "rd", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_NOTV9, v6 }, /* rd %psr,r */
|
||||
{ "rd", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_NOTV9, v6 }, /* rd %wim,r */
|
||||
{ "rd", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_NOTV9, v6 }, /* rd %tbr,r */
|
||||
|
||||
{ "rd", F3(2, 0x28, 0)|RS1(2), F3(~2, ~0x28, ~0)|RS1(~2)|SIMM13(~0), "E,d", 0, v9 }, /* rd %ccr,r */
|
||||
{ "rd", F3(2, 0x28, 0)|RS1(3), F3(~2, ~0x28, ~0)|RS1(~3)|SIMM13(~0), "o,d", 0, v9 }, /* rd %asi,r */
|
||||
{ "rd", F3(2, 0x28, 0)|RS1(4), F3(~2, ~0x28, ~0)|RS1(~4)|SIMM13(~0), "W,d", 0, v9 }, /* rd %tick,r */
|
||||
{ "rd", F3(2, 0x28, 0)|RS1(5), F3(~2, ~0x28, ~0)|RS1(~5)|SIMM13(~0), "P,d", 0, v9 }, /* rd %pc,r */
|
||||
{ "rd", F3(2, 0x2b, 0)|RS1(6), F3(~2, ~0x2b, ~0)|RS1(~6)|SIMM13(~0), "s,d", 0, v9 }, /* rd %fprs,r */
|
||||
{ "rd", F3(2, 0x28, 0)|RS1(6), F3(~2, ~0x28, ~0)|RS1(~6)|SIMM13(~0), "s,d", 0, v9 }, /* rd %fprs,r */
|
||||
|
||||
{ "rdpr", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|SIMM13(~0), "?,d", 0, v9 }, /* rdpr %priv,r */
|
||||
{ "wrpr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0), "1,2,!", 0, v9 }, /* wrpr r1,r2,%priv */
|
||||
|
@ -714,9 +703,9 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
v9: Methinks we will need some sort of F_NOTFORV9 flag. */
|
||||
{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", F_ALIAS, v8 }, /* rd %asr1,r */
|
||||
{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", F_ALIAS, v6 }, /* rd %y,r */
|
||||
{ "mov", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS, v6 }, /* rd %psr,r */
|
||||
{ "mov", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS, v6 }, /* rd %wim,r */
|
||||
{ "mov", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS, v6 }, /* rd %tbr,r */
|
||||
{ "mov", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS|F_NOTV9, v6 }, /* rd %psr,r */
|
||||
{ "mov", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS|F_NOTV9, v6 }, /* rd %wim,r */
|
||||
{ "mov", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS|F_NOTV9, v6 }, /* rd %tbr,r */
|
||||
|
||||
{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
|
||||
{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "i,y", F_ALIAS, v6 },
|
||||
|
@ -763,17 +752,13 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "subcc", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "subcc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "1,i,d", 0, v6 },
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", F_ALIAS, v6 },
|
||||
{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", F_ALIAS, v6 },
|
||||
{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", F_NOTV9, v6 },
|
||||
{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", F_NOTV9, v6 },
|
||||
{ "subc", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "subc", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v9 },
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", F_ALIAS, v6 },
|
||||
{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", F_ALIAS, v6 },
|
||||
{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", F_NOTV9, v6 },
|
||||
{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", F_NOTV9, v6 },
|
||||
{ "subccc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "subccc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v9 },
|
||||
|
||||
|
@ -806,19 +791,17 @@ struct sparc_opcode sparc_opcodes[] = {
|
|||
{ "addcc", F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "1,i,d", 0, v6 },
|
||||
{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,1,d", 0, v6 },
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", F_ALIAS, v6 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", F_ALIAS, v6 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", F_ALIAS, v6 },
|
||||
|
||||
{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", F_NOTV9, v6 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", F_NOTV9, v6 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", F_NOTV9, v6 },
|
||||
{ "addc", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v9 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v9 },
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", F_ALIAS, v6 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", F_ALIAS, v6 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", F_ALIAS, v6 },
|
||||
|
||||
{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", F_NOTV9, v6 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", F_NOTV9, v6 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", F_NOTV9, v6 },
|
||||
{ "addccc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v9 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v9 },
|
||||
|
@ -1297,9 +1280,7 @@ condfc("fbule", "cb013", 0xe, 0),
|
|||
{ "tsubcctv", F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "tsubcctv", F3(2, 0x23, 1), F3(~2, ~0x23, ~1), "1,i,d", 0, v6 },
|
||||
|
||||
/* FIXME This is marked F_ALIAS, so that it won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "unimp", F2(0x0, 0x0), 0xffc00000, "n", F_ALIAS, v6 },
|
||||
{ "unimp", F2(0x0, 0x0), 0xffc00000, "n", F_NOTV9, v6 },
|
||||
{ "illtrap", F2(0, 0), F2(~0, ~0)|RD_G0, "n", 0, v9 },
|
||||
|
||||
/* This *is* a commutative instruction. */
|
||||
|
@ -1412,16 +1393,59 @@ condfc("fbule", "cb013", 0xe, 0),
|
|||
{ "fcmpes", CMPFCC(2)|F3F(2, 0x35, 0x055), CMPFCC(~2)|F3F(~2, ~0x35, ~0x055), "8,e,f", 0, v9 },
|
||||
{ "fcmpes", CMPFCC(3)|F3F(2, 0x35, 0x055), CMPFCC(~3)|F3F(~2, ~0x35, ~0x055), "9,e,f", 0, v9 },
|
||||
|
||||
/* FIXME These are marked F_ALIAS, so that they won't conflict with new v9
|
||||
insns when v9 is present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "cpop1", F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS, v6 },
|
||||
{ "cpop2", F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS, v6 },
|
||||
/* These Extended FPop (FIFO) instructions are new in the Fujitsu
|
||||
MB86934, replacing the CPop instructions from v6 and later
|
||||
processors. */
|
||||
|
||||
#define EFPOP1_2(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op)|RS1_G0, args, 0, sparclite }
|
||||
#define EFPOP1_3(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op), args, 0, sparclite }
|
||||
#define EFPOP2_2(name, op, args) { name, F3F(2, 0x37, op), F3F(~2, ~0x37, ~op)|RD_G0, args, 0, sparclite }
|
||||
|
||||
EFPOP1_2 ("efitod", 0x0c8, "f,H"),
|
||||
EFPOP1_2 ("efitos", 0x0c4, "f,g"),
|
||||
EFPOP1_2 ("efdtoi", 0x0d2, "B,g"),
|
||||
EFPOP1_2 ("efstoi", 0x0d1, "f,g"),
|
||||
EFPOP1_2 ("efstod", 0x0c9, "f,H"),
|
||||
EFPOP1_2 ("efdtos", 0x0c6, "B,g"),
|
||||
EFPOP1_2 ("efmovs", 0x001, "f,g"),
|
||||
EFPOP1_2 ("efnegs", 0x005, "f,g"),
|
||||
EFPOP1_2 ("efabss", 0x009, "f,g"),
|
||||
EFPOP1_2 ("efsqrtd", 0x02a, "B,H"),
|
||||
EFPOP1_2 ("efsqrts", 0x029, "f,g"),
|
||||
EFPOP1_3 ("efaddd", 0x042, "v,B,H"),
|
||||
EFPOP1_3 ("efadds", 0x041, "e,f,g"),
|
||||
EFPOP1_3 ("efsubd", 0x046, "v,B,H"),
|
||||
EFPOP1_3 ("efsubs", 0x045, "e,f,g"),
|
||||
EFPOP1_3 ("efdivd", 0x04e, "v,B,H"),
|
||||
EFPOP1_3 ("efdivs", 0x04d, "e,f,g"),
|
||||
EFPOP1_3 ("efmuld", 0x04a, "v,B,H"),
|
||||
EFPOP1_3 ("efmuls", 0x049, "e,f,g"),
|
||||
EFPOP1_3 ("efsmuld", 0x069, "e,f,H"),
|
||||
EFPOP2_2 ("efcmpd", 0x052, "v,B"),
|
||||
EFPOP2_2 ("efcmped", 0x056, "v,B"),
|
||||
EFPOP2_2 ("efcmps", 0x051, "e,f"),
|
||||
EFPOP2_2 ("efcmpes", 0x055, "e,f"),
|
||||
|
||||
#undef EFPOP1_2
|
||||
#undef EFPOP1_3
|
||||
#undef EFPOP2_2
|
||||
|
||||
/* These are marked F_ALIAS, so that they won't conflict with sparclite insns
|
||||
present. Otherwise, the F_ALIAS flag is ignored. */
|
||||
{ "cpop1", F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS|F_NOTV9, v6 },
|
||||
{ "cpop2", F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS|F_NOTV9, v6 },
|
||||
|
||||
#define IMPDEP(name, code) \
|
||||
{ name, F3(2, code, 0), F3(~2, ~code, ~0)|ASI(~0), "1,2,d", 0, v9 }, \
|
||||
{ name, F3(2, code, 1), F3(~2, ~code, ~1), "1,i,d", 0, v9 }, \
|
||||
{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,1,2,d", 0, v9 }, \
|
||||
{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,e,f,g", 0, v9 }
|
||||
|
||||
IMPDEP ("impdep1", 0x36),
|
||||
IMPDEP ("impdep2", 0x37),
|
||||
|
||||
#undef IMPDEP
|
||||
|
||||
{ "impdep1", F3(2, 0x36, 0), F3(~2, ~0x36, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "impdep1", F3(2, 0x36, 1), F3(~2, ~0x36, ~1), "1,i,d", 0, v9 },
|
||||
{ "impdep2", F3(2, 0x37, 0), F3(~2, ~0x37, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "impdep2", F3(2, 0x37, 1), F3(~2, ~0x37, ~1), "1,i,d", 0, v9 },
|
||||
|
||||
{ "casa", F3(3, 0x3c, 0), F3(~3, ~0x3c, ~0), "[1]A,2,d", 0, v9 },
|
||||
{ "casa", F3(3, 0x3c, 1), F3(~3, ~0x3c, ~1), "[1]o,2,d", 0, v9 },
|
||||
{ "casxa", F3(3, 0x3e, 0), F3(~3, ~0x3e, ~0), "[1]A,2,d", 0, v9 },
|
||||
|
@ -1429,4 +1453,4 @@ condfc("fbule", "cb013", 0xe, 0),
|
|||
|
||||
};
|
||||
|
||||
CONST int bfd_sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
|
||||
const int bfd_sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
|
||||
|
|
Loading…
Reference in a new issue