X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Fsparc-dis.c;h=c825c863b2ec69d81afa37e214185941dde14e79;hb=5b6d1e4fa4fc6827c7b3f0e99ff120dfa14d65d2;hp=8dec272fb2b4c9e661f25f7412dea2c49a0ebc7c;hpb=c7e2358a8849d7540212543e1a2acbac648cb973;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/sparc-dis.c b/opcodes/sparc-dis.c index 8dec272fb2..c825c863b2 100644 --- a/opcodes/sparc-dis.c +++ b/opcodes/sparc-dis.c @@ -1,7 +1,5 @@ /* Print SPARC instructions. - Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 - Free Software Foundation, Inc. + Copyright (C) 1989-2020 Free Software Foundation, Inc. This file is part of the GNU opcodes library. @@ -20,9 +18,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include - #include "sysdep.h" +#include #include "opcode/sparc.h" #include "dis-asm.h" #include "libiberty.h" @@ -31,7 +28,13 @@ /* Bitmask of v9 architectures. */ #define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \ | (1 << SPARC_OPCODE_ARCH_V9A) \ - | (1 << SPARC_OPCODE_ARCH_V9B)) + | (1 << SPARC_OPCODE_ARCH_V9B) \ + | (1 << SPARC_OPCODE_ARCH_V9C) \ + | (1 << SPARC_OPCODE_ARCH_V9D) \ + | (1 << SPARC_OPCODE_ARCH_V9E) \ + | (1 << SPARC_OPCODE_ARCH_V9V) \ + | (1 << SPARC_OPCODE_ARCH_V9M) \ + | (1 << SPARC_OPCODE_ARCH_M8)) /* 1 if INSN is for v9 only. */ #define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9)) /* 1 if INSN is for v9. */ @@ -60,8 +63,8 @@ static sparc_opcode_hash *opcode_hash_table[HASH_SIZE]; /* Sign-extend a value which is N bits long. */ #define SEX(value, bits) \ - ((((int)(value)) << ((8 * sizeof (int)) - bits)) \ - >> ((8 * sizeof (int)) - bits) ) + ((int) (((value & ((1u << (bits - 1) << 1) - 1)) \ + ^ (1u << (bits - 1))) - (1u << (bits - 1)))) static char *reg_names[] = { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", @@ -89,7 +92,7 @@ static char *v9_priv_reg_names[] = "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl", "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", "wstate", "fq", "gl" - /* "ver" - special cased */ + /* "ver" and "pmcdper" - special cased */ }; /* These are ordered according to there register number in @@ -97,18 +100,19 @@ static char *v9_priv_reg_names[] = static char *v9_hpriv_reg_names[] = { "hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver", - "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13", + "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" + "resv21", "resv22", "hmcdper", "hmcddfr", "resv25", "resv26", "hva_mask_nz", + "hstick_offset", "hstick_enable", "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", "stick", "stick_cmpr" + "pcr", "pic", "dcr", "gsr", "softint_set", "softint_clear", + "softint", "tick_cmpr", "stick", "stick_cmpr", "cfr", + "pause", "mwait" }; /* Macros used to extract instruction fields. Not all fields have @@ -119,14 +123,17 @@ static char *v9a_asr_reg_names[] = #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) #define X_IMM22(i) X_DISP22 (i) #define X_DISP30(i) (((i) >> 0) & 0x3fffffff) +#define X_IMM2(i) (((i & 0x10) >> 3) | (i & 0x1)) /* 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) @@ -221,7 +228,8 @@ compute_arch_mask (unsigned long mach) { 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 : @@ -240,6 +248,24 @@ compute_arch_mask (unsigned long mach) case bfd_mach_sparc_v8plusb : case bfd_mach_sparc_v9b : return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B); + case bfd_mach_sparc_v8plusc : + case bfd_mach_sparc_v9c : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9C); + case bfd_mach_sparc_v8plusd : + case bfd_mach_sparc_v9d : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9D); + case bfd_mach_sparc_v8pluse : + case bfd_mach_sparc_v9e : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9E); + case bfd_mach_sparc_v8plusv : + case bfd_mach_sparc_v9v : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9V); + case bfd_mach_sparc_v8plusm : + case bfd_mach_sparc_v9m : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9M); + case bfd_mach_sparc_v8plusm8 : + case bfd_mach_sparc_v9m8 : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_M8); } abort (); } @@ -277,10 +303,9 @@ compare_opcodes (const void * a, const void * b) wrong with the opcode table. */ if (match0 & lose0) { - fprintf - (stderr, - /* xgettext:c-format */ - _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), + opcodes_error_handler + /* xgettext:c-format */ + (_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), op0->name, match0, lose0); op0->lose &= ~op0->match; lose0 = op0->lose; @@ -288,10 +313,9 @@ compare_opcodes (const void * a, const void * b) if (match1 & lose1) { - fprintf - (stderr, - /* xgettext:c-format */ - _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), + opcodes_error_handler + /* xgettext:c-format */ + (_("internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), op1->name, match1, lose1); op1->lose &= ~op1->match; lose1 = op1->lose; @@ -301,7 +325,7 @@ compare_opcodes (const void * a, const void * b) another, it is important to order the opcodes in the right order. */ for (i = 0; i < 32; ++i) { - unsigned long int x = 1 << i; + unsigned long int x = 1ul << i; int x0 = (match0 & x) != 0; int x1 = (match1 & x) != 0; @@ -311,7 +335,7 @@ compare_opcodes (const void * a, const void * b) for (i = 0; i < 32; ++i) { - unsigned long int x = 1 << i; + unsigned long int x = 1ul << i; int x0 = (lose0 & x) != 0; int x1 = (lose1 & x) != 0; @@ -336,13 +360,22 @@ compare_opcodes (const void * a, const void * b) 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 */ - _("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"), - op0->name, op1->name); + opcodes_error_handler + /* xgettext:c-format */ + (_("internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"), + op0->name, op1->name); } /* Fewer arguments are preferred. */ @@ -548,7 +581,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) /* 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; @@ -623,6 +656,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) break; case 'v': /* Double/even. */ case 'V': /* Quad/multiple of 4. */ + case ';': /* Double/even multiple of 8 doubles. */ fregx (X_RS1 (insn)); break; @@ -631,16 +665,34 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) break; case 'B': /* Double/even. */ case 'R': /* Quad/multiple of 4. */ + case ':': /* Double/even multiple of 8 doubles. */ 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; case 'H': /* Double/even. */ case 'J': /* Quad/multiple of 4. */ + case '}': /* Double/even. */ fregx (X_RD (insn)); break; + + case '^': /* Double/even multiple of 8 doubles. */ + fregx (X_RD (insn) & ~0x6); + break; + + case '\'': /* Double/even in FPCMPSHL. */ + fregx (X_RS2 (insn | 0x11)); + break; + #undef freg #undef fregx @@ -660,8 +712,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) case 'h': (*info->fprintf_func) (stream, "%%hi(%#x)", - ((unsigned) 0xFFFFFFFF - & ((int) X_IMM22 (insn) << 10))); + (unsigned) X_IMM22 (insn) << 10); break; case 'i': /* 13 bit immediate. */ @@ -694,6 +745,10 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) } 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. */ { @@ -734,6 +789,11 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) 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); @@ -767,6 +827,14 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) (*info->fprintf_func) (stream, "%%fprs"); break; + case '{': + (*info->fprintf_func) (stream, "%%mcdper"); + break; + + case '&': + (*info->fprintf_func) (stream, "%%entropy"); + break; + case 'o': (*info->fprintf_func) (stream, "%%asi"); break; @@ -782,6 +850,8 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) case '?': if (X_RS1 (insn) == 31) (*info->fprintf_func) (stream, "%%ver"); + else if (X_RS1 (insn) == 23) + (*info->fprintf_func) (stream, "%%pmcdper"); else if ((unsigned) X_RS1 (insn) < 17) (*info->fprintf_func) (stream, "%%%s", v9_priv_reg_names[X_RS1 (insn)]); @@ -790,7 +860,11 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) break; case '!': - if ((unsigned) X_RD (insn) < 17) + if (X_RD (insn) == 31) + (*info->fprintf_func) (stream, "%%ver"); + else if (X_RD (insn) == 23) + (*info->fprintf_func) (stream, "%%pmcdper"); + else if ((unsigned) X_RD (insn) < 17) (*info->fprintf_func) (stream, "%%%s", v9_priv_reg_names[X_RD (insn)]); else @@ -814,7 +888,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) 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", @@ -822,7 +896,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) 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", @@ -882,6 +956,10 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) (*info->fprintf_func) (stream, "%%fsr"); break; + case '(': + (*info->fprintf_func) (stream, "%%efsr"); + break; + case 'p': (*info->fprintf_func) (stream, "%%psr"); break; @@ -908,6 +986,10 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) + X_ASI (insn))); break; + case '|': /* 2-bit immediate */ + (*info->fprintf_func) (stream, "%ld", X_IMM2 (insn)); + break; + case 'y': (*info->fprintf_func) (stream, "%%y"); break; @@ -979,9 +1061,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) && X_RD (prev_insn) == X_RS1 (insn)) { (*info->fprintf_func) (stream, "\t! "); - info->target = - ((unsigned) 0xFFFFFFFF - & ((int) X_IMM22 (prev_insn) << 10)); + info->target = (unsigned) X_IMM22 (prev_insn) << 10; if (imm_added_to_rs1) info->target += X_SIMM (insn, 13); else