diff options
-rw-r--r-- | opcodes/.Sanitize | 1 | ||||
-rw-r--r-- | opcodes/ChangeLog | 7 | ||||
-rw-r--r-- | opcodes/Makefile.in | 7 | ||||
-rw-r--r-- | opcodes/m88k-dis.c | 321 |
4 files changed, 334 insertions, 2 deletions
diff --git a/opcodes/.Sanitize b/opcodes/.Sanitize index a73b2d6..a10b965 100644 --- a/opcodes/.Sanitize +++ b/opcodes/.Sanitize @@ -38,6 +38,7 @@ i386-dis.c i960-dis.c m68881-ext.c m68k-dis.c +m88k-dis.c mips-dis.c sh-opc.h sh-dis.c diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 9f7deaa..d4dce91 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +Thu Jul 15 12:37:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * m88k-dis.c: New file, moved in from gdb and changed to use the + new dis-asm.h disassembler interface. + * Makefile.in (DIS_LIBS): Added m88k-dis.o. + (m88k-dis.o): New target. + Tue Jul 13 10:04:16 1993 Ian Lance Taylor (ian@cygnus.com) * mips-dis.c (print_insn_arg, _print_insn_mips): Made pointer to diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index d550dc9..fee9aab 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -63,8 +63,10 @@ TARGETLIB = libopcodes.a # To circumvent a Sun make VPATH bug, each file listed here # should also have a foo.o: foo.c line further along in this file. -DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o h8300-dis.o dis-buf.o \ - sparc-dis.o a29k-dis.o i960-dis.o alpha-dis.o sh-dis.o hppa-dis.o + +DIS_LIBS = i386-dis.o z8k-dis.o m68k-dis.o mips-dis.o h8500-dis.o \ + h8300-dis.o dis-buf.o sparc-dis.o a29k-dis.o i960-dis.o \ + alpha-dis.o sh-dis.o hppa-dis.o m88k-dis.o OFILES = $(DIS_LIBS) sparc-opc.o m68881-ext.o #### host and target dependent Makefile fragments come in here. @@ -128,6 +130,7 @@ z8k-dis.o: z8k-dis.c z8k-opc.h $(INCDIR)/dis-asm.h sh-dis.o: sh-dis.c sh-opc.h $(INCDIR)/dis-asm.h alpha-dis.o: alpha-dis.c alpha-opc.h $(INCDIR)/dis-asm.h hppa-dis.o: hppa-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/hppa.h +m88k-dis.o: m88k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/m88k.h tags etags: TAGS diff --git a/opcodes/m88k-dis.c b/opcodes/m88k-dis.c new file mode 100644 index 0000000..fec9559 --- /dev/null +++ b/opcodes/m88k-dis.c @@ -0,0 +1,321 @@ +/* Print instructions for the Motorola 88000, for GDB and GNU Binutils. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993 + Free Software Foundation, Inc. + Contributed by Data General Corporation, November 1989. + Partially derived from an earlier printcmd.c. + +This file is part of GDB and the GNU Binutils. + +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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "dis-asm.h" +#include "opcode/m88k.h" + +/* FIXME: Uses the internal bfd swapping routines. */ +#include "libbfd.h" + +INSTAB *hashtable[HASHVAL] = {0}; + +static int +m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *)); + +static void +printop PARAMS ((struct disassemble_info *, OPSPEC *, + unsigned long, bfd_vma, int)); + +static void +init_disasm PARAMS ((void)); + +static void +install PARAMS ((INSTAB *instptr)); + +/* +* Disassemble an M88000 Instruction +* +* +* This module decodes the instruction at memaddr. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date by Motorola +* 05/11/89 R. Trawick adapted to GDB interface. +* 07/12/93 Ian Lance Taylor updated to +* binutils interface. +*/ + +int +print_insn_m88k (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + bfd_byte buffer[4]; + int status; + + /* Instruction addresses may have low two bits set. Clear them. */ + memaddr &=~ (bfd_vma) 3; + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + return m88kdis (memaddr, _do_getb32 (buffer), info); +} + +/* + * disassemble the instruction in 'instruction'. + * 'pc' should be the address of this instruction, it will + * be used to print the target address if this is a relative jump or call + * the disassembled instruction is written to 'info'. + * The function returns the length of this instruction in bytes. + */ + +static int +m88kdis (pc, instruction, info) + bfd_vma pc; + unsigned long instruction; + struct disassemble_info *info; +{ + static int ihashtab_initialized = 0; + unsigned int opcode; + INSTAB *entry_ptr; + int opmask; + int class; + + if (! ihashtab_initialized) + init_disasm (); + + /* create a the appropriate mask to isolate the opcode */ + opmask = DEFMASK; + class = instruction & DEFMASK; + if ((class >= SFU0) && (class <= SFU7)) + { + if (instruction < SFU1) + opmask = CTRLMASK; + else + opmask = SFUMASK; + } + else if (class == RRR) + opmask = RRRMASK; + else if (class == RRI10) + opmask = RRI10MASK; + + /* isolate the opcode */ + opcode = instruction & opmask; + + /* search the hash table with the isolated opcode */ + for (entry_ptr = hashtable[opcode % HASHVAL]; + (entry_ptr != NULL) && (entry_ptr->opcode != opcode); + entry_ptr = entry_ptr->next) + ; + + if (entry_ptr == NULL) + (*info->fprintf_func) (info->stream, "word\t%08x", instruction); + else + { + (*info->fprintf_func) (info->stream, "%s ", entry_ptr->mnemonic); + printop (info, &(entry_ptr->op1), instruction, pc, 1); + printop (info, &(entry_ptr->op2), instruction, pc, 0); + printop (info, &(entry_ptr->op3), instruction, pc, 0); + } + + return 4; +} + +/* +* Decode an Operand of an Instruction +* +* Functional Description +* +* This module formats and writes an operand of an instruction to info +* based on the operand specification. When the first flag is set this +* is the first operand of an instruction. Undefined operand types +* cause a <dis error> message. +* +* Parameters +* disassemble_info where the operand may be printed +* OPSPEC *opptr Pointer to an operand specification +* UINT inst Instruction from which operand is extracted +* UINT pc PC of instruction; used for pc-relative disp. +* int first Flag which if nonzero indicates the first +* operand of an instruction +* +* Output +* +* The operand specified is extracted from the instruction and is +* written to buf in the format specified. The operand is preceded +* by a comma if it is not the first operand of an instruction and it +* is not a register indirect form. Registers are preceded by 'r' and +* hex values by '0x'. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date +*/ + +static void +printop (info, opptr, inst, pc, first) + struct disassemble_info *info; + OPSPEC *opptr; + unsigned long inst; + bfd_vma pc; + int first; +{ + int extracted_field; + char *cond_mask_sym; + + if (opptr->width == 0) + return; + + if (! first) + { + switch (opptr->type) + { + case REGSC: + case CONT: + break; + default: + (*info->fprintf_func) (info->stream, ","); + break; + } + } + + switch (opptr->type) + { + case CRREG: + (*info->fprintf_func) (info->stream, "cr%d", + UEXT (inst, opptr->offset, opptr->width)); + break; + + case FCRREG: + (*info->fprintf_func) (info->stream, "fcr%d", + UEXT (inst, opptr->offset, opptr->width)); + break; + + case REGSC: + (*info->fprintf_func) (info->stream, "[r%d]", + UEXT (inst, opptr->offset, opptr->width)); + break; + + case REG: + (*info->fprintf_func) (info->stream, "r%d", + UEXT (inst, opptr->offset, opptr->width)); + break; + + case HEX: + extracted_field = UEXT (inst, opptr->offset, opptr->width); + if (extracted_field == 0) + (*info->fprintf_func) (info->stream, "0"); + else + (*info->fprintf_func) (info->stream, "0x%02x", extracted_field); + break; + + case CONDMASK: + extracted_field = UEXT (inst, opptr->offset, opptr->width); + switch (extracted_field & 0x0f) + { + case 0x1: cond_mask_sym = "gt0"; break; + case 0x2: cond_mask_sym = "eq0"; break; + case 0x3: cond_mask_sym = "ge0"; break; + case 0xc: cond_mask_sym = "lt0"; break; + case 0xd: cond_mask_sym = "ne0"; break; + case 0xe: cond_mask_sym = "le0"; break; + default: cond_mask_sym = NULL; break; + } + if (cond_mask_sym != NULL) + (*info->fprintf_func) (info->stream, "%s", cond_mask_sym); + else + (*info->fprintf_func) (info->stream, "%x", extracted_field); + break; + + case PCREL: + (*info->print_address_func) + (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))), + info); + break; + + case CONT: + (*info->fprintf_func) (info->stream, "%d,r%d", + UEXT (inst, opptr->offset, 5), + UEXT (inst, (opptr->offset) + 5, 5)); + break; + + case BF: + (*info->fprintf_func) (info->stream, "%d<%d>", + UEXT (inst, (opptr->offset) + 5, 5), + UEXT (inst, opptr->offset, 5)); + break; + + default: + (*info->fprintf_func) (info->stream, "# <dis error: %08x>", inst); + } +} + +/* +* Initialize the Disassembler Instruction Table +* +* Initialize the hash table and instruction table for the disassembler. +* This should be called once before the first call to disasm(). +* +* Parameters +* +* Output +* +* If the debug option is selected, certain statistics about the hashing +* distribution are written to stdout. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date +*/ + +static void +init_disasm () +{ + int i, size; + + for (i = 0; i < HASHVAL; i++) + hashtable[i] = NULL; + + size = sizeof (instructions) / sizeof (INSTAB); + for (i = 0; i < size; i++) + install (&instructions[i]); +} + +/* +* Insert an instruction into the disassembler table by hashing the +* opcode and inserting it into the linked list for that hash value. +* +* Parameters +* +* INSTAB *instptr Pointer to the entry in the instruction table +* to be installed +* +* Revision 1.0 11/08/85 Creation date +* 05/11/89 R. TRAWICK ADAPTED FROM MOTOROLA +*/ + +static void +install (instptr) + INSTAB *instptr; +{ + unsigned int i; + + i = (instptr->opcode) % HASHVAL; + instptr->next = hashtable[i]; + hashtable[i] = instptr; +} |