aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-09-17 15:31:06 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-09-17 15:31:06 -0700
commit8972118ba4e080f0982c0ade16d31da2d6970fd9 (patch)
treeb00a67302f9044ee989a1fcc639981eb811a5427
parent562a0c1d17ae1bb183f5bd16e48ed6c17c185892 (diff)
downloadriscv-gnu-toolchain-8972118ba4e080f0982c0ade16d31da2d6970fd9.zip
riscv-gnu-toolchain-8972118ba4e080f0982c0ade16d31da2d6970fd9.tar.gz
riscv-gnu-toolchain-8972118ba4e080f0982c0ade16d31da2d6970fd9.tar.bz2
binutils: clean up disassembler code a lot
-rw-r--r--binutils/gas/config/tc-riscv.c21
-rw-r--r--binutils/include/opcode/riscv.h17
-rw-r--r--binutils/opcodes/riscv-dis.c140
3 files changed, 91 insertions, 87 deletions
diff --git a/binutils/gas/config/tc-riscv.c b/binutils/gas/config/tc-riscv.c
index f45a4a1..f4289e7 100644
--- a/binutils/gas/config/tc-riscv.c
+++ b/binutils/gas/config/tc-riscv.c
@@ -264,26 +264,11 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
(((x) &~ (offsetT) 0xffffffff) == 0 \
|| (((x) &~ (offsetT) 0xffffffff) == ~ (offsetT) 0xffffffff))
-/* Replace bits MASK << SHIFT of STRUCT with the equivalent bits in
- VALUE << SHIFT. VALUE is evaluated exactly once. */
-#define INSERT_BITS(STRUCT, VALUE, MASK, SHIFT) \
- (STRUCT) = (((STRUCT) & ~((insn_t)(MASK) << (SHIFT))) \
- | ((insn_t)((VALUE) & (MASK)) << (SHIFT)))
-
-/* Extract bits MASK << SHIFT from STRUCT and shift them right
- SHIFT places. */
-#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \
- (((STRUCT) >> (SHIFT)) & (MASK))
-
/* Change INSN's opcode so that the operand given by FIELD has value VALUE.
INSN is a riscv_cl_insn structure and VALUE is evaluated exactly once. */
#define INSERT_OPERAND(FIELD, INSN, VALUE) \
INSERT_BITS ((INSN).insn_opcode, VALUE, OP_MASK_##FIELD, OP_SH_##FIELD)
-/* Extract the operand given by FIELD from riscv_cl_insn INSN. */
-#define EXTRACT_OPERAND(FIELD, INSN) \
- EXTRACT_BITS ((INSN).insn_opcode, OP_MASK_##FIELD, OP_SH_##FIELD)
-
/* Determine if an instruction matches an opcode. */
#define OPCODE_MATCHES(OPCODE, OP) \
(((OPCODE) & MASK_##OP) == MATCH_##OP)
@@ -1313,7 +1298,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
continue;
case 'w': /* RS1 x8-x15, constrained to equal RD x8-x15 */
if (!reg_lookup (&s, RCLASS_GPR, &regno)
- || EXTRACT_OPERAND (CRS1S, *ip) + 8 != regno)
+ || EXTRACT_OPERAND (CRS1S, ip->insn_opcode) + 8 != regno)
break;
continue;
case 't': /* RS2 x8-x15 */
@@ -1324,7 +1309,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
continue;
case 'x': /* RS2 x8-x15, constrained to equal RD x8-x15 */
if (!reg_lookup (&s, RCLASS_GPR, &regno)
- || EXTRACT_OPERAND (CRS2S, *ip) + 8 != regno)
+ || EXTRACT_OPERAND (CRS2S, ip->insn_opcode) + 8 != regno)
break;
continue;
case 'D': /* RD, nonzero */
@@ -1334,7 +1319,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
continue;
case 'U': /* RS1, constrained to equal RD */
if (!reg_lookup (&s, RCLASS_GPR, &regno)
- || EXTRACT_OPERAND (RD, *ip) != regno)
+ || EXTRACT_OPERAND (RD, ip->insn_opcode) != regno)
break;
continue;
case 'T': /* RS2, nonzero */
diff --git a/binutils/include/opcode/riscv.h b/binutils/include/opcode/riscv.h
index cf5afe7..1a01f25 100644
--- a/binutils/include/opcode/riscv.h
+++ b/binutils/include/opcode/riscv.h
@@ -44,7 +44,7 @@ typedef uint64_t insn_t;
static inline unsigned int riscv_insn_length (insn_t insn)
{
- if ((insn & 0x3) != 3) /* RVC. */
+ if ((insn & 0x3) != 0x3) /* RVC. */
return 2;
if ((insn & 0x1f) != 0x1f) /* Base ISA and extensions in 32-bit space. */
return 4;
@@ -266,6 +266,21 @@ static const char * const riscv_pred_succ[16] = {
#define RISCV_BRANCH_ALIGN (1 << RISCV_BRANCH_ALIGN_BITS)
#define RISCV_BRANCH_REACH (RISCV_IMM_REACH * RISCV_BRANCH_ALIGN)
+/* Replace bits MASK << SHIFT of STRUCT with the equivalent bits in
+ VALUE << SHIFT. VALUE is evaluated exactly once. */
+#define INSERT_BITS(STRUCT, VALUE, MASK, SHIFT) \
+ (STRUCT) = (((STRUCT) & ~((insn_t)(MASK) << (SHIFT))) \
+ | ((insn_t)((VALUE) & (MASK)) << (SHIFT)))
+
+/* Extract bits MASK << SHIFT from STRUCT and shift them right
+ SHIFT places. */
+#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \
+ (((STRUCT) >> (SHIFT)) & (MASK))
+
+/* Extract the operand given by FIELD from integer INSN. */
+#define EXTRACT_OPERAND(FIELD, INSN) \
+ EXTRACT_BITS ((INSN), OP_MASK_##FIELD, OP_SH_##FIELD)
+
/* This structure holds information for a particular instruction. */
struct riscv_opcode
diff --git a/binutils/opcodes/riscv-dis.c b/binutils/opcodes/riscv-dis.c
index f145b67..1247a02 100644
--- a/binutils/opcodes/riscv-dis.c
+++ b/binutils/opcodes/riscv-dis.c
@@ -132,18 +132,16 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
switch (*++d)
{
case 'd':
- (*info->fprintf_func) (info->stream, "%d", rd);
+ print (info->stream, "%d", rd);
break;
case 's':
- (*info->fprintf_func) (info->stream, "%d", rs1);
+ print (info->stream, "%d", rs1);
break;
case 't':
- (*info->fprintf_func)
- ( info->stream, "%d", (int)((l >> OP_SH_RS2) & OP_MASK_RS2));
+ print (info->stream, "%d", (int) EXTRACT_OPERAND (RS2, l));
break;
case 'j':
- (*info->fprintf_func)
- ( info->stream, "%d", (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
+ print (info->stream, "%d", (int) EXTRACT_OPERAND (CUSTOM_IMM, l));
break;
}
break;
@@ -154,12 +152,12 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case 's': /* RS1 x8-x15 */
case 'w': /* RS1 x8-x15 */
print (info->stream, "%s",
- riscv_gpr_names[((l >> OP_SH_CRS1S) & OP_MASK_CRS1S) + 8]);
+ riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
break;
case 't': /* RS2 x8-x15 */
case 'x': /* RS2 x8-x15 */
print (info->stream, "%s",
- riscv_gpr_names[((l >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8]);
+ riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
break;
case 'U': /* RS1, constrained to equal RD */
case 'D': /* RS1 or RD, nonzero */
@@ -171,7 +169,7 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case 'T': /* RS2, nonzero */
case 'V': /* RS2 */
print (info->stream, "%s",
- riscv_gpr_names[(l >> OP_SH_CRS2) & OP_MASK_CRS2]);
+ riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
break;
case 'i':
print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
@@ -213,13 +211,13 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
break;
case 'u':
print (info->stream, "0x%x",
- (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
+ (int) (EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
break;
case '>':
- print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
+ print (info->stream, "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x3f);
break;
case '<':
- print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
+ print (info->stream, "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x1f);
break;
}
break;
@@ -229,14 +227,14 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
{
case 't': /* RS2 x8-x15 */
print (info->stream, "%s",
- riscv_gpr_names[((l >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8]);
+ riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
break;
case 'D': /* RD */
print (info->stream, "%s", riscv_gpr_names[rd]);
break;
case 'V': /* RS2 */
print (info->stream, "%s",
- riscv_gpr_names[(l >> OP_SH_CRS2) & OP_MASK_CRS2]);
+ riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
break;
}
break;
@@ -246,7 +244,7 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case ')':
case '[':
case ']':
- (*info->fprintf_func) (info->stream, "%c", *d);
+ print (info->stream, "%c", *d);
break;
case '0':
@@ -257,32 +255,32 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case 'b':
case 's':
- (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rs1]);
+ print (info->stream, "%s", riscv_gpr_names[rs1]);
break;
case 't':
- (*info->fprintf_func) (info->stream, "%s",
- riscv_gpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
+ print (info->stream, "%s",
+ riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
break;
case 'u':
- (*info->fprintf_func) (info->stream, "0x%x",
- (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
+ print (info->stream, "0x%x",
+ (unsigned) EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
break;
case 'm':
- arg_print(info, (l >> OP_SH_RM) & OP_MASK_RM,
- riscv_rm, ARRAY_SIZE (riscv_rm));
+ arg_print (info, EXTRACT_OPERAND (RM, l),
+ riscv_rm, ARRAY_SIZE (riscv_rm));
break;
case 'P':
- arg_print(info, (l >> OP_SH_PRED) & OP_MASK_PRED,
- riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
+ arg_print (info, EXTRACT_OPERAND (PRED, l),
+ riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
break;
case 'Q':
- arg_print(info, (l >> OP_SH_SUCC) & OP_MASK_SUCC,
- riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
+ arg_print (info, EXTRACT_OPERAND (SUCC, l),
+ riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
break;
case 'o':
@@ -290,12 +288,12 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
case 'j':
if ((l & MASK_ADDI) == MATCH_ADDI || (l & MASK_JALR) == MATCH_JALR)
maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
- (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
+ print (info->stream, "%d", (int) EXTRACT_ITYPE_IMM (l));
break;
case 'q':
maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
- (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
+ print (info->stream, "%d", (int) EXTRACT_STYPE_IMM (l));
break;
case 'a':
@@ -313,46 +311,42 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
else if ((l & MASK_LUI) == MATCH_LUI)
pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
- (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rd]);
+ print (info->stream, "%s", riscv_gpr_names[rd]);
break;
case 'z':
- (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[0]);
+ print (info->stream, "%s", riscv_gpr_names[0]);
break;
case '>':
- (*info->fprintf_func) (info->stream, "0x%x",
- (unsigned)((l >> OP_SH_SHAMT) & OP_MASK_SHAMT));
+ print (info->stream, "0x%x", (int) EXTRACT_OPERAND (SHAMT, l));
break;
case '<':
- (*info->fprintf_func) (info->stream, "0x%x",
- (unsigned)((l >> OP_SH_SHAMTW) & OP_MASK_SHAMTW));
+ print (info->stream, "0x%x", (int) EXTRACT_OPERAND (SHAMTW, l));
break;
case 'S':
case 'U':
- (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rs1]);
+ print (info->stream, "%s", riscv_fpr_names[rs1]);
break;
case 'T':
- (*info->fprintf_func) (info->stream, "%s",
- riscv_fpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
+ print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
break;
case 'D':
- (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rd]);
+ print (info->stream, "%s", riscv_fpr_names[rd]);
break;
case 'R':
- (*info->fprintf_func) (info->stream, "%s",
- riscv_fpr_names[(l >> OP_SH_RS3) & OP_MASK_RS3]);
+ print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
break;
case 'E':
{
const char* csr_name = NULL;
- unsigned int csr = (l >> OP_SH_CSR) & OP_MASK_CSR;
+ unsigned int csr = EXTRACT_OPERAND (CSR, l);
switch (csr)
{
#define DECLARE_CSR(name, num) case num: csr_name = #name; break;
@@ -360,21 +354,20 @@ print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
#undef DECLARE_CSR
}
if (csr_name)
- (*info->fprintf_func) (info->stream, "%s", csr_name);
+ print (info->stream, "%s", csr_name);
else
- (*info->fprintf_func) (info->stream, "0x%x", csr);
+ print (info->stream, "0x%x", csr);
break;
}
case 'Z':
- (*info->fprintf_func) (info->stream, "%d", rs1);
+ print (info->stream, "%d", rs1);
break;
default:
/* xgettext:c-format */
- (*info->fprintf_func) (info->stream,
- _("# internal error, undefined modifier (%c)"),
- *d);
+ print (info->stream, _("# internal error, undefined modifier (%c)"),
+ *d);
return;
}
}
@@ -394,7 +387,7 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
struct riscv_private_data *pd;
int insnlen;
-#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : 0x7f))
+#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
/* Build a hash table to shorten the search time. */
if (! init)
@@ -455,27 +448,39 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
for (; op < &riscv_opcodes[NUMOPCODES]; op++)
{
- if ((op->match_func) (op, word)
- && !(no_aliases && (op->pinfo & INSN_ALIAS))
- && !(op->subset[0] == 'X' && extension != NULL
- && strcmp (op->subset, extension))
- && !(isdigit(op->subset[0]) && atoi(op->subset) != xlen))
+ /* Does the opcode match? */
+ if (! (op->match_func) (op, word))
+ continue;
+ /* Is this a pseudo-instruction and may we print it as such? */
+ if (no_aliases && (op->pinfo & INSN_ALIAS))
+ continue;
+ /* Is this instruction for an ISA extension and does it match the
+ extension for which the object was compiled? */
+ if (extension != NULL && op->subset[0] == 'X')
+ if (strcmp (op->subset, extension) != 0)
+ continue;
+ /* Is this instruction restricted to a certain value of XLEN? */
+ if (isdigit (op->subset[0]) && atoi (op->subset) != xlen)
+ continue;
+
+ /* It's a match. */
+ (*info->fprintf_func) (info->stream, "%s", op->name);
+ print_insn_args (op->args, word, memaddr, info);
+
+ /* Try to disassemble multi-instruction addressing sequences. */
+ if (pd->print_addr != (bfd_vma)-1)
{
- (*info->fprintf_func) (info->stream, "%s", op->name);
- print_insn_args (op->args, word, memaddr, info);
- if (pd->print_addr != (bfd_vma)-1)
- {
- info->target = pd->print_addr;
- (*info->fprintf_func) (info->stream, " # ");
- (*info->print_address_func) (info->target, info);
- pd->print_addr = -1;
- }
- return insnlen;
+ info->target = pd->print_addr;
+ (*info->fprintf_func) (info->stream, " # ");
+ (*info->print_address_func) (info->target, info);
+ pd->print_addr = -1;
}
+
+ return insnlen;
}
}
- /* Handle undefined instructions. */
+ /* We did not find a match, so just print the instruction bits. */
info->insn_type = dis_noninsn;
(*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
return insnlen;
@@ -484,7 +489,7 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
int
print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
{
- uint16_t i2;
+ bfd_byte packet[2];
insn_t insn = 0;
bfd_vma n;
int status;
@@ -501,7 +506,7 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
/* Instructions are a sequence of 2-byte packets in little-endian order. */
for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
{
- status = (*info->read_memory_func) (memaddr + n, (bfd_byte*)&i2, 2, info);
+ status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
if (status != 0)
{
/* Don't fail just because we fell off the end. */
@@ -511,8 +516,7 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
return status;
}
- i2 = bfd_getl16 (&i2);
- insn |= (insn_t)i2 << (8 * n);
+ insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
}
return riscv_disassemble_insn (memaddr, insn, info);