diff options
author | Jason Eckhardt <jle@rice.edu> | 2000-07-28 21:10:20 +0000 |
---|---|---|
committer | Jason Eckhardt <jle@rice.edu> | 2000-07-28 21:10:20 +0000 |
commit | 9d751335284aad9de560434108a112f357f2e304 (patch) | |
tree | 2c49776716361d7d3281c9a79ce273711bb3944a /opcodes/i860-dis.c | |
parent | b22a60275347d3cba34d19c892a3da2e97e329e9 (diff) | |
download | gdb-9d751335284aad9de560434108a112f357f2e304.zip gdb-9d751335284aad9de560434108a112f357f2e304.tar.gz gdb-9d751335284aad9de560434108a112f357f2e304.tar.bz2 |
2000-07-22 Jason Eckhardt <jle@cygnus.com>
* include/opcode/i860.h (btne, bte, bla): Changed these opcodes
to use sbroff ('r') instead of split16 ('s').
(J, K, L, M): New operand types for 16-bit aligned fields.
(ld.x, {p}fld.x, fst.x, pst.d): Changed these opcodes to
use I, J, K, L, M instead of just I.
(T, U): New operand types for split 16-bit aligned fields.
(st.x): Changed these opcodes to use S, T, U instead of just S.
(andh, andnoth, orh, xorh): Deleted 3-register forms as they do not
exist on the i860.
(pfgt.sd, pfle.sd): Deleted these as they do not exist on the i860.
(pfeq.ss, pfeq.dd): New opcodes.
(st.s): Fixed incorrect mask bits.
(fmlow): Fixed incorrect mask bits.
(fzchkl, pfzchkl): Fixed incorrect mask bits.
(faddz, pfaddz): Fixed incorrect mask bits.
(form, pform): Fixed incorrect mask bits.
(pfld.l): Fixed incorrect mask bits.
(fst.q): Fixed incorrect mask bits.
(all floating point opcodes): Fixed incorrect mask bits for
handling of dual bit.
* include/elf/i860.h: New file.
(elf_i860_reloc_type): Defined ELF32 i860 relocations.
* bfd/cpu-i860.c: Added comments.
* bfd/elf32-i860.c (TARGET_LITTLE_SYM): Defined to
bfd_elf32_i860_little_vec.
(TARGET_LITTLE_NAME): Defined to "elf32-i860-little".
(ELF_MAXPAGESIZE): Changed to 4096.
* bfd/targets.c (bfd_elf32_i860_little_vec): Declaration of
new target.
(bfd_target_vector): Added bfd_elf32_i860_little_vec.
* bfd/config.bfd (i860-stardent-sysv4*, i860-stardent-elf*): Added
config for little endian elf32 i860.
(targ_defvec): Define for the new config above
as "bfd_elf32_i860_little_vec".
(targ_selvecs): Define for the new config above
as "bfd_elf32_i860_vec bfd_elf32_i860_little_vec"
* bfd/configure.in (bfd_elf32_i860_little_vec): Added recognition
of new target vec.
* bfd/configure: Regenerated.
* opcodes/i860-dis.c: New file.
(print_insn_i860): New function.
(print_br_address): New function.
(sign_extend): New function.
(BITWISE_OP): New macro.
(I860_REG_PREFIX): New macro.
(grnames, frnames, crnames): New structures.
* opcodes/disassemble.c (ARCH_i860): Define.
(disassembler): Add check for bfd_arch_i860 to set disassemble
function to print_insn_i860.
* include/dis-asm.h (print_insn_i860): Add prototype.
* opcodes/Makefile.in (CFILES): Added i860-dis.c.
(ALL_MACHINES): Added i860-dis.lo.
(i860-dis.lo): New dependences.
* opcodes/configure.in: New bits for bfd_i860_arch.
* opcodes/configure: Regenerated.
Diffstat (limited to 'opcodes/i860-dis.c')
-rw-r--r-- | opcodes/i860-dis.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/opcodes/i860-dis.c b/opcodes/i860-dis.c new file mode 100644 index 0000000..d969200 --- /dev/null +++ b/opcodes/i860-dis.c @@ -0,0 +1,288 @@ +/* Disassembler for the i860. + Copyright 2000 Free Software Foundation, Inc. + + Contributed by Jason Eckhardt <jle@cygnus.com>. + +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 +the Free Software Foundation; either version 2 of the License, 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. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "dis-asm.h" +#include "opcode/i860.h" + +/* Later we should probably choose the prefix based on which OS flavor. */ +#define I860_REG_PREFIX "%" + +/* Integer register names (encoded as 0..31 in the instruction). */ +static const char *const grnames[] = + {"r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"}; + +/* FP register names (encoded as 0..31 in the instruction). */ +static const char *const frnames[] = + {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; + +/* Control/status register names (encoded as 0..5 in the instruction). */ +static const char *const crnames[] = + {"fir", "psr", "dirbase", "db", "fsr", "epsr", "", ""}; + + +/* Prototypes. */ +static int sign_ext PARAMS((unsigned int, int)); +static void print_br_address PARAMS((disassemble_info *, bfd_vma, int)); + + +/* True if opcode is xor, xorh, and, andh, or, orh, andnot, andnoth. */ +#define BITWISE_OP(op) ((op) == 0x30 || (op) == 0x31 \ + || (op) == 0x34 || (op) == 0x35 \ + || (op) == 0x38 || (op) == 0x39 \ + || (op) == 0x3c || (op) == 0x3d \ + || (op) == 0x33 || (op) == 0x37 \ + || (op) == 0x3b || (op) == 0x3f) + + +/* Sign extend N-bit number. */ +static int +sign_ext (x, n) + unsigned int x; + int n; +{ + int t; + t = x >> (n - 1); + t = ((-t) << n) | x; + return t; +} + + +/* Print a PC-relative branch offset. VAL is the sign extended value + from the branch instruction. */ +static void +print_br_address (info, memaddr, val) + disassemble_info *info; + bfd_vma memaddr; + int val; +{ + + int adj = memaddr + 4 + (val << 2); + + (*info->fprintf_func) (info->stream, "0x%08x", adj); + + /* Attempt to obtain a symbol for the target address. */ + + if (info->print_address_func && adj != 0) + { + (*info->fprintf_func) (info->stream, "\t// "); + (*info->print_address_func) (adj, info); + } +} + + +/* Print one instruction. */ +int +print_insn_i860 (memaddr, info) + bfd_vma memaddr; + disassemble_info *info; +{ + bfd_byte buff[4]; + unsigned int insn, i; + int status; + const struct i860_opcode *opcode = 0; + + status = (*info->read_memory_func) (memaddr, buff, sizeof (buff), info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + /* Note that i860 instructions are always accessed as little endian + data, regardless of the endian mode of the i860. */ + insn = bfd_getl32 (buff); + + status = 0; + i = 0; + while (i860_opcodes[i].name != NULL) + { + opcode = &i860_opcodes[i]; + if ((insn & opcode->match) == opcode->match + && (insn & opcode->lose) == 0) + { + status = 1; + break; + } + ++i; + } + + if (status == 0) + { + /* Instruction not in opcode table. */ + (*info->fprintf_func) (info->stream, ".long %#08x", insn); + } + else + { + const char *s; + int val; + + /* If this a flop and its dual bit is set, prefix with 'd.'. */ + if ((insn & 0xfc000000) == 0x48000000 && (insn & 0x200)) + (*info->fprintf_func) (info->stream, "d.%s\t", opcode->name); + else + (*info->fprintf_func) (info->stream, "%s\t", opcode->name); + + for (s = opcode->args; *s; s++) + { + switch (*s) + { + /* Integer register (src1). */ + case '1': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + grnames[(insn >> 11) & 0x1f]); + break; + + /* Integer register (src2). */ + case '2': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + grnames[(insn >> 21) & 0x1f]); + break; + + /* Integer destination register. */ + case 'd': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + grnames[(insn >> 16) & 0x1f]); + break; + + /* Floating-point register (src1). */ + case 'e': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + frnames[(insn >> 11) & 0x1f]); + break; + + /* Floating-point register (src2). */ + case 'f': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + frnames[(insn >> 21) & 0x1f]); + break; + + /* Floating-point destination register. */ + case 'g': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + frnames[(insn >> 16) & 0x1f]); + break; + + /* Control register. */ + case 'c': + (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, + crnames[(insn >> 21) & 0x7]); + break; + + /* 16-bit immediate (sign extend, except for bitwise ops). */ + case 'i': + if (BITWISE_OP ((insn & 0xfc000000) >> 26)) + (*info->fprintf_func) (info->stream, "0x%04x", + (unsigned int) (insn & 0xffff)); + else + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xffff), 16)); + break; + + /* 16-bit immediate, aligned (2^0, ld.b). */ + case 'I': + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xffff), 16)); + break; + + /* 16-bit immediate, aligned (2^1, ld.s). */ + case 'J': + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xfffe), 16)); + break; + + /* 16-bit immediate, aligned (2^2, ld.l, {p}fld.l, fst.l). */ + case 'K': + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xfffc), 16)); + break; + + /* 16-bit immediate, aligned (2^3, {p}fld.d, fst.d). */ + case 'L': + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xfff8), 16)); + break; + + /* 16-bit immediate, aligned (2^4, {p}fld.q, fst.q). */ + case 'M': + (*info->fprintf_func) (info->stream, "%d", + sign_ext ((insn & 0xfff0), 16)); + break; + + /* 5-bit immediate (zero extend). */ + case '5': + (*info->fprintf_func) (info->stream, "%d", + ((insn >> 11) & 0x1f)); + break; + + /* Split 16 bit immediate (20..16:10..0). */ + case 's': + val = ((insn >> 5) & 0xf800) | (insn & 0x07ff); + (*info->fprintf_func) (info->stream, "%d", + sign_ext (val, 16)); + break; + + /* Split 16 bit immediate, aligned. (2^0, st.b). */ + case 'S': + val = ((insn >> 5) & 0xf800) | (insn & 0x07ff); + (*info->fprintf_func) (info->stream, "%d", + sign_ext (val, 16)); + break; + + /* Split 16 bit immediate, aligned. (2^1, st.s). */ + case 'T': + val = ((insn >> 5) & 0xf800) | (insn & 0x07fe); + (*info->fprintf_func) (info->stream, "%d", + sign_ext (val, 16)); + break; + + /* Split 16 bit immediate, aligned. (2^2, st.l). */ + case 'U': + val = ((insn >> 5) & 0xf800) | (insn & 0x07fc); + (*info->fprintf_func) (info->stream, "%d", + sign_ext (val, 16)); + break; + + /* 26-bit PC relative immediate (lbroff). */ + case 'l': + val = sign_ext ((insn & 0x03ffffff), 26); + print_br_address (info, memaddr, val); + break; + + /* 16-bit PC relative immediate (sbroff). */ + case 'r': + val = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); + print_br_address (info, memaddr, val); + break; + + default: + (*info->fprintf_func) (info->stream, "%c", *s); + break; + } + } + } + + return sizeof (insn); +} + |