/* Print SPARC instructions.
- Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This file is part of the GNU opcodes library.
+
+ This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the 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., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include <stdio.h>
-
#include "sysdep.h"
+#include <stdio.h>
#include "opcode/sparc.h"
#include "dis-asm.h"
#include "libiberty.h"
{
"tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
"pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
- "wstate", "fq"
+ "wstate", "fq", "gl"
/* "ver" - special cased */
};
+/* These are ordered according to there register number in
+ rdhpr and wrhpr insns. */
+static char *v9_hpriv_reg_names[] =
+{
+ "hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver",
+ "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13",
+ "resv14", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
+ "resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27",
+ "resv28", "resv29", "resv30", "hstick_cmpr"
+};
+
/* These are ordered according to there register number in
rd and wr insns (-16). */
static char *v9a_asr_reg_names[] =
{
"pcr", "pic", "dcr", "gsr", "set_softint", "clear_softint",
- "softint", "tick_cmpr", "sys_tick", "sys_tick_cmpr"
+ "softint", "tick_cmpr", "stick", "stick_cmpr", "cfr",
+ "pause", "cps"
};
/* Macros used to extract instruction fields. Not all fields have
#define X_LDST_I(i) (((i) >> 13) & 1)
#define X_ASI(i) (((i) >> 5) & 0xff)
#define X_RS2(i) (((i) >> 0) & 0x1f)
+#define X_RS3(i) (((i) >> 9) & 0x1f)
#define X_IMM(i,n) (((i) >> 0) & ((1 << (n)) - 1))
#define X_SIMM(i,n) SEX (X_IMM ((i), (n)), (n))
#define X_DISP22(i) (((i) >> 0) & 0x3fffff)
/* These are for v9. */
#define X_DISP16(i) (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
+#define X_DISP10(i) (((((i) >> 19) & 3) << 8) | (((i) >> 5) & 0xff))
#define X_DISP19(i) (((i) >> 0) & 0x7ffff)
#define X_MEMBAR(i) ((i) & 0x7f)
{
case 0 :
case bfd_mach_sparc :
- return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8);
+ return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
+ | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_LEON));
case bfd_mach_sparc_sparclet :
return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET);
case bfd_mach_sparc_sparclite :
i = strcmp (op0->name, op1->name);
if (i)
{
- if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */
- return i;
+ if (op0->flags & F_ALIAS)
+ {
+ if (op0->flags & F_PREFERRED)
+ return -1;
+ if (op1->flags & F_PREFERRED)
+ return 1;
+
+ /* If they're both aliases, and neither is marked as preferred,
+ be arbitrary. */
+ return i;
+ }
else
fprintf (stderr,
/* xgettext:c-format */
/* Can't do simple format if source and dest are different. */
continue;
- (*info->fprintf_func) (stream, opcode->name);
+ (*info->fprintf_func) (stream, "%s", opcode->name);
{
const char *s;
fregx (X_RS2 (insn));
break;
+ case '4':
+ freg (X_RS3 (insn));
+ break;
+ case '5': /* Double/even. */
+ fregx (X_RS3 (insn));
+ break;
+
case 'g':
freg (X_RD (insn));
break;
}
break;
+ case ')': /* 5 bit unsigned immediate from RS3. */
+ (info->fprintf_func) (stream, "%#x", (unsigned int) X_RS3 (insn));
+ break;
+
case 'X': /* 5 bit unsigned immediate. */
case 'Y': /* 6 bit unsigned immediate. */
{
break;
case '3':
- (info->fprintf_func) (stream, "%d", X_IMM (insn, 3));
+ (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3));
break;
case 'K':
break;
}
+ case '=':
+ info->target = memaddr + SEX (X_DISP10 (insn), 10) * 4;
+ (*info->print_address_func) (info->target, info);
+ break;
+
case 'k':
info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
(*info->print_address_func) (info->target, info);
case '?':
if (X_RS1 (insn) == 31)
(*info->fprintf_func) (stream, "%%ver");
- else if ((unsigned) X_RS1 (insn) < 16)
+ else if ((unsigned) X_RS1 (insn) < 17)
(*info->fprintf_func) (stream, "%%%s",
v9_priv_reg_names[X_RS1 (insn)]);
else
break;
case '!':
- if ((unsigned) X_RD (insn) < 15)
+ if ((unsigned) X_RD (insn) < 17)
(*info->fprintf_func) (stream, "%%%s",
v9_priv_reg_names[X_RD (insn)]);
else
(*info->fprintf_func) (stream, "%%reserved");
break;
+ case '$':
+ if ((unsigned) X_RS1 (insn) < 32)
+ (*info->fprintf_func) (stream, "%%%s",
+ v9_hpriv_reg_names[X_RS1 (insn)]);
+ else
+ (*info->fprintf_func) (stream, "%%reserved");
+ break;
+
+ case '%':
+ if ((unsigned) X_RD (insn) < 32)
+ (*info->fprintf_func) (stream, "%%%s",
+ v9_hpriv_reg_names[X_RD (insn)]);
+ else
+ (*info->fprintf_func) (stream, "%%reserved");
+ break;
+
case '/':
- if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)
+ if (X_RS1 (insn) < 16 || X_RS1 (insn) > 28)
(*info->fprintf_func) (stream, "%%reserved");
else
(*info->fprintf_func) (stream, "%%%s",
break;
case '_':
- if (X_RD (insn) < 16 || X_RD (insn) > 25)
+ if (X_RD (insn) < 16 || X_RD (insn) > 28)
(*info->fprintf_func) (stream, "%%reserved");
else
(*info->fprintf_func) (stream, "%%%s",
if (name)
(*info->fprintf_func) (stream, "%s", name);
else
- (*info->fprintf_func) (stream, "%d", X_RD (insn));
+ (*info->fprintf_func) (stream, "%ld", X_RD (insn));
break;
}
case 'M':
- (*info->fprintf_func) (stream, "%%asr%d", X_RS1 (insn));
+ (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn));
break;
case 'm':
- (*info->fprintf_func) (stream, "%%asr%d", X_RD (insn));
+ (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn));
break;
case 'L':
if (name)
(*info->fprintf_func) (stream, "%s", name);
else
- (*info->fprintf_func) (stream, "(%d)", X_ASI (insn));
+ (*info->fprintf_func) (stream, "(%ld)", X_ASI (insn));
break;
}
(*info->fprintf_func) (stream, "%%fsr");
break;
+ case '(':
+ (*info->fprintf_func) (stream, "%%efsr");
+ break;
+
case 'p':
(*info->fprintf_func) (stream, "%%psr");
break;
break;
case 'x':
- (*info->fprintf_func) (stream, "%d",
+ (*info->fprintf_func) (stream, "%ld",
((X_LDST_I (insn) << 8)
+ X_ASI (insn)));
break;
if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
{
- /* FIXME -- check is_annulled flag. */
+ /* FIXME -- check is_annulled flag. */
+ (void) is_annulled;
if (opcode->flags & F_UNBR)
info->insn_type = dis_branch;
if (opcode->flags & F_CONDBR)