aboutsummaryrefslogtreecommitdiff
path: root/opcodes/tic80-dis.c
diff options
context:
space:
mode:
authorFred Fish <fnf@specifix.com>1997-01-04 01:39:30 +0000
committerFred Fish <fnf@specifix.com>1997-01-04 01:39:30 +0000
commit872dc6f0bcc4992b5fdefa11ea41df4cada72ca2 (patch)
treeecf546fd17b065ddd846de1b4dcb46a397965e9d /opcodes/tic80-dis.c
parent28eb95aa337f72b4a87cdd2a2d6aff9cc0984a4b (diff)
downloadgdb-872dc6f0bcc4992b5fdefa11ea41df4cada72ca2.zip
gdb-872dc6f0bcc4992b5fdefa11ea41df4cada72ca2.tar.gz
gdb-872dc6f0bcc4992b5fdefa11ea41df4cada72ca2.tar.bz2
* ppc-opc.c (powerpc_operands): Make comment match the
actual fields (no shift field). * sparc-opc.c (sparc_opcodes): Document why this cannot be "const". * tic80-dis.c (print_insn_tic80): Replace abort stub with a partial implementation, work in progress. * tic80-opc.c (tic80_operands): Begin construction operands table. (tic80_opcodes): Continue populating opcodes table and start filling in the operand indices. (tic80_num_opcodes): Add this.
Diffstat (limited to 'opcodes/tic80-dis.c')
-rw-r--r--opcodes/tic80-dis.c177
1 files changed, 176 insertions, 1 deletions
diff --git a/opcodes/tic80-dis.c b/opcodes/tic80-dis.c
index d78d676..d930c80 100644
--- a/opcodes/tic80-dis.c
+++ b/opcodes/tic80-dis.c
@@ -26,5 +26,180 @@ print_insn_tic80 (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
{
- abort ();
+ bfd_byte buffer[4];
+ int status;
+ unsigned long insn[2];
+ const struct tic80_opcode *opcode;
+ const struct tic80_opcode *opcode_end;
+ const unsigned char *opindex;
+ const struct tic80_operand *operand;
+ int need_comma;
+ int need_paren;
+ int length = 4;
+
+ status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ if (info -> endian == BFD_ENDIAN_LITTLE)
+ {
+ insn[0] = bfd_getl32 (buffer);
+ }
+ else if (info -> endian == BFD_ENDIAN_BIG)
+ {
+ insn[0] = bfd_getb32 (buffer);
+ }
+ else
+ {
+ /* FIXME: Should probably just default to one or the other */
+ abort ();
+ }
+
+ /* Find the first opcode match in the opcodes table. FIXME: there should
+ be faster ways to find one (hash table or binary search), but don't
+ worry too much about it until other TIc80 support is finished. */
+
+ opcode_end = tic80_opcodes + tic80_num_opcodes;
+ for (opcode = tic80_opcodes; opcode < opcode_end; opcode++)
+ {
+ if ((insn[0] & opcode -> mask) == opcode -> opcode)
+ {
+ break;
+ }
+ }
+
+ if (opcode == opcode_end)
+ {
+ /* No match found, just print the bits as a .word directive */
+ (*info -> fprintf_func) (info -> stream, ".word %#08lx", insn[0]);
+ }
+ else
+ {
+ /* Match found, decode the instruction. */
+ (*info -> fprintf_func) (info -> stream, "%s", opcode -> name);
+
+ /* Now extract and print the operands. */
+ need_comma = 0;
+ need_paren = 0;
+ if (opcode -> operands[0] != 0)
+ {
+ (*info -> fprintf_func) (info -> stream, "\t");
+ }
+ for (opindex = opcode -> operands; *opindex != 0; opindex++)
+ {
+ long value;
+
+ operand = tic80_operands + *opindex;
+
+ /* Extract the value from the instruction. */
+ if (operand -> extract)
+ {
+ value = (*operand -> extract) (insn[0], (int *) NULL);
+ }
+ else if (operand -> bits == 32)
+ {
+ status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ if (info -> endian == BFD_ENDIAN_LITTLE)
+ {
+ insn[1] = bfd_getl32 (buffer);
+ }
+ else if (info -> endian == BFD_ENDIAN_BIG)
+ {
+ insn[1] = bfd_getb32 (buffer);
+ }
+ value = (long) insn[1];
+ length += 4;
+ }
+ else
+ {
+ value = (insn[0] >> operand -> shift) & ((1 << operand -> bits) - 1);
+ if ((operand -> flags & TIC80_OPERAND_SIGNED) != 0
+ && (value & (1 << (operand -> bits - 1))) != 0)
+ value -= 1 << operand -> bits;
+ }
+
+ if (need_comma)
+ {
+ (*info -> fprintf_func) (info -> stream, ",");
+ need_comma = 0;
+ }
+
+ /* Print the operand as directed by the flags. */
+ if ((operand -> flags & TIC80_OPERAND_GPR) != 0)
+ {
+ (*info -> fprintf_func) (info -> stream, "r%ld", value);
+ }
+ else if ((operand -> flags & TIC80_OPERAND_FPA) != 0)
+ {
+ (*info -> fprintf_func) (info -> stream, "a%ld", value);
+ }
+ else if ((operand -> flags & TIC80_OPERAND_RELATIVE) != 0)
+ {
+ (*info -> print_address_func) (memaddr + value, info);
+ }
+ else if ((operand -> flags & TIC80_OPERAND_CC_SZ) != 0)
+ {
+#if 0 /* FIXME */
+ if (operand -> bits == 3)
+ (*info -> fprintf_func) (info -> stream, "cr%d", value);
+ else
+ {
+ static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+ int cr;
+ int cc;
+
+ cr = value >> 2;
+ if (cr != 0)
+ (*info -> fprintf_func) (info -> stream, "4*cr%d", cr);
+ cc = value & 3;
+ if (cc != 0)
+ {
+ if (cr != 0)
+ (*info -> fprintf_func) (info -> stream, "+");
+ (*info -> fprintf_func) (info -> stream, "%s", cbnames[cc]);
+ }
+ }
+#endif
+ }
+ else
+ {
+ if ((value > 999 || value < -999)
+ || operand -> flags & TIC80_OPERAND_BITFIELD)
+ {
+ (*info -> fprintf_func) (info -> stream, "%#lx", value);
+ }
+ else
+ {
+ (*info -> fprintf_func) (info -> stream, "%ld", value);
+ }
+ }
+
+ if (need_paren)
+ {
+ (*info -> fprintf_func) (info -> stream, ")");
+ need_paren = 0;
+ }
+
+ if ((operand -> flags & TIC80_OPERAND_PARENS) == 0)
+ {
+ need_comma = 1;
+ }
+ else
+ {
+ (*info -> fprintf_func) (info -> stream, "(");
+ need_paren = 1;
+ }
+ }
+ }
+
+ return (length);
}