summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/gdb/objdump
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /gnu/usr.bin/gdb/objdump
initial import of NetBSD tree
Diffstat (limited to 'gnu/usr.bin/gdb/objdump')
-rw-r--r--gnu/usr.bin/gdb/objdump/Makefile32
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/i386/Makefile.inc8
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/i386/i386-pinsn.c1860
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/m68k/Makefile.inc8
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/m68k/m68k-pinsn.c807
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/sparc/Makefile.inc8
-rw-r--r--gnu/usr.bin/gdb/objdump/arch/sparc/sparc-pinsn.c482
-rw-r--r--gnu/usr.bin/gdb/objdump/bucomm.c146
-rw-r--r--gnu/usr.bin/gdb/objdump/filemode.c193
-rw-r--r--gnu/usr.bin/gdb/objdump/objdump.1227
-rw-r--r--gnu/usr.bin/gdb/objdump/objdump.c1087
-rw-r--r--gnu/usr.bin/gdb/objdump/objdump.h2
-rw-r--r--gnu/usr.bin/gdb/objdump/version.c5
13 files changed, 4865 insertions, 0 deletions
diff --git a/gnu/usr.bin/gdb/objdump/Makefile b/gnu/usr.bin/gdb/objdump/Makefile
new file mode 100644
index 00000000000..e5507a9755b
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/Makefile
@@ -0,0 +1,32 @@
+# $Id: Makefile,v 1.1 1995/10/18 08:40:13 deraadt Exp $
+
+# Paths to libraries
+#
+LIBBFD!=cd $(.CURDIR)/../bfd; \
+ printf "xxx:\n\techo \$${.OBJDIR}/libbfd.a\n" | make -r -s -f - xxx
+
+LIBIBERTY!=cd $(.CURDIR)/../libiberty; \
+ printf "xxx:\n\techo \$${.OBJDIR}/libiberty.a\n" | make -r -s -f - xxx
+
+
+PROG= objdump
+
+CFLAGS+= -I$(.CURDIR)/arch/$(MACHINE_ARCH) -I$(.CURDIR)/../bfd \
+ -I$(.CURDIR)/../include \
+ -I$(.CURDIR)/../bfd/arch/$(MACHINE_ARCH) \
+ -I$(.CURDIR)
+
+CFLAGS+= -DVERSION=\"2.0\"
+
+.PATH: $(.CURDIR)/arch/$(MACHINE_ARCH) \
+ $(.CURDIR)/../gdb/arch/$(MACHINE_ARCH)
+
+SRCS= objdump.c bucomm.c filemode.c version.c
+
+LDADD= $(LIBBFD) $(LIBIBERTY)
+DPADD= $(LIBBFD) $(LIBIBERTY)
+
+.include "$(.CURDIR)/arch/$(MACHINE_ARCH)/Makefile.inc"
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
+
diff --git a/gnu/usr.bin/gdb/objdump/arch/i386/Makefile.inc b/gnu/usr.bin/gdb/objdump/arch/i386/Makefile.inc
new file mode 100644
index 00000000000..7c88f86753e
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/i386/Makefile.inc
@@ -0,0 +1,8 @@
+# $Id: Makefile.inc,v 1.1 1995/10/18 08:40:14 deraadt Exp $
+
+SRCS+= i386-pinsn.c
+
+CFLAGS+= -DSELECT_ARCHITECTURES=bfd_arch_i386 \
+ -DPRINT_INSN=print_insn_i386
+
+
diff --git a/gnu/usr.bin/gdb/objdump/arch/i386/i386-pinsn.c b/gnu/usr.bin/gdb/objdump/arch/i386/i386-pinsn.c
new file mode 100644
index 00000000000..8262b89b19a
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/i386/i386-pinsn.c
@@ -0,0 +1,1860 @@
+/* Stolen from GDB on 27 mar 92 by steve chamberlain */
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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. */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual. Usually, there is a capital letter, followed
+ * by a small letter. The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size. Refer to
+ * the Intel manual for details.
+ */
+#include "bfd.h"
+#include "sysdep.h"
+
+#if 0
+#include "defs.h"
+
+#include <ctype.h>
+
+/* For the GDB interface at the bottom of the file... */
+#include "gdbcore.h"
+#endif
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0 /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4 NULL, NULL, 11
+#define GRP5 NULL, NULL, 12
+#define GRP6 NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+ char *name;
+ int (*op1)();
+ int bytemode1;
+ int (*op2)();
+ int bytemode2;
+ int (*op3)();
+ int bytemode3;
+};
+
+struct dis386 dis386[] = {
+ /* 00 */
+ { "addb", Eb, Gb },
+ { "addS", Ev, Gv },
+ { "addb", Gb, Eb },
+ { "addS", Gv, Ev },
+ { "addb", AL, Ib },
+ { "addS", eAX, Iv },
+ { "pushl", es },
+ { "popl", es },
+ /* 08 */
+ { "orb", Eb, Gb },
+ { "orS", Ev, Gv },
+ { "orb", Gb, Eb },
+ { "orS", Gv, Ev },
+ { "orb", AL, Ib },
+ { "orS", eAX, Iv },
+ { "pushl", cs },
+ { "(bad)" }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcb", Eb, Gb },
+ { "adcS", Ev, Gv },
+ { "adcb", Gb, Eb },
+ { "adcS", Gv, Ev },
+ { "adcb", AL, Ib },
+ { "adcS", eAX, Iv },
+ { "pushl", ss },
+ { "popl", ss },
+ /* 18 */
+ { "sbbb", Eb, Gb },
+ { "sbbS", Ev, Gv },
+ { "sbbb", Gb, Eb },
+ { "sbbS", Gv, Ev },
+ { "sbbb", AL, Ib },
+ { "sbbS", eAX, Iv },
+ { "pushl", ds },
+ { "popl", ds },
+ /* 20 */
+ { "andb", Eb, Gb },
+ { "andS", Ev, Gv },
+ { "andb", Gb, Eb },
+ { "andS", Gv, Ev },
+ { "andb", AL, Ib },
+ { "andS", eAX, Iv },
+ { "(bad)" }, /* SEG ES prefix */
+ { "daa" },
+ /* 28 */
+ { "subb", Eb, Gb },
+ { "subS", Ev, Gv },
+ { "subb", Gb, Eb },
+ { "subS", Gv, Ev },
+ { "subb", AL, Ib },
+ { "subS", eAX, Iv },
+ { "(bad)" }, /* SEG CS prefix */
+ { "das" },
+ /* 30 */
+ { "xorb", Eb, Gb },
+ { "xorS", Ev, Gv },
+ { "xorb", Gb, Eb },
+ { "xorS", Gv, Ev },
+ { "xorb", AL, Ib },
+ { "xorS", eAX, Iv },
+ { "(bad)" }, /* SEG SS prefix */
+ { "aaa" },
+ /* 38 */
+ { "cmpb", Eb, Gb },
+ { "cmpS", Ev, Gv },
+ { "cmpb", Gb, Eb },
+ { "cmpS", Gv, Ev },
+ { "cmpb", AL, Ib },
+ { "cmpS", eAX, Iv },
+ { "(bad)" }, /* SEG DS prefix */
+ { "aas" },
+ /* 40 */
+ { "incS", eAX },
+ { "incS", eCX },
+ { "incS", eDX },
+ { "incS", eBX },
+ { "incS", eSP },
+ { "incS", eBP },
+ { "incS", eSI },
+ { "incS", eDI },
+ /* 48 */
+ { "decS", eAX },
+ { "decS", eCX },
+ { "decS", eDX },
+ { "decS", eBX },
+ { "decS", eSP },
+ { "decS", eBP },
+ { "decS", eSI },
+ { "decS", eDI },
+ /* 50 */
+ { "pushS", eAX },
+ { "pushS", eCX },
+ { "pushS", eDX },
+ { "pushS", eBX },
+ { "pushS", eSP },
+ { "pushS", eBP },
+ { "pushS", eSI },
+ { "pushS", eDI },
+ /* 58 */
+ { "popS", eAX },
+ { "popS", eCX },
+ { "popS", eDX },
+ { "popS", eBX },
+ { "popS", eSP },
+ { "popS", eBP },
+ { "popS", eSI },
+ { "popS", eDI },
+ /* 60 */
+ { "pusha" },
+ { "popa" },
+ { "boundS", Gv, Ma },
+ { "arpl", Ew, Gw },
+ { "(bad)" }, /* seg fs */
+ { "(bad)" }, /* seg gs */
+ { "(bad)" }, /* op size prefix */
+ { "(bad)" }, /* adr size prefix */
+ /* 68 */
+ { "pushS", Iv }, /* 386 book wrong */
+ { "imulS", Gv, Ev, Iv },
+ { "pushl", sIb }, /* push of byte really pushes 4 bytes */
+ { "imulS", Gv, Ev, Ib },
+ { "insb", Yb, indirDX },
+ { "insS", Yv, indirDX },
+ { "outsb", indirDX, Xb },
+ { "outsS", indirDX, Xv },
+ /* 70 */
+ { "jo", Jb },
+ { "jno", Jb },
+ { "jb", Jb },
+ { "jae", Jb },
+ { "je", Jb },
+ { "jne", Jb },
+ { "jbe", Jb },
+ { "ja", Jb },
+ /* 78 */
+ { "js", Jb },
+ { "jns", Jb },
+ { "jp", Jb },
+ { "jnp", Jb },
+ { "jl", Jb },
+ { "jnl", Jb },
+ { "jle", Jb },
+ { "jg", Jb },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)" },
+ { GRP1Ss },
+ { "testb", Eb, Gb },
+ { "testS", Ev, Gv },
+ { "xchgb", Eb, Gb },
+ { "xchgS", Ev, Gv },
+ /* 88 */
+ { "movb", Eb, Gb },
+ { "movS", Ev, Gv },
+ { "movb", Gb, Eb },
+ { "movS", Gv, Ev },
+ { "movw", Ew, Sw },
+ { "leaS", Gv, M },
+ { "movw", Sw, Ew },
+ { "popS", Ev },
+ /* 90 */
+ { "nop" },
+ { "xchgS", eCX, eAX },
+ { "xchgS", eDX, eAX },
+ { "xchgS", eBX, eAX },
+ { "xchgS", eSP, eAX },
+ { "xchgS", eBP, eAX },
+ { "xchgS", eSI, eAX },
+ { "xchgS", eDI, eAX },
+ /* 98 */
+ { "cwtl" },
+ { "cltd" },
+ { "lcall", Ap },
+ { "(bad)" }, /* fwait */
+ { "pushf" },
+ { "popf" },
+ { "sahf" },
+ { "lahf" },
+ /* a0 */
+ { "movb", AL, Ob },
+ { "movS", eAX, Ov },
+ { "movb", Ob, AL },
+ { "movS", Ov, eAX },
+ { "movsb", Yb, Xb },
+ { "movsS", Yv, Xv },
+ { "cmpsb", Yb, Xb },
+ { "cmpsS", Yv, Xv },
+ /* a8 */
+ { "testb", AL, Ib },
+ { "testS", eAX, Iv },
+ { "stosb", Yb, AL },
+ { "stosS", Yv, eAX },
+ { "lodsb", AL, Xb },
+ { "lodsS", eAX, Xv },
+ { "scasb", AL, Xb },
+ { "scasS", eAX, Xv },
+ /* b0 */
+ { "movb", AL, Ib },
+ { "movb", CL, Ib },
+ { "movb", DL, Ib },
+ { "movb", BL, Ib },
+ { "movb", AH, Ib },
+ { "movb", CH, Ib },
+ { "movb", DH, Ib },
+ { "movb", BH, Ib },
+ /* b8 */
+ { "movS", eAX, Iv },
+ { "movS", eCX, Iv },
+ { "movS", eDX, Iv },
+ { "movS", eBX, Iv },
+ { "movS", eSP, Iv },
+ { "movS", eBP, Iv },
+ { "movS", eSI, Iv },
+ { "movS", eDI, Iv },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "ret", Iw },
+ { "ret" },
+ { "lesS", Gv, Mp },
+ { "ldsS", Gv, Mp },
+ { "movb", Eb, Ib },
+ { "movS", Ev, Iv },
+ /* c8 */
+ { "enter", Iw, Ib },
+ { "leave" },
+ { "lret", Iw },
+ { "lret" },
+ { "int3" },
+ { "int", Ib },
+ { "into" },
+ { "iret" },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", Ib },
+ { "aad", Ib },
+ { "(bad)" },
+ { "xlat" },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb },
+ { "loope", Jb },
+ { "loop", Jb },
+ { "jCcxz", Jb },
+ { "inb", AL, Ib },
+ { "inS", eAX, Ib },
+ { "outb", Ib, AL },
+ { "outS", Ib, eAX },
+ /* e8 */
+ { "call", Av },
+ { "jmp", Jv },
+ { "ljmp", Ap },
+ { "jmp", Jb },
+ { "inb", AL, indirDX },
+ { "inS", eAX, indirDX },
+ { "outb", indirDX, AL },
+ { "outS", indirDX, eAX },
+ /* f0 */
+ { "(bad)" }, /* lock prefix */
+ { "(bad)" },
+ { "(bad)" }, /* repne */
+ { "(bad)" }, /* repz */
+ { "hlt" },
+ { "cmc" },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc" },
+ { "stc" },
+ { "cli" },
+ { "sti" },
+ { "cld" },
+ { "std" },
+ { GRP4 },
+ { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", Gv, Ew },
+ { "lslS", Gv, Ew },
+ { "(bad)" },
+ { "(bad)" },
+ { "clts" },
+ { "(bad)" },
+ /* 08 */
+ { "invd" },
+ { "wbinvd" },
+ { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 10 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 18 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "movl", Rd, Cd },
+ { "movl", Rd, Dd },
+ { "movl", Cd, Rd },
+ { "movl", Dd, Rd },
+ { "movl", Rd, Td },
+ { "(bad)" },
+ { "movl", Td, Rd },
+ { "(bad)" },
+ /* 28 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 30 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 38 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 40 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 48 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 50 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 58 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 60 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 68 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 70 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 78 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 80 */
+ { "jo", Jv },
+ { "jno", Jv },
+ { "jb", Jv },
+ { "jae", Jv },
+ { "je", Jv },
+ { "jne", Jv },
+ { "jbe", Jv },
+ { "ja", Jv },
+ /* 88 */
+ { "js", Jv },
+ { "jns", Jv },
+ { "jp", Jv },
+ { "jnp", Jv },
+ { "jl", Jv },
+ { "jge", Jv },
+ { "jle", Jv },
+ { "jg", Jv },
+ /* 90 */
+ { "seto", Eb },
+ { "setno", Eb },
+ { "setb", Eb },
+ { "setae", Eb },
+ { "sete", Eb },
+ { "setne", Eb },
+ { "setbe", Eb },
+ { "seta", Eb },
+ /* 98 */
+ { "sets", Eb },
+ { "setns", Eb },
+ { "setp", Eb },
+ { "setnp", Eb },
+ { "setl", Eb },
+ { "setge", Eb },
+ { "setle", Eb },
+ { "setg", Eb },
+ /* a0 */
+ { "pushl", fs },
+ { "popl", fs },
+ { "cpuid" },
+ { "btS", Ev, Gv },
+ { "shldS", Ev, Gv, Ib },
+ { "shldS", Ev, Gv, CL },
+ { "(bad)" },
+ { "(bad)" },
+ /* a8 */
+ { "pushl", gs },
+ { "popl", gs },
+ { "(bad)" },
+ { "btsS", Ev, Gv },
+ { "shrdS", Ev, Gv, Ib },
+ { "shrdS", Ev, Gv, CL },
+ { "(bad)" },
+ { "imulS", Gv, Ev },
+ /* b0 */
+ { "cmpxchgb", Eb, Gb },
+ { "cmpxchgS", Ev, Gv },
+ { "lssS", Gv, Mp }, /* 386 lists only Mp */
+ { "btrS", Ev, Gv },
+ { "lfsS", Gv, Mp }, /* 386 lists only Mp */
+ { "lgsS", Gv, Mp }, /* 386 lists only Mp */
+ { "movzbS", Gv, Eb },
+ { "movzwS", Gv, Ew },
+ /* b8 */
+ { "(bad)" },
+ { "(bad)" },
+ { GRP8 },
+ { "btcS", Ev, Gv },
+ { "bsfS", Gv, Ev },
+ { "bsrS", Gv, Ev },
+ { "movsbS", Gv, Eb },
+ { "movswS", Gv, Ew },
+ /* c0 */
+ { "xaddb", Eb, Gb },
+ { "xaddS", Ev, Gv },
+ { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* c8 */
+ { "bswap", eAX },
+ { "bswap", eCX },
+ { "bswap", eDX },
+ { "bswap", eBX },
+ { "bswap", eSP },
+ { "bswap", eBP },
+ { "bswap", eSI },
+ { "bswap", eDI },
+ /* d0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static int mod;
+static int rm;
+static int reg;
+static void oappend ();
+
+static char *names32[]={
+ "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+ "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+ "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+
+struct dis386 grps[][8] = {
+ /* GRP1b */
+ {
+ { "addb", Eb, Ib },
+ { "orb", Eb, Ib },
+ { "adcb", Eb, Ib },
+ { "sbbb", Eb, Ib },
+ { "andb", Eb, Ib },
+ { "subb", Eb, Ib },
+ { "xorb", Eb, Ib },
+ { "cmpb", Eb, Ib }
+ },
+ /* GRP1S */
+ {
+ { "addS", Ev, Iv },
+ { "orS", Ev, Iv },
+ { "adcS", Ev, Iv },
+ { "sbbS", Ev, Iv },
+ { "andS", Ev, Iv },
+ { "subS", Ev, Iv },
+ { "xorS", Ev, Iv },
+ { "cmpS", Ev, Iv }
+ },
+ /* GRP1Ss */
+ {
+ { "addS", Ev, sIb },
+ { "orS", Ev, sIb },
+ { "adcS", Ev, sIb },
+ { "sbbS", Ev, sIb },
+ { "andS", Ev, sIb },
+ { "subS", Ev, sIb },
+ { "xorS", Ev, sIb },
+ { "cmpS", Ev, sIb }
+ },
+ /* GRP2b */
+ {
+ { "rolb", Eb, Ib },
+ { "rorb", Eb, Ib },
+ { "rclb", Eb, Ib },
+ { "rcrb", Eb, Ib },
+ { "shlb", Eb, Ib },
+ { "shrb", Eb, Ib },
+ { "(bad)" },
+ { "sarb", Eb, Ib },
+ },
+ /* GRP2S */
+ {
+ { "rolS", Ev, Ib },
+ { "rorS", Ev, Ib },
+ { "rclS", Ev, Ib },
+ { "rcrS", Ev, Ib },
+ { "shlS", Ev, Ib },
+ { "shrS", Ev, Ib },
+ { "(bad)" },
+ { "sarS", Ev, Ib },
+ },
+ /* GRP2b_one */
+ {
+ { "rolb", Eb },
+ { "rorb", Eb },
+ { "rclb", Eb },
+ { "rcrb", Eb },
+ { "shlb", Eb },
+ { "shrb", Eb },
+ { "(bad)" },
+ { "sarb", Eb },
+ },
+ /* GRP2S_one */
+ {
+ { "rolS", Ev },
+ { "rorS", Ev },
+ { "rclS", Ev },
+ { "rcrS", Ev },
+ { "shlS", Ev },
+ { "shrS", Ev },
+ { "(bad)" },
+ { "sarS", Ev },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolb", Eb, CL },
+ { "rorb", Eb, CL },
+ { "rclb", Eb, CL },
+ { "rcrb", Eb, CL },
+ { "shlb", Eb, CL },
+ { "shrb", Eb, CL },
+ { "(bad)" },
+ { "sarb", Eb, CL },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolS", Ev, CL },
+ { "rorS", Ev, CL },
+ { "rclS", Ev, CL },
+ { "rcrS", Ev, CL },
+ { "shlS", Ev, CL },
+ { "shrS", Ev, CL },
+ { "(bad)" },
+ { "sarS", Ev, CL }
+ },
+ /* GRP3b */
+ {
+ { "testb", Eb, Ib },
+ { "(bad)", Eb },
+ { "notb", Eb },
+ { "negb", Eb },
+ { "mulb", AL, Eb },
+ { "imulb", AL, Eb },
+ { "divb", AL, Eb },
+ { "idivb", AL, Eb }
+ },
+ /* GRP3S */
+ {
+ { "testS", Ev, Iv },
+ { "(bad)" },
+ { "notS", Ev },
+ { "negS", Ev },
+ { "mulS", eAX, Ev },
+ { "imulS", eAX, Ev },
+ { "divS", eAX, Ev },
+ { "idivS", eAX, Ev },
+ },
+ /* GRP4 */
+ {
+ { "incb", Eb },
+ { "decb", Eb },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* GRP5 */
+ {
+ { "incS", Ev },
+ { "decS", Ev },
+ { "call", indirEv },
+ { "lcall", indirEv },
+ { "jmp", indirEv },
+ { "ljmp", indirEv },
+ { "pushS", Ev },
+ { "(bad)" },
+ },
+ /* GRP6 */
+ {
+ { "sldt", Ew },
+ { "str", Ew },
+ { "lldt", Ew },
+ { "ltr", Ew },
+ { "verr", Ew },
+ { "verw", Ew },
+ { "(bad)" },
+ { "(bad)" }
+ },
+ /* GRP7 */
+ {
+ { "sgdt", Ew },
+ { "sidt", Ew },
+ { "lgdt", Ew },
+ { "lidt", Ew },
+ { "smsw", Ew },
+ { "(bad)" },
+ { "lmsw", Ew },
+ { "invlpg", Ew },
+ },
+ /* GRP8 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "btS", Ev, Ib },
+ { "btsS", Ev, Ib },
+ { "btrS", Ev, Ib },
+ { "btcS", Ev, Ib },
+ }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+ckprefix ()
+{
+ prefixes = 0;
+ while (1)
+ {
+ switch (*codep)
+ {
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADR;
+ break;
+ case 0x9b:
+ prefixes |= PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ codep++;
+ }
+}
+
+static int dflag;
+static int aflag;
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+
+
+/*
+ * disassemble the first instruction in 'inbuf'. You have to make
+ * sure all of the bytes of the instruction are filled in.
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * '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
+ * 'outbuf' gets filled in with the disassembled instruction. it should
+ * be long enough to hold the longest disassembled instruction.
+ * 100 bytes is certainly enough, unless symbol printing is added later
+ * The function returns the length of this instruction in bytes.
+ */
+i386dis (pc, inbuf, stream)
+ int pc;
+ unsigned char *inbuf;
+ FILE *stream;
+{
+ struct dis386 *dp;
+ char *p;
+ int i;
+ int enter_instruction;
+ char *first, *second, *third;
+ int needcomma;
+
+ obuf[0] = 0;
+ op1out[0] = 0;
+ op2out[0] = 0;
+ op3out[0] = 0;
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
+
+ start_pc = pc;
+ start_codep = inbuf;
+ codep = inbuf;
+
+ ckprefix ();
+
+ if (*codep == 0xc8)
+ enter_instruction = 1;
+ else
+ enter_instruction = 0;
+
+ obufp = obuf;
+
+ if (prefixes & PREFIX_REPZ)
+ oappend ("repz ");
+ if (prefixes & PREFIX_REPNZ)
+ oappend ("repnz ");
+ if (prefixes & PREFIX_LOCK)
+ oappend ("lock ");
+
+ if ((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ {
+ /* fwait not followed by floating point instruction */
+ fputs ("fwait", stream);
+ return (1);
+ }
+
+ /* these would be initialized to 0 if disassembling for 8086 or 286 */
+ dflag = 1;
+ aflag = 1;
+
+ if (prefixes & PREFIX_DATA)
+ dflag ^= 1;
+
+ if (prefixes & PREFIX_ADR)
+ {
+ aflag ^= 1;
+ oappend ("addr16 ");
+ }
+
+ if (*codep == 0x0f)
+ dp = &dis386_twobyte[*++codep];
+ else
+ dp = &dis386[*codep];
+ codep++;
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+
+ if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+ {
+ dofloat ();
+ }
+ else
+ {
+ if (dp->name == NULL)
+ dp = &grps[dp->bytemode1][reg];
+
+ putop (dp->name);
+
+ obufp = op1out;
+ op_ad = 2;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+
+ obufp = op2out;
+ op_ad = 1;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+
+ obufp = op3out;
+ op_ad = 0;
+ if (dp->op3)
+ (*dp->op3)(dp->bytemode3);
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+ fputs (obuf, stream);
+
+ /* enter instruction is printed with operands in the
+ * same order as the intel book; everything else
+ * is printed in reverse order
+ */
+ if (enter_instruction)
+ {
+ first = op1out;
+ second = op2out;
+ third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
+ }
+ else
+ {
+ first = op3out;
+ second = op2out;
+ third = op1out;
+ }
+ needcomma = 0;
+ if (*first)
+ {
+ if (op_index[0] != -1)
+ print_address (op_address[op_index[0]], stream);
+ else
+ fputs (first, stream);
+ needcomma = 1;
+ }
+ if (*second)
+ {
+ if (needcomma)
+ fputs (",", stream);
+ if (op_index[1] != -1)
+ print_address (op_address[op_index[1]], stream);
+ else
+ fputs (second, stream);
+ needcomma = 1;
+ }
+ if (*third)
+ {
+ if (needcomma)
+ fputs (",", stream);
+ if (op_index[2] != -1)
+ print_address (op_address[op_index[2]], stream);
+ else
+ fputs (third, stream);
+ }
+ return (codep - inbuf);
+}
+
+char *float_mem[] = {
+ /* d8 */
+ "fadds",
+ "fmuls",
+ "fcoms",
+ "fcomps",
+ "fsubs",
+ "fsubrs",
+ "fdivs",
+ "fdivrs",
+ /* d9 */
+ "flds",
+ "(bad)",
+ "fsts",
+ "fstps",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiaddl",
+ "fimull",
+ "ficoml",
+ "ficompl",
+ "fisubl",
+ "fisubrl",
+ "fidivl",
+ "fidivrl",
+ /* db */
+ "fildl",
+ "(bad)",
+ "fistl",
+ "fistpl",
+ "(bad)",
+ "fldt",
+ "(bad)",
+ "fstpt",
+ /* dc */
+ "faddl",
+ "fmull",
+ "fcoml",
+ "fcompl",
+ "fsubl",
+ "fsubrl",
+ "fdivl",
+ "fdivrl",
+ /* dd */
+ "fldl",
+ "(bad)",
+ "fstl",
+ "fstpl",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fildll",
+ "fbstp",
+ "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", ST, STi },
+ { "fmul", ST, STi },
+ { "fcom", STi },
+ { "fcomp", STi },
+ { "fsub", ST, STi },
+ { "fsubr", ST, STi },
+ { "fdiv", ST, STi },
+ { "fdivr", ST, STi },
+ },
+ /* d9 */
+ {
+ { "fld", STi },
+ { "fxch", STi },
+ { FGRPd9_2 },
+ { "(bad)" },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPda_5 },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* db */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdb_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* dc */
+ {
+ { "fadd", STi, ST },
+ { "fmul", STi, ST },
+ { "(bad)" },
+ { "(bad)" },
+ { "fsub", STi, ST },
+ { "fsubr", STi, ST },
+ { "fdiv", STi, ST },
+ { "fdivr", STi, ST },
+ },
+ /* dd */
+ {
+ { "ffree", STi },
+ { "(bad)" },
+ { "fst", STi },
+ { "fstp", STi },
+ { "fucom", STi },
+ { "fucomp", STi },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* de */
+ {
+ { "faddp", STi, ST },
+ { "fmulp", STi, ST },
+ { "(bad)" },
+ { FGRPde_3 },
+ { "fsubp", STi, ST },
+ { "fsubrp", STi, ST },
+ { "fdivp", STi, ST },
+ { "fdivrp", STi, ST },
+ },
+ /* df */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdf_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+};
+
+
+char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+
+dofloat ()
+{
+ struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (mod != 3)
+ {
+ putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ obufp = op1out;
+ OP_E (v_mode);
+ return;
+ }
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->bytemode1][rm]);
+ /* instruction fnstsw is only one with strange arg */
+ if (floatop == 0xdf && *codep == 0xe0)
+ strcpy (op1out, "%eax");
+ }
+ else
+ {
+ putop (dp->name);
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+ }
+}
+
+/* ARGSUSED */
+OP_ST (ignore)
+{
+ oappend ("%st");
+}
+
+/* ARGSUSED */
+OP_STi (ignore)
+{
+ sprintf (scratchbuf, "%%st(%d)", rm);
+ oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+putop (template)
+ char *template;
+{
+ char *p;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case 'C': /* For jcxz/jecxz */
+ if (aflag == 0)
+ *obufp++ = 'e';
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ break;
+ case 'S':
+ /* operand size flag */
+ if (dflag)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ break;
+ }
+ }
+ *obufp = 0;
+}
+
+static void
+oappend (s)
+char *s;
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+ *obufp = 0;
+}
+
+append_prefix ()
+{
+ if (prefixes & PREFIX_CS)
+ oappend ("%cs:");
+ if (prefixes & PREFIX_DS)
+ oappend ("%ds:");
+ if (prefixes & PREFIX_SS)
+ oappend ("%ss:");
+ if (prefixes & PREFIX_ES)
+ oappend ("%es:");
+ if (prefixes & PREFIX_FS)
+ oappend ("%fs:");
+ if (prefixes & PREFIX_GS)
+ oappend ("%gs:");
+}
+
+OP_indirE (bytemode)
+{
+ oappend ("*");
+ OP_E (bytemode);
+}
+
+OP_E (bytemode)
+{
+ int disp;
+ int havesib;
+ int didoutput = 0;
+ int base;
+ int index;
+ int scale;
+ int havebase;
+
+ /* skip mod/rm byte */
+ codep++;
+
+ havesib = 0;
+ havebase = 0;
+ disp = 0;
+
+ if (mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[rm]);
+ else
+ oappend (names16[rm]);
+ break;
+ default:
+ oappend ("<bad dis table>");
+ break;
+ }
+ return;
+ }
+
+ append_prefix ();
+ if (rm == 4)
+ {
+ havesib = 1;
+ havebase = 1;
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
+ {
+ case 0:
+ switch (rm)
+ {
+ case 4:
+ /* implies havesib and havebase */
+ if (base == 5) {
+ havebase = 0;
+ disp = get32 ();
+ }
+ break;
+ case 5:
+ disp = get32 ();
+ break;
+ default:
+ havebase = 1;
+ base = rm;
+ break;
+ }
+ break;
+ case 1:
+ disp = *(char *)codep++;
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ case 2:
+ disp = get32 ();
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ }
+
+ if (mod != 0 || rm == 5 || (havesib && base == 5))
+ {
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ }
+
+ if (havebase || havesib)
+ {
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ oappend (")");
+ }
+}
+
+OP_G (bytemode)
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[reg]);
+ break;
+ case w_mode:
+ oappend (names16[reg]);
+ break;
+ case d_mode:
+ oappend (names32[reg]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[reg]);
+ else
+ oappend (names16[reg]);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+get32 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ x |= (*codep++ & 0xff) << 16;
+ x |= (*codep++ & 0xff) << 24;
+ return (x);
+}
+
+get16 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return (x);
+}
+
+set_op (op)
+int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+OP_REG (code)
+{
+ char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg: s = "(%dx)"; break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ if (dflag)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ break;
+ default:
+ s = "<internal disassembler error>";
+ break;
+ }
+ oappend (s);
+}
+
+OP_I (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *codep++ & 0xff;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = get16 ();
+ break;
+ case w_mode:
+ op = get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_sI (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = (short)get16();
+ break;
+ case w_mode:
+ op = (short)get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_J (bytemode)
+{
+ int disp;
+ int mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ disp = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ disp = get32 ();
+ else
+ {
+ disp = (short)get16 ();
+ /* for some reason, a data16 prefix on a jump instruction
+ means that the pc is masked to 16 bits after the
+ displacement is added! */
+ mask = 0xffff;
+ }
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ disp = (start_pc + codep - start_codep + disp) & mask;
+ set_op (disp);
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_SEG (dummy)
+{
+ static char *sreg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+
+ oappend (sreg[reg]);
+}
+
+OP_DIR (size)
+{
+ int seg, offset;
+
+ switch (size)
+ {
+ case lptr:
+ if (aflag)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+ oappend (scratchbuf);
+ break;
+ case v_mode:
+ if (aflag)
+ offset = get32 ();
+ else
+ offset = (short)get16 ();
+
+ offset = start_pc + codep - start_codep + offset;
+ set_op (offset);
+ sprintf (scratchbuf, "0x%x", offset);
+ oappend (scratchbuf);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+/* ARGSUSED */
+OP_OFF (bytemode)
+{
+ int off;
+
+ if (aflag)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ sprintf (scratchbuf, "0x%x", off);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_ESDI (dummy)
+{
+ oappend ("%es:(");
+ oappend (aflag ? "%edi" : "%di");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_DSSI (dummy)
+{
+ oappend ("%ds:(");
+ oappend (aflag ? "%esi" : "%si");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_ONE (dummy)
+{
+ oappend ("1");
+}
+
+/* ARGSUSED */
+OP_C (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%cr%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_D (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%db%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_T (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%tr%d", reg);
+ oappend (scratchbuf);
+}
+
+OP_rm (bytemode)
+{
+ switch (bytemode)
+ {
+ case d_mode:
+ oappend (names32[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ }
+}
+#define MAXLEN 20
+#if 0
+
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ return (i386dis ((int)memaddr, buffer, stream));
+}
+
+#endif
+
+int
+print_insn_i386(memaddr, buffer, stream)
+int memaddr;
+ char *buffer;
+ FILE *stream;
+{
+
+
+ return (i386dis ((int)memaddr, buffer, stream));
+
+
+}
diff --git a/gnu/usr.bin/gdb/objdump/arch/m68k/Makefile.inc b/gnu/usr.bin/gdb/objdump/arch/m68k/Makefile.inc
new file mode 100644
index 00000000000..47c4ad64fbe
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/m68k/Makefile.inc
@@ -0,0 +1,8 @@
+# $Id: Makefile.inc,v 1.1 1995/10/18 08:40:14 deraadt Exp $
+
+SRCS+= m68k-pinsn.c
+
+CFLAGS+= -DSELECT_ARCHITECTURES=bfd_arch_m68k \
+ -DPRINT_INSN=print_insn_m68k
+
+
diff --git a/gnu/usr.bin/gdb/objdump/arch/m68k/m68k-pinsn.c b/gnu/usr.bin/gdb/objdump/arch/m68k/m68k-pinsn.c
new file mode 100644
index 00000000000..4040ae92b2d
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/m68k/m68k-pinsn.c
@@ -0,0 +1,807 @@
+/* Print m68k instructions for objdump
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+
+This file is part of the binutils.
+
+The binutils are 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, or (at your option)
+any later version.
+
+The binutils are distributed in the hope that they 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 the binutils; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include <stdio.h>
+#include "opcode/m68k.h"
+
+#ifndef GDB
+#define fprintf_filtered fprintf
+#define fputs_filtered fputs
+#endif
+
+/* Sign-extend an (unsigned char). */
+#if __STDC__ == 1
+#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
+#else
+#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
+#endif
+
+extern void print_address();
+
+/* 68k instructions are never longer than this many bytes. */
+#define MAXLEN 22
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
+
+extern char *reg_names[];
+char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
+ "fpiar/fpcr", "fpsr/fpcr", "fpiar/fpsr/fpcr"};
+
+char *reg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc"};
+static unsigned char *print_insn_arg ();
+static unsigned char *print_indexed ();
+static void print_base ();
+static int fetch_arg ();
+
+#define NEXTBYTE(p) (p += 2, COERCE_SIGNED_CHAR(p[-1]))
+
+#define NEXTWORD(p) \
+ (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
+
+#define NEXTLONG(p) \
+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+/* NEXTSINGLE and NEXTDOUBLE handle alignment problems, but not
+ * byte-swapping or other float format differences. FIXME! */
+
+union number {
+ double d;
+ float f;
+ char c[10];
+};
+
+#define NEXTSINGLE(val, p) \
+ { int i; union number u;\
+ for (i = 0; i < sizeof(float); i++) u.c[i] = *p++; \
+ val = u.f; }
+
+#define NEXTDOUBLE(val, p) \
+ { int i; union number u;\
+ for (i = 0; i < sizeof(double); i++) u.c[i] = *p++; \
+ val = u.d; }
+
+#define NEXTEXTEND(p) \
+ (p += 12, 0.0) /* Need a function to convert from extended to double
+ precision... */
+
+#define NEXTPACKED(p) \
+ (p += 12, 0.0) /* Need a function to convert from packed to double
+ precision. Actually, it's easier to print a
+ packed number than a double anyway, so maybe
+ there should be a special case to handle this... */
+
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn_m68k(addr, buffer, stream)
+ bfd_vma addr;
+unsigned char *buffer;
+ FILE *stream;
+{
+ register unsigned int i;
+ register unsigned char *p;
+ register char *d;
+ register unsigned int bestmask;
+ int best;
+
+
+
+ bestmask = 0;
+ best = -1;
+ for (i = 0; i < NOPCODES; i++)
+ {
+ register unsigned int opcode = m68k_opcodes[i].opcode;
+ register unsigned int match = m68k_opcodes[i].match;
+ if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
+ && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
+ && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
+ && ((0xff & buffer[3] & match) == (0xff & opcode)))
+ {
+ /* Don't use for printout the variants of divul and divsl
+ that have the same register number in two places.
+ The more general variants will match instead. */
+ for (d = m68k_opcodes[i].args; *d; d += 2)
+ if (d[1] == 'D')
+ break;
+
+ /* Don't use for printout the variants of most floating
+ point coprocessor instructions which use the same
+ register number in two places, as above. */
+ if (*d == 0)
+ for (d = m68k_opcodes[i].args; *d; d += 2)
+ if (d[1] == 't')
+ break;
+
+ if (*d == 0 && match > bestmask)
+ {
+ best = i;
+ bestmask = match;
+ }
+ }
+ }
+
+ /* Handle undefined instructions. */
+ if (best < 0)
+ {
+ fprintf_filtered (stream, "0%o", (unsigned) (buffer[0] << 8) + buffer[1]);
+ return 2;
+ }
+
+ fprintf_filtered (stream, "%s", m68k_opcodes[best].name);
+
+ /* Point at first word of argument data,
+ and at descriptor for first argument. */
+ p = buffer + 2;
+
+ /* Why do this this way? -MelloN */
+ for (d = m68k_opcodes[best].args; *d; d += 2)
+ {
+ if (d[0] == '#')
+ {
+ if (d[1] == 'l' && p - buffer < 6)
+ p = buffer + 6;
+ else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
+ p = buffer + 4;
+ }
+ if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
+ p = buffer + 4;
+ if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
+ p = buffer + 6;
+ if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
+ p = buffer + 4;
+ }
+
+ d = m68k_opcodes[best].args;
+
+ if (*d)
+ fputs_filtered (" ", stream);
+
+ while (*d)
+ {
+ p = print_insn_arg (d, buffer, p, addr + p - buffer, stream);
+ d += 2;
+ if (*d && *(d - 2) != 'I' && *d != 'k')
+ fputs_filtered (",", stream);
+ }
+ return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, buffer, p, addr, stream)
+ char *d;
+ unsigned char *buffer;
+ register unsigned char *p;
+ bfd_vma addr; /* PC for this arg to be relative to */
+ FILE *stream;
+{
+ register int val = 0;
+ register int place = d[1];
+ int regno;
+ register char *regname;
+ register unsigned char *p1;
+ register double flval = 0;
+ int flt_p;
+
+ switch (*d)
+ {
+ case 'C':
+ fprintf_filtered (stream, "ccr");
+ break;
+
+ case 'S':
+ fprintf_filtered (stream, "sr");
+ break;
+
+ case 'U':
+ fprintf_filtered (stream, "usp");
+ break;
+
+ case 'J':
+ {
+ static struct { char *name; int value; } names[]
+ = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
+ {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
+ {"msp", 0x803}, {"isp", 0x804}};
+
+ val = fetch_arg (buffer, place, 12);
+ for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
+ if (names[regno].value == val)
+ {
+ fprintf_filtered (stream, names[regno].name);
+ break;
+ }
+ if (regno < 0)
+ fprintf_filtered (stream, "%d", val);
+ }
+ break;
+
+ case 'Q':
+ val = fetch_arg (buffer, place, 3);
+ /* 0 means 8, except for the bkpt instruction... */
+ if (val == 0 && d[1] != 's')
+ val = 8;
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'M':
+ val = fetch_arg (buffer, place, 8);
+ if (val & 0x80)
+ val = val - 0x100;
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'T':
+ val = fetch_arg (buffer, place, 4);
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'D':
+ fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
+ break;
+
+ case 'A':
+ fprintf_filtered (stream, "%s",
+ reg_names[fetch_arg (buffer, place, 3) + 010]);
+ break;
+
+ case 'R':
+ fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
+ break;
+
+ case 'r':
+ fprintf_filtered (stream, "%s@", reg_names[fetch_arg (buffer, place, 4)]);
+ break;
+
+ case 'F':
+ fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3));
+ break;
+
+ case 'O':
+ val = fetch_arg (buffer, place, 6);
+ if (val & 0x20)
+ fprintf_filtered (stream, "%s", reg_names [val & 7]);
+ else
+ fprintf_filtered (stream, "%d", val);
+ break;
+
+ case '+':
+ fprintf_filtered (stream, "%s@+",
+ reg_names[fetch_arg (buffer, place, 3) + 8]);
+ break;
+
+ case '-':
+ fprintf_filtered (stream, "%s@-",
+ reg_names[fetch_arg (buffer, place, 3) + 8]);
+ break;
+
+ case 'k':
+ if (place == 'k')
+ fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
+ else if (place == 'C')
+ {
+ val = fetch_arg (buffer, place, 7);
+ if ( val > 63 ) /* This is a signed constant. */
+ val -= 128;
+ fprintf_filtered (stream, "{#%d}", val);
+ }
+ else
+ fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ break;
+
+ case '#':
+ case '^':
+ p1 = buffer + (*d == '#' ? 2 : 4);
+ if (place == 's')
+ val = fetch_arg (buffer, place, 4);
+ else if (place == 'C')
+ val = fetch_arg (buffer, place, 7);
+ else if (place == '8')
+ val = fetch_arg (buffer, place, 3);
+ else if (place == '3')
+ val = fetch_arg (buffer, place, 8);
+ else if (place == 'b')
+ val = NEXTBYTE (p1);
+ else if (place == 'w')
+ val = NEXTWORD (p1);
+ else if (place == 'l')
+ val = NEXTLONG (p1);
+ else
+ fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'B':
+ if (place == 'b')
+ val = NEXTBYTE (p);
+ else if (place == 'B')
+ val = COERCE_SIGNED_CHAR(buffer[1]);
+ else if (place == 'w' || place == 'W')
+ val = NEXTWORD (p);
+ else if (place == 'l' || place == 'L')
+ val = NEXTLONG (p);
+ else if (place == 'g')
+ {
+ val = ((char *)buffer)[1];
+ if (val == 0)
+ val = NEXTWORD (p);
+ else if (val == -1)
+ val = NEXTLONG (p);
+ }
+ else if (place == 'c')
+ {
+ if (buffer[1] & 0x40) /* If bit six is one, long offset */
+ val = NEXTLONG (p);
+ else
+ val = NEXTWORD (p);
+ }
+ else
+ fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ print_address (addr + val, stream);
+ break;
+
+ case 'd':
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "%s@(%d)",
+ reg_names[fetch_arg (buffer, place, 3)], val);
+ break;
+
+ case 's':
+ fprintf_filtered (stream, "%s",
+ fpcr_names[fetch_arg (buffer, place, 3)]);
+ break;
+
+ case 'I':
+ val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
+ if (val != 1) /* Unusual coprocessor ID? */
+ fprintf_filtered (stream, "(cpid=%d) ", val);
+ if (place == 'i')
+ p += 2; /* Skip coprocessor extended operands */
+ break;
+
+ case '*':
+ case '~':
+ case '%':
+ case ';':
+ case '@':
+ case '!':
+ case '$':
+ case '?':
+ case '/':
+ case '&':
+
+ if (place == 'd')
+ {
+ val = fetch_arg (buffer, 'x', 6);
+ val = ((val & 7) << 3) + ((val >> 3) & 7);
+ }
+ else
+ val = fetch_arg (buffer, 's', 6);
+
+ /* Get register number assuming address register. */
+ regno = (val & 7) + 8;
+ regname = reg_names[regno];
+ switch (val >> 3)
+ {
+ case 0:
+ fprintf_filtered (stream, "%s", reg_names[val]);
+ break;
+
+ case 1:
+ fprintf_filtered (stream, "%s", regname);
+ break;
+
+ case 2:
+ fprintf_filtered (stream, "%s@", regname);
+ break;
+
+ case 3:
+ fprintf_filtered (stream, "%s@+", regname);
+ break;
+
+ case 4:
+ fprintf_filtered (stream, "%s@-", regname);
+ break;
+
+ case 5:
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "%s@(%d)", regname, val);
+ break;
+
+ case 6:
+ p = print_indexed (regno, p, addr, stream);
+ break;
+
+ case 7:
+ switch (val & 7)
+ {
+ case 0:
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "@#");
+ print_address (val, stream);
+ break;
+
+ case 1:
+ val = NEXTLONG (p);
+ fprintf_filtered (stream, "@#");
+ print_address (val, stream);
+ break;
+
+ case 2:
+ val = NEXTWORD (p);
+ print_address (addr + val, stream);
+ break;
+
+ case 3:
+ p = print_indexed (-1, p, addr, stream);
+ break;
+
+ case 4:
+ flt_p = 1; /* Assume it's a float... */
+ switch( place )
+ {
+ case 'b':
+ val = NEXTBYTE (p);
+ flt_p = 0;
+ break;
+
+ case 'w':
+ val = NEXTWORD (p);
+ flt_p = 0;
+ break;
+
+ case 'l':
+ val = NEXTLONG (p);
+ flt_p = 0;
+ break;
+
+ case 'f':
+ NEXTSINGLE(flval, p);
+ break;
+
+ case 'F':
+ NEXTDOUBLE(flval, p);
+ break;
+
+ case 'x':
+ flval = NEXTEXTEND(p);
+ break;
+
+ case 'p':
+ flval = NEXTPACKED(p);
+ break;
+
+ default:
+ fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ }
+ if ( flt_p ) /* Print a float? */
+ fprintf_filtered (stream, "#%g", flval);
+ else
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ default:
+ fprintf_filtered (stream, "<invalid address mode 0%o>", (unsigned) val);
+ }
+ }
+ break;
+
+ case 'L':
+ case 'l':
+ if (place == 'w')
+ {
+ char doneany;
+ p1 = buffer + 2;
+ val = NEXTWORD (p1);
+ /* Move the pointer ahead if this point is farther ahead
+ than the last. */
+ p = p1 > p ? p1 : p;
+ if (val == 0)
+ {
+ fputs_filtered ("#0", stream);
+ break;
+ }
+ if (*d == 'l')
+ {
+ register int newval = 0;
+ for (regno = 0; regno < 16; ++regno)
+ if (val & (0x8000 >> regno))
+ newval |= 1 << regno;
+ val = newval;
+ }
+ val &= 0xffff;
+ doneany = 0;
+ for (regno = 0; regno < 16; ++regno)
+ if (val & (1 << regno))
+ {
+ int first_regno;
+ if (doneany)
+ fputs_filtered ("/", stream);
+ doneany = 1;
+ fprintf_filtered (stream, "%s", reg_names[regno]);
+ first_regno = regno;
+ while (val & (1 << (regno + 1)))
+ ++regno;
+ if (regno > first_regno)
+ fprintf_filtered (stream, "-%s", reg_names[regno]);
+ }
+ }
+ else if (place == '3')
+ {
+ /* `fmovem' insn. */
+ char doneany;
+ val = fetch_arg (buffer, place, 8);
+ if (val == 0)
+ {
+ fputs_filtered ("#0", stream);
+ break;
+ }
+ if (*d == 'l')
+ {
+ register int newval = 0;
+ for (regno = 0; regno < 8; ++regno)
+ if (val & (0x80 >> regno))
+ newval |= 1 << regno;
+ val = newval;
+ }
+ val &= 0xff;
+ doneany = 0;
+ for (regno = 0; regno < 8; ++regno)
+ if (val & (1 << regno))
+ {
+ int first_regno;
+ if (doneany)
+ fputs_filtered ("/", stream);
+ doneany = 1;
+ fprintf_filtered (stream, "fp%d", regno);
+ first_regno = regno;
+ while (val & (1 << (regno + 1)))
+ ++regno;
+ if (regno > first_regno)
+ fprintf_filtered (stream, "-fp%d", regno);
+ }
+ }
+ else
+ goto de_fault;
+ break;
+
+ default: de_fault:
+ fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c\".", *d);
+ }
+
+ return (unsigned char *) p;
+}
+
+/* Fetch BITS bits from a position in the instruction specified by CODE.
+ CODE is a "place to put an argument", or 'x' for a destination
+ that is a general address (mode and register).
+ BUFFER contains the instruction. */
+
+static int
+fetch_arg (buffer, code, bits)
+ unsigned char *buffer;
+ char code;
+ int bits;
+{
+ register int val = 0;
+ switch (code)
+ {
+ case 's':
+ val = buffer[1];
+ break;
+
+ case 'd': /* Destination, for register or quick. */
+ val = (buffer[0] << 8) + buffer[1];
+ val >>= 9;
+ break;
+
+ case 'x': /* Destination, for general arg */
+ val = (buffer[0] << 8) + buffer[1];
+ val >>= 6;
+ break;
+
+ case 'k':
+ val = (buffer[3] >> 4);
+ break;
+
+ case 'C':
+ val = buffer[3];
+ break;
+
+ case '1':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 12;
+ break;
+
+ case '2':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 6;
+ break;
+
+ case '3':
+ case 'j':
+ val = (buffer[2] << 8) + buffer[3];
+ break;
+
+ case '4':
+ val = (buffer[4] << 8) + buffer[5];
+ val >>= 12;
+ break;
+
+ case '5':
+ val = (buffer[4] << 8) + buffer[5];
+ val >>= 6;
+ break;
+
+ case '6':
+ val = (buffer[4] << 8) + buffer[5];
+ break;
+
+ case '7':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 7;
+ break;
+
+ case '8':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 10;
+ break;
+
+ default:
+ abort ();
+ }
+
+ switch (bits)
+ {
+ case 3:
+ return val & 7;
+ case 4:
+ return val & 017;
+ case 5:
+ return val & 037;
+ case 6:
+ return val & 077;
+ case 7:
+ return val & 0177;
+ case 8:
+ return val & 0377;
+ case 12:
+ return val & 07777;
+ default:
+ abort ();
+ return(0);
+ }
+} /* fetch_arg() */
+
+/* Print an indexed argument. The base register is BASEREG (-1 for pc).
+ P points to extension word, in buffer.
+ ADDR is the nominal core address of that extension word. */
+
+static unsigned char *
+print_indexed (basereg, p, addr, stream)
+ int basereg;
+ unsigned char *p;
+ FILE *stream;
+bfd_vma addr;
+{
+ register int word;
+ static char *scales[] = {"", "*2", "*4", "*8"};
+ register int base_disp;
+ register int outer_disp;
+ char buf[40];
+
+ word = NEXTWORD (p);
+
+ /* Generate the text for the index register.
+ Where this will be output is not yet determined. */
+ sprintf (buf, "[%s.%c%s]",
+ reg_names[(word >> 12) & 0xf],
+ (word & 0x800) ? 'l' : 'w',
+ scales[(word >> 9) & 3]);
+
+ /* Handle the 68000 style of indexing. */
+
+ if ((word & 0x100) == 0)
+ {
+ print_base (basereg,
+ ((word & 0x80) ? word | 0xff00 : word & 0xff)
+ + ((basereg == -1) ? addr : 0),
+ stream);
+ fputs_filtered (buf, stream);
+ return p;
+ }
+
+ /* Handle the generalized kind. */
+ /* First, compute the displacement to add to the base register. */
+
+ if (word & 0200)
+ basereg = -2;
+ if (word & 0100)
+ buf[0] = 0;
+ base_disp = 0;
+ switch ((word >> 4) & 3)
+ {
+ case 2:
+ base_disp = NEXTWORD (p);
+ break;
+ case 3:
+ base_disp = NEXTLONG (p);
+ }
+ if (basereg == -1)
+ base_disp += addr;
+
+ /* Handle single-level case (not indirect) */
+
+ if ((word & 7) == 0)
+ {
+ print_base (basereg, base_disp, stream);
+ fputs_filtered (buf, stream);
+ return p;
+ }
+
+ /* Two level. Compute displacement to add after indirection. */
+
+ outer_disp = 0;
+ switch (word & 3)
+ {
+ case 2:
+ outer_disp = NEXTWORD (p);
+ break;
+ case 3:
+ outer_disp = NEXTLONG (p);
+ }
+
+ fprintf_filtered (stream, "%d(", outer_disp);
+ print_base (basereg, base_disp, stream);
+
+ /* If postindexed, print the closeparen before the index. */
+ if (word & 4)
+ fprintf_filtered (stream, ")%s", buf);
+ /* If preindexed, print the closeparen after the index. */
+ else
+ fprintf_filtered (stream, "%s)", buf);
+
+ return p;
+}
+
+/* Print a base register REGNO and displacement DISP, on STREAM.
+ REGNO = -1 for pc, -2 for none (suppressed). */
+
+static void
+print_base (regno, disp, stream)
+ int regno;
+ int disp;
+ FILE *stream;
+{
+ if (regno == -2)
+ fprintf_filtered (stream, "%d", disp);
+ else if (regno == -1)
+ fprintf_filtered (stream, "0x%x", (unsigned) disp);
+ else
+ fprintf_filtered (stream, "%d(%s)", disp, reg_names[regno]);
+}
diff --git a/gnu/usr.bin/gdb/objdump/arch/sparc/Makefile.inc b/gnu/usr.bin/gdb/objdump/arch/sparc/Makefile.inc
new file mode 100644
index 00000000000..d2c3227a651
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/sparc/Makefile.inc
@@ -0,0 +1,8 @@
+# $Id: Makefile.inc,v 1.1 1995/10/18 08:40:14 deraadt Exp $
+
+SRCS+= sparc-pinsn.c sparc-opc.c
+
+CFLAGS+= -DSELECT_ARCHITECTURES=bfd_arch_sparc \
+ -DPRINT_INSN=print_insn_sparc
+
+
diff --git a/gnu/usr.bin/gdb/objdump/arch/sparc/sparc-pinsn.c b/gnu/usr.bin/gdb/objdump/arch/sparc/sparc-pinsn.c
new file mode 100644
index 00000000000..a82b5447f16
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/arch/sparc/sparc-pinsn.c
@@ -0,0 +1,482 @@
+/* disassemble sparc instructions for objdump
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+
+This file is part of the binutils.
+
+The binutils are 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, or (at your option)
+any later version.
+
+The binutils are distributed in the hope that they 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 the binutils; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include <stdio.h>
+#include "opcode/sparc.h"
+#include "objdump.h"
+extern int print_address();
+
+static char *reg_names[] =
+ { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
+ "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",
+ "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
+
+#define freg_names (&reg_names[4 * 8])
+
+union sparc_insn
+ {
+ unsigned long int code;
+ struct
+ {
+ unsigned int _OP:2;
+#define op ldst._OP
+ unsigned int _RD:5;
+#define rd ldst._RD
+ unsigned int op3:6;
+ unsigned int _RS1:5;
+#define rs1 ldst._RS1
+ unsigned int i:1;
+ unsigned int _ASI:8;
+#define asi ldst._ASI
+ unsigned int _RS2:5;
+#define rs2 ldst._RS2
+#define shcnt rs2
+ } ldst;
+ struct
+ {
+ unsigned int _OP:2, _RD:5, op3:6, _RS1:5, i:1;
+ unsigned int IMM13:13;
+#define imm13 IMM13.IMM13
+ } IMM13;
+ struct
+ {
+ unsigned int _OP:2;
+ unsigned int a:1;
+ unsigned int cond:4;
+ unsigned int op2:3;
+ unsigned int DISP22:22;
+#define disp22 branch.DISP22
+ } branch;
+
+#define imm22 disp22
+ struct
+ {
+ unsigned int _OP:2;
+ unsigned int _DISP30:30;
+#define disp30 call._DISP30
+ } call;
+ };
+
+/* Nonzero if INSN is the opcode for a delayed branch. */
+static int
+is_delayed_branch (insn)
+ union sparc_insn insn;
+{
+ unsigned int i;
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
+ if ((opcode->match & insn.code) == opcode->match
+ && (opcode->lose & insn.code) == 0
+ && (opcode->flags&F_DELAYED))
+ return 1;
+ }
+ return 0;
+}
+
+static int opcodes_sorted = 0;
+
+/* Print one instruction from MEMADDR on STREAM. */
+int
+print_insn_sparc (memaddr, buffer, stream)
+ bfd_vma memaddr;
+ bfd_byte *buffer;
+ FILE *stream;
+
+{
+ union sparc_insn insn;
+
+ register unsigned int i;
+
+ if (!opcodes_sorted)
+ {
+ static int compare_opcodes ();
+ qsort ((char *) sparc_opcodes, NUMOPCODES,
+ sizeof (sparc_opcodes[0]), compare_opcodes);
+ opcodes_sorted = 1;
+ }
+
+memcpy(&insn,buffer, sizeof (insn));
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
+ if ((opcode->match & insn.code) == opcode->match
+ && (opcode->lose & insn.code) == 0)
+ {
+ /* Nonzero means that we have found an instruction which has
+ the effect of adding or or'ing the imm13 field to rs1. */
+ int imm_added_to_rs1 = 0;
+
+ /* Nonzero means that we have found a plus sign in the args
+ field of the opcode table. */
+ int found_plus = 0;
+
+ /* Do we have an 'or' instruction where rs1 is the same
+ as rsd, and which has the i bit set? */
+ if (opcode->match == 0x80102000
+ && insn.rs1 == insn.rd)
+ imm_added_to_rs1 = 1;
+
+ if (index (opcode->args, 'S') != 0)
+ /* Reject the special case for `set'.
+ The real `sethi' will match. */
+ continue;
+ if (insn.rs1 != insn.rd
+ && index (opcode->args, 'r') != 0)
+ /* Can't do simple format if source and dest are different. */
+ continue;
+
+ fputs (opcode->name, stream);
+
+ {
+ register const char *s;
+
+ if (opcode->args[0] != ',')
+ fputs (" ", stream);
+ for (s = opcode->args; *s != '\0'; ++s)
+ {
+ while (*s == ',')
+ {
+ fputs (",", stream);
+ ++s;
+
+ switch (*s) {
+ case 'a':
+ fputs ("a", stream);
+ ++s;
+ continue;
+
+ default:
+ break;
+ } /* switch on arg */
+ } /* while there are comma started args */
+
+ fputs (" ", stream);
+
+ switch (*s)
+ {
+ case '+':
+ found_plus = 1;
+
+ /* note fall-through */
+ default:
+ fprintf (stream, "%c", *s);
+ break;
+
+ case '#':
+ fputs ("0", stream);
+ break;
+
+#define reg(n) fprintf (stream, "%%%s", reg_names[n])
+ case '1':
+ case 'r':
+ reg (insn.rs1);
+ break;
+
+ case '2':
+ reg (insn.rs2);
+ break;
+
+ case 'd':
+ reg (insn.rd);
+ break;
+#undef reg
+
+#define freg(n) fprintf (stream, "%%%s", freg_names[n])
+ case 'e':
+ case 'v': /* double/even */
+ case 'V': /* quad/multiple of 4 */
+ freg (insn.rs1);
+ break;
+
+ case 'f':
+ case 'B': /* double/even */
+ case 'R': /* quad/multiple of 4 */
+ freg (insn.rs2);
+ break;
+
+ case 'g':
+ case 'H': /* double/even */
+ case 'J': /* quad/multiple of 4 */
+ freg (insn.rd);
+ break;
+#undef freg
+
+#define creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
+ case 'b':
+ creg (insn.rs1);
+ break;
+
+ case 'c':
+ creg (insn.rs2);
+ break;
+
+ case 'D':
+ creg (insn.rd);
+ break;
+#undef creg
+
+ case 'h':
+ fprintf (stream, "%%hi(%#x)",
+ (unsigned int) insn.imm22 << 10);
+ break;
+
+ case 'i':
+ {
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ int imm = ((int) insn.imm13 << 19) >> 19;
+
+ /* Check to see whether we have a 1+i, and take
+ note of that fact.
+
+ Note: because of the way we sort the table,
+ we will be matching 1+i rather than i+1,
+ so it is OK to assume that i is after +,
+ not before it. */
+ if (found_plus)
+ imm_added_to_rs1 = 1;
+
+ if (imm <= 9)
+ fprintf (stream, "%d", imm);
+ else
+ fprintf (stream, "%#x", (unsigned) imm);
+ }
+ break;
+
+
+ case 'M':
+ fprintf(stream, "%%asr%d", insn.rs1);
+ break;
+
+ case 'm':
+ fprintf(stream, "%%asr%d", insn.rd);
+ break;
+
+ case 'L':
+ print_address ((bfd_vma) memaddr + insn.disp30 * 4,
+ stream);
+ break;
+
+ case 'l':
+ if ((insn.code >> 22) == 0)
+ /* Special case for `unimp'. Don't try to turn
+ it's operand into a function offset. */
+ fprintf (stream, "%#x",
+ (unsigned) (((int) insn.disp22 << 10) >> 10));
+ else
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ print_address ((bfd_vma)
+ (memaddr
+ + (((int) insn.disp22 << 10) >> 10) * 4),
+ stream);
+ break;
+
+ case 'A':
+ fprintf (stream, "(%d)", (int) insn.asi);
+ break;
+
+ case 'C':
+ fputs ("%csr", stream);
+ break;
+
+ case 'F':
+ fputs ("%fsr", stream);
+ break;
+
+ case 'p':
+ fputs ("%psr", stream);
+ break;
+
+ case 'q':
+ fputs ("%fq", stream);
+ break;
+
+ case 'Q':
+ fputs ("%cq", stream);
+ break;
+
+ case 't':
+ fputs ("%tbr", stream);
+ break;
+
+ case 'w':
+ fputs ("%wim", stream);
+ break;
+
+ case 'y':
+ fputs ("%y", stream);
+ break;
+ }
+ }
+ }
+
+ /* If we are adding or or'ing something to rs1, then
+ check to see whether the previous instruction was
+ a sethi to the same register as in the sethi.
+ If so, attempt to print the result of the add or
+ or (in this context add and or do the same thing)
+ and its symbolic value. */
+ if (imm_added_to_rs1)
+ {
+ union sparc_insn prev_insn;
+ int errcode = 0;
+
+ memcpy(&prev_insn, buffer -4, sizeof (prev_insn));
+
+ if (errcode == 0)
+ {
+ /* If it is a delayed branch, we need to look at the
+ instruction before the delayed branch. This handles
+ sequences such as
+
+ sethi %o1, %hi(_foo), %o1
+ call _printf
+ or %o1, %lo(_foo), %o1
+ */
+
+ if (is_delayed_branch (prev_insn))
+ memcpy(&prev_insn, buffer - 8, sizeof(prev_insn));
+
+ }
+
+ /* If there was a problem reading memory, then assume
+ the previous instruction was not sethi. */
+ if (errcode == 0)
+ {
+ /* Is it sethi to the same register? */
+ if ((prev_insn.code & 0xc1c00000) == 0x01000000
+ && prev_insn.rd == insn.rs1)
+ {
+ fprintf (stream, "\t! ");
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ print_address (((int) prev_insn.imm22 << 10)
+ | (insn.imm13 << 19) >> 19, stream);
+ }
+ }
+ }
+
+ return sizeof (insn);
+ }
+ }
+
+ fprintf (stream, "%#8x", insn.code);
+ return sizeof (insn);
+}
+
+
+/* Compare opcodes A and B. */
+
+static int
+compare_opcodes (a, b)
+ char *a, *b;
+{
+ struct sparc_opcode *op0 = (struct sparc_opcode *) a;
+ struct sparc_opcode *op1 = (struct sparc_opcode *) b;
+ unsigned long int match0 = op0->match, match1 = op1->match;
+ unsigned long int lose0 = op0->lose, lose1 = op1->lose;
+ register unsigned int i;
+
+ /* If a bit is set in both match and lose, there is something
+ wrong with the opcode table. */
+ if (match0 & lose0)
+ {
+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+ op0->name, match0, lose0);
+ op0->lose &= ~op0->match;
+ lose0 = op0->lose;
+ }
+
+ if (match1 & lose1)
+ {
+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+ op1->name, match1, lose1);
+ op1->lose &= ~op1->match;
+ lose1 = op1->lose;
+ }
+
+ /* Because the bits that are variable in one opcode are constant in
+ another, it is important to order the opcodes in the right order. */
+ for (i = 0; i < 32; ++i)
+ {
+ unsigned long int x = 1 << i;
+ int x0 = (match0 & x) != 0;
+ int x1 = (match1 & x) != 0;
+
+ if (x0 != x1)
+ return x1 - x0;
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ unsigned long int x = 1 << i;
+ int x0 = (lose0 & x) != 0;
+ int x1 = (lose1 & x) != 0;
+
+ if (x0 != x1)
+ return x1 - x0;
+ }
+
+ /* They are functionally equal. So as long as the opcode table is
+ valid, we can put whichever one first we want, on aesthetic grounds. */
+ {
+ int length_diff = strlen (op0->args) - strlen (op1->args);
+ if (length_diff != 0)
+ /* Put the one with fewer arguments first. */
+ return length_diff;
+ }
+
+ /* Put 1+i before i+1. */
+ {
+ char *p0 = (char *) index(op0->args, '+');
+ char *p1 = (char *) index(op1->args, '+');
+
+ if (p0 && p1)
+ {
+ /* There is a plus in both operands. Note that a plus
+ sign cannot be the first character in args,
+ so the following [-1]'s are valid. */
+ if (p0[-1] == 'i' && p1[1] == 'i')
+ /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
+ return 1;
+ if (p0[1] == 'i' && p1[-1] == 'i')
+ /* op0 is 1+i and op1 is i+1, so op0 goes first. */
+ return -1;
+ }
+ }
+
+ /* They are, as far as we can tell, identical.
+ Since qsort may have rearranged the table partially, there is
+ no way to tell which one was first in the opcode table as
+ written, so just say there are equal. */
+ return 0;
+}
diff --git a/gnu/usr.bin/gdb/objdump/bucomm.c b/gnu/usr.bin/gdb/objdump/bucomm.c
new file mode 100644
index 00000000000..728892d52c5
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/bucomm.c
@@ -0,0 +1,146 @@
+/* bucomm.c -- Bin Utils COMmon code.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of 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. */
+
+/* We might put this in a library someday so it could be dynamically
+ loaded, but for now it's not necessary */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include <varargs.h>
+
+char *target = NULL; /* default as late as possible */
+
+/* Yes, this is what atexit is for, but that isn't guaranteed yet.
+ And yes, I know this isn't as good, but it does what is needed just fine */
+void (*exit_handler) ();
+
+
+
+
+/* Error reporting */
+
+char *program_name;
+
+void
+DEFUN(bfd_fatal,(string),
+ char *string)
+{
+ CONST char *errmsg = bfd_errmsg (bfd_error);
+
+ if (string)
+ fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
+ else
+ fprintf (stderr, "%s: %s\n", program_name, errmsg);
+
+ if (NULL != exit_handler) (*exit_handler) ();
+ exit (1);
+}
+
+#if 0 /* !defined(NO_STDARG) */
+void
+fatal (Format)
+ const char *Format;
+{
+ va_list args;
+
+ va_start (args, Format);
+ vfprintf (stderr, Format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+ if (NULL != exit_handler) (*exit_handler) ();
+ exit (1);
+}
+#else
+void fatal (va_alist)
+ va_dcl
+{
+ char *Format;
+ va_list args;
+
+ va_start (args);
+ Format = va_arg(args, char *);
+ vfprintf (stderr, Format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+ if (NULL != exit_handler) (*exit_handler) ();
+ exit (1);
+} /* fatal() */
+#endif
+
+
+/** Display the archive header for an element as if it were an ls -l listing */
+
+/* Mode User\tGroup\tSize\tDate Name */
+
+void
+DEFUN(print_arelt_descr,(file, abfd, verbose),
+ FILE *file AND
+ bfd *abfd AND
+ boolean verbose)
+{
+ void mode_string ();
+ struct stat buf;
+
+ if (verbose) {
+
+ if (bfd_stat_arch_elt (abfd, &buf) == 0) { /* if not, huh? */
+ char modebuf[11];
+ char timebuf[40];
+ long when = buf.st_mtime;
+ CONST char *ctime_result = (CONST char *)ctime (&when);
+
+ /* Posix format: skip weekday and seconds from ctime output. */
+ sprintf(timebuf, "%.12s %.4s", ctime_result+4, ctime_result+20);
+
+ mode_string (buf.st_mode, modebuf);
+ modebuf[10] = '\0';
+ /* Posix 1003.2/D11 says to skip first character (entry type). */
+ fprintf (file, "%s %d/%d %6qd %s ", modebuf+1, buf.st_uid, buf.st_gid, buf.st_size, timebuf);
+ }
+ }
+
+ fprintf (file, "%s\n",abfd->filename);
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+char *
+xmalloc (size)
+ unsigned size;
+{
+ register char *result = malloc (size);
+ if (result == (char *) NULL && size != 0) {
+ fatal ("virtual memory exhausted");
+ }
+
+ return result;
+}
+
+/* Like realloc but get fatal error if memory is exhausted. */
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ register char *result = realloc (ptr, size);
+ if (result == 0 && size != 0) {
+ fatal ("virtual memory exhausted");
+ }
+
+ return result;
+}
diff --git a/gnu/usr.bin/gdb/objdump/filemode.c b/gnu/usr.bin/gdb/objdump/filemode.c
new file mode 100644
index 00000000000..d53cef11d34
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/filemode.c
@@ -0,0 +1,193 @@
+/* filemode.c -- make a string describing file modes
+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
+
+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 <sys/types.h>
+#include <sys/stat.h>
+
+void mode_string ();
+static char ftypelet ();
+static void rwx ();
+static void setst ();
+
+/* filemodestring - fill in string STR with an ls-style ASCII
+ representation of the st_mode field of file stats block STATP.
+ 10 characters are stored in STR; no terminating null is added.
+ The characters stored in STR are:
+
+ 0 File type. 'd' for directory, 'c' for character
+ special, 'b' for block special, 'm' for multiplex,
+ 'l' for symbolic link, 's' for socket, 'p' for fifo,
+ '-' for any other file type
+
+ 1 'r' if the owner may read, '-' otherwise.
+
+ 2 'w' if the owner may write, '-' otherwise.
+
+ 3 'x' if the owner may execute, 's' if the file is
+ set-user-id, '-' otherwise.
+ 'S' if the file is set-user-id, but the execute
+ bit isn't set.
+
+ 4 'r' if group members may read, '-' otherwise.
+
+ 5 'w' if group members may write, '-' otherwise.
+
+ 6 'x' if group members may execute, 's' if the file is
+ set-group-id, '-' otherwise.
+ 'S' if it is set-group-id but not executable.
+
+ 7 'r' if any user may read, '-' otherwise.
+
+ 8 'w' if any user may write, '-' otherwise.
+
+ 9 'x' if any user may execute, 't' if the file is "sticky"
+ (will be retained in swap space after execution), '-'
+ otherwise.
+ 'T' if the file is sticky but not executable. */
+
+void
+filemodestring (statp, str)
+ struct stat *statp;
+ char *str;
+{
+ mode_string (statp->st_mode, str);
+}
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+ is given as an argument. */
+
+void
+mode_string (mode, str)
+ unsigned short mode;
+ char *str;
+{
+ str[0] = ftypelet (mode);
+ rwx ((mode & 0700) << 0, &str[1]);
+ rwx ((mode & 0070) << 3, &str[4]);
+ rwx ((mode & 0007) << 6, &str[7]);
+ setst (mode, str);
+}
+
+/* Return a character indicating the type of file described by
+ file mode BITS:
+ 'd' for directories
+ 'b' for block special files
+ 'c' for character special files
+ 'm' for multiplexor files
+ 'l' for symbolic links
+ 's' for sockets
+ 'p' for fifos
+ '-' for any other file type. */
+
+static char
+ftypelet (bits)
+ unsigned short bits;
+{
+ switch (bits & S_IFMT)
+ {
+ default:
+ return '-';
+ case S_IFDIR:
+ return 'd';
+#ifdef S_IFLNK
+ case S_IFLNK:
+ return 'l';
+#endif
+#ifdef S_IFCHR
+ case S_IFCHR:
+ return 'c';
+#endif
+#ifdef S_IFBLK
+ case S_IFBLK:
+ return 'b';
+#endif
+#ifdef S_IFMPC
+ case S_IFMPC:
+ case S_IFMPB:
+ return 'm';
+#endif
+#ifdef S_IFSOCK
+ case S_IFSOCK:
+ return 's';
+#endif
+#ifdef S_IFIFO
+#if S_IFIFO != S_IFSOCK
+ case S_IFIFO:
+ return 'p';
+#endif
+#endif
+#ifdef S_IFNWK /* HP-UX */
+ case S_IFNWK:
+ return 'n';
+#endif
+ }
+}
+
+/* Look at read, write, and execute bits in BITS and set
+ flags in CHARS accordingly. */
+
+static void
+rwx (bits, chars)
+ unsigned short bits;
+ char *chars;
+{
+ chars[0] = (bits & S_IREAD) ? 'r' : '-';
+ chars[1] = (bits & S_IWRITE) ? 'w' : '-';
+ chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+ according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+ unsigned short bits;
+ char *chars;
+{
+#ifdef S_ISUID
+ if (bits & S_ISUID)
+ {
+ if (chars[3] != 'x')
+ /* Set-uid, but not executable by owner. */
+ chars[3] = 'S';
+ else
+ chars[3] = 's';
+ }
+#endif
+#ifdef S_ISGID
+ if (bits & S_ISGID)
+ {
+ if (chars[6] != 'x')
+ /* Set-gid, but not executable by group. */
+ chars[6] = 'S';
+ else
+ chars[6] = 's';
+ }
+#endif
+#ifdef S_ISVTX
+ if (bits & S_ISVTX)
+ {
+ if (chars[9] != 'x')
+ /* Sticky, but not executable by others. */
+ chars[9] = 'T';
+ else
+ chars[9] = 't';
+ }
+#endif
+}
+
+
diff --git a/gnu/usr.bin/gdb/objdump/objdump.1 b/gnu/usr.bin/gdb/objdump/objdump.1
new file mode 100644
index 00000000000..b26fb7cb027
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/objdump.1
@@ -0,0 +1,227 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH objdump 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+objdump\(em\&display information from object files.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B objdump
+.RB "[\|" \-a "\|]"
+.RB "[\|" "\-b\ "\c
+.I bfdname\c
+\&\|]
+.RB "[\|" \-d "\|]"
+.RB "[\|" \-f "\|]"
+.RB "[\|" \-h | --header "\|]"
+.RB "[\|" \-i "\|]"
+.RB "[\|" "\-j\ "\c
+.I section\c
+\&\|]
+.RB "[\|" \-l "\|]"
+.RB "[\|" "\-m\ "\c
+.I machine\c
+\&\|]
+.RB "[\|" \-r | --reloc "\|]"
+.RB "[\|" \-s "\|]"
+.RB "[\|" \--stabs "\|]"
+.RB "[\|" \-t | --syms "\|]"
+.RB "[\|" \-x "\|]"
+.I objfiles\c
+\&.\|.\|.
+.ad b
+.hy 1
+.SH DESCRIPTION
+\c
+.B objdump\c
+\& displays information about one or more object files.
+The options control what particular information to display. This
+information is mostly useful to programmers who are working on the
+compilation tools, as opposed to programmers who just want their
+program to compile and work.
+.SH OPTIONS
+Where long and short forms of an option are shown together, they are
+equivalent.
+
+.TP
+.IR "objfiles" .\|.\|.
+The object files to be examined. When you specify archives,
+\c
+.B objdump\c
+\& shows information on each of the member object files.
+
+.TP
+.B \-a
+If any files from \c
+.I objfiles\c
+\& are archives, display the archive
+header information (in a format similar to `\|\c
+.B ls \-l\c
+\|'). Besides the
+information you could list with `\|\c
+.B ar tv\c
+\|', `\|\c
+.B objdump \-a\c
+\|' shows
+the object file format of each archive member.
+
+.TP
+.BI "-b " "bfdname"\c
+\&
+You can specify a particular object-code format for your object files as
+\c
+.I bfdname\c
+\&. This may not be necessary; \c
+.I objdump\c
+\& can
+automatically recognize many formats. For example,
+.sp
+.br
+objdump\ \-b\ oasys\ \-m\ vax\ \-h\ fu.o
+.br
+.sp
+
+Displays summary information from the section headers (`\|\c
+.B \-h\c
+\|') of
+`\|\c
+.B fu.o\c
+\|', which is explicitly identified (`\|\c
+.B \-m\c
+\|') as a Vax object
+file in the format produced by Oasys compilers. You can list the
+formats available with the `\|\c
+.B \-i\c
+\|' option.
+
+.TP
+.B \-d
+Disassemble. Display the assembler mnemonics for the machine
+instructions from \c
+.I objfiles\c
+\&.
+
+.TP
+.B \-f
+File header. Display summary information from the overall header of
+each file in \c
+.I objfiles\c
+\&.
+
+.TP
+.B \-h
+.TP
+.B --header
+Header. Display summary information from the section headers of the
+object file.
+
+.TP
+.B \-i
+Display a list showing all architectures and object formats available
+for specification with \c
+.B \-b\c
+\& or \c
+.B \-m\c
+\&.
+
+.TP
+.BI "-j " "name"\c
+\&
+Display information only for section \c
+.I name\c
+\&
+
+.TP
+.B \-l
+Label the display (using debugging information) with the source filename
+and line numbers corresponding to the object code shown.
+
+.TP
+.BI "-m " "machine"\c
+\&
+Specify the object files \c
+.I objfiles\c
+\& are for architecture
+\c
+.I machine\c
+\&. You can list available architectures using the `\|\c
+.B \-i\c
+\|'
+option.
+
+.TP
+.B \-r
+.TP
+.B --reloc
+Relocation. Print the relocation entries of the file.
+
+.TP
+.B \-s
+Display the full contents of any sections requested.
+
+.TP
+.B \--stabs
+Display the contents of the .stab, .stab.index, and .stab.excl
+sections from an ELF file. This is only useful on systems (such as
+Solaris 2.0) in which .stab debugging symbol-table entries are carried
+in an ELF section. In most other file formats, debugging symbol-table
+entries are interleaved with linkage symbols, and are visible in the
+--syms output.
+
+.TP
+.B \-t
+.TP
+.B --syms
+Symbol Table. Print the symbol table entries of the file.
+This is similar to the information provided by the `\|\c
+.B nm\c
+\|' program.
+
+.TP
+.B \-x
+Display all available header information, including the symbol table and
+relocation entries. Using `\|\c
+.B \-x\c
+\|' is equivalent to specifying all of
+`\|\c
+.B \-a \-f \-h \-r \-t\c
+\|'.
+
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in
+.B
+info\c
+\&;
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991);
+.BR nm "(" 1 ")."
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gnu/usr.bin/gdb/objdump/objdump.c b/gnu/usr.bin/gdb/objdump/objdump.c
new file mode 100644
index 00000000000..982b7d2a427
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/objdump.c
@@ -0,0 +1,1087 @@
+/* objdump.c -- dump information about an object file.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Until there is other documentation, refer to the manual page dump(1) in
+ * the system 5 program's reference manual
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "getopt.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#define ELF_STAB_DISPLAY /* This code works, but uses internal
+ bfd and elf stuff. Flip this define
+ off if you need to just use generic
+ BFD interfaces. */
+
+#ifdef ELF_STAB_DISPLAY
+/* Internal headers for the ELF .stab-dump code - sorry. */
+#define BYTES_IN_WORD 32
+#include "aout/aout64.h"
+#include "elf/internal.h"
+extern Elf_Internal_Shdr *bfd_elf_find_section();
+#endif /* ELF_STAB_DISPLAY */
+
+char *xmalloc ();
+
+char *default_target = NULL; /* default at runtime */
+
+extern *program_version;
+char *program_name = NULL;
+
+int show_version = 0; /* show the version number */
+int dump_section_contents; /* -s */
+int dump_section_headers; /* -h */
+boolean dump_file_header; /* -f */
+int dump_symtab; /* -t */
+int dump_reloc_info; /* -r */
+int dump_ar_hdrs; /* -a */
+int with_line_numbers; /* -l */
+int dump_stab_section_info; /* -stabs */
+boolean disassemble; /* -d */
+boolean info; /* -i */
+char *only;
+
+PROTO (void, display_file, (char *filename, char *target));
+PROTO (void, dump_data, (bfd * abfd));
+PROTO (void, dump_relocs, (bfd * abfd));
+PROTO (void, dump_symbols, (bfd * abfd));
+PROTO (void, print_arelt_descr, (FILE *, bfd * abfd, boolean verbose));
+
+
+
+
+
+
+
+char *machine = (char *) NULL;
+asymbol **syms;
+asymbol **syms2;
+
+
+unsigned int storage;
+
+unsigned int symcount = 0;
+
+void
+usage ()
+{
+ fprintf (stderr,
+ "usage: %s [-ahifdrtxsl] [-m machine] [-j section_name] obj ...\n",
+ program_name);
+ exit (1);
+}
+
+static struct option long_options[]=
+{
+ {"syms", no_argument, &dump_symtab, 1},
+ {"reloc", no_argument, &dump_reloc_info, 1},
+ {"header", no_argument, &dump_section_headers, 1},
+ {"version", no_argument, &show_version, 1},
+#ifdef ELF_STAB_DISPLAY
+ {"stabs", no_argument, &dump_stab_section_info, 1},
+#endif
+ {0, no_argument, 0, 0}};
+
+
+static void
+dump_headers (abfd)
+ bfd *abfd;
+{
+ asection *section;
+
+ for (section = abfd->sections;
+ section != (asection *) NULL;
+ section = section->next)
+ {
+ char *comma = "";
+
+#define PF(x,y) \
+ if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; }
+
+
+ printf ("SECTION %d [%s]\t: size %08x",
+ section->index,
+ section->name,
+ (unsigned) bfd_get_section_size_before_reloc (section));
+ printf (" vma ");
+ printf_vma (section->vma);
+ printf (" align 2**%u\n ",
+ section->alignment_power);
+ PF (SEC_ALLOC, "ALLOC");
+ PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
+ PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT");
+ PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA");
+ PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS");
+ PF (SEC_LOAD, "LOAD");
+ PF (SEC_RELOC, "RELOC");
+#ifdef SEC_BALIGN
+ PF (SEC_BALIGN, "BALIGN");
+#endif
+ PF (SEC_READONLY, "READONLY");
+ PF (SEC_CODE, "CODE");
+ PF (SEC_DATA, "DATA");
+ PF (SEC_ROM, "ROM");
+ printf ("\n");
+#undef PF
+ }
+}
+
+static asymbol **
+DEFUN (slurp_symtab, (abfd),
+ bfd * abfd)
+{
+ asymbol **sy = (asymbol **) NULL;
+
+ if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
+ {
+ (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
+ return (NULL);
+ }
+
+ storage = get_symtab_upper_bound (abfd);
+ if (storage)
+ {
+ sy = (asymbol **) malloc (storage);
+ if (sy == NULL)
+ {
+ fprintf (stderr, "%s: out of memory.\n", program_name);
+ exit (1);
+ }
+ }
+ symcount = bfd_canonicalize_symtab (abfd, sy);
+ return sy;
+}
+
+/* Sort symbols into value order */
+static int
+comp (ap, bp)
+ PTR ap;
+ PTR bp;
+{
+ asymbol *a = *(asymbol **)ap;
+ asymbol *b = *(asymbol **)bp;
+ int diff;
+
+ if (a->name == (char *) NULL || (a->flags & (BSF_DEBUGGING)))
+ a->the_bfd = 0;
+ if (b->name == (char *) NULL || (b->flags & (BSF_DEBUGGING)))
+ b->the_bfd = 0;
+
+ diff = a->the_bfd - b->the_bfd;
+ if (diff)
+ {
+ return -diff;
+ }
+ diff = a->value - b->value;
+ if (diff)
+ {
+ return diff;
+ }
+ return a->section - b->section;
+}
+
+/* Print the supplied address symbolically if possible */
+void
+print_address (vma, stream)
+ bfd_vma vma;
+ FILE *stream;
+{
+ /* Perform a binary search looking for the closest symbol to
+ the required value */
+
+ unsigned int min = 0;
+ unsigned int max = symcount;
+
+ unsigned int thisplace = 1;
+ unsigned int oldthisplace;
+
+ int vardiff;
+
+ if (symcount == 0)
+ {
+ fprintf_vma (stream, vma);
+ }
+ else
+ {
+ while (true)
+ {
+ oldthisplace = thisplace;
+ thisplace = (max + min) / 2;
+ if (thisplace == oldthisplace)
+ break;
+ vardiff = syms[thisplace]->value - vma;
+
+ if (vardiff)
+ {
+ if (vardiff > 0)
+ {
+ max = thisplace;
+ }
+ else
+ {
+ min = thisplace;
+ }
+ }
+ else
+ {
+ /* Totally awesome! the exact right symbol */
+ CONST char *match_name = syms[thisplace]->name;
+ int sym_len = strlen (match_name);
+
+ /* Avoid "filename.o" as a match */
+ if (sym_len > 2
+ && match_name[sym_len - 2] == '.'
+ && match_name[sym_len - 1] == 'o'
+ && thisplace + 1 < symcount
+ && syms[thisplace + 1]->value == vma)
+ match_name = syms[thisplace + 1]->name;
+ /* Totally awesome! the exact right symbol */
+ fprintf_vma (stream, vma);
+ fprintf (stream, " (%s+)0000", syms[thisplace]->name);
+ return;
+ }
+ }
+ /* We've run out of places to look, print the symbol before this one
+ see if this or the symbol before describes this location the best */
+
+ if (thisplace != 0)
+ {
+ if (syms[thisplace - 1]->value - vma >
+ syms[thisplace]->value - vma)
+ {
+ /* Previous symbol is in correct section and is closer */
+ thisplace--;
+ }
+ }
+
+ fprintf_vma (stream, vma);
+ if (syms[thisplace]->value > vma)
+ {
+ fprintf (stream, " (%s-)", syms[thisplace]->name);
+ fprintf (stream, "%04x", syms[thisplace]->value - vma);
+ }
+ else
+ {
+ fprintf (stream, " (%s+)", syms[thisplace]->name);
+ fprintf (stream, "%04x", vma - syms[thisplace]->value);
+ }
+ }
+}
+
+void
+disassemble_data (abfd)
+ bfd *abfd;
+{
+ bfd_byte *data = NULL;
+ bfd_arch_info_type *info;
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ unsigned int (*print) ()= 0;
+ unsigned int print_insn_m68k ();
+ unsigned int print_insn_a29k ();
+ unsigned int print_insn_z8k ();
+ unsigned int print_insn_i960 ();
+ unsigned int print_insn_sparc ();
+ unsigned int print_insn_i386 ();
+ unsigned int print_insn_h8300 ();
+ enum bfd_architecture a;
+
+ asection *section;
+
+ /* Replace symbol section relative values with abs values */
+ boolean done_dot = false;
+
+ for (i = 0; i < symcount; i++)
+ {
+ syms[i]->value += syms[i]->section->vma;
+ }
+
+ /* We keep a copy of the symbols in the original order */
+ syms2 = slurp_symtab (abfd);
+
+ /* Sort the symbols into section and symbol order */
+ (void) qsort (syms, symcount, sizeof (asymbol *), comp);
+
+ /* Find the first useless symbol */
+ {
+ unsigned int i;
+
+ for (i = 0; i < symcount; i++)
+ {
+ if (syms[i]->the_bfd == 0)
+ {
+ symcount = i;
+ break;
+ }
+ }
+ }
+
+
+ if (machine != (char *) NULL)
+ {
+ info = bfd_scan_arch (machine);
+ if (info == 0)
+ {
+ fprintf (stderr, "%s: Can't use supplied machine %s\n",
+ program_name,
+ machine);
+ exit (1);
+ }
+ abfd->arch_info = info;
+ }
+
+ /* See if we can disassemble using bfd */
+
+ if (abfd->arch_info->disassemble)
+ {
+ print = abfd->arch_info->disassemble;
+ }
+ else
+ {
+ a = bfd_get_arch (abfd);
+ switch (a)
+ {
+#ifdef SELECT_ARCHITECTURES
+ case SELECT_ARCHITECTURES:
+ print = PRINT_INSN;
+ break;
+#else
+ case bfd_arch_sparc:
+ print = print_insn_sparc;
+ break;
+ case bfd_arch_i386:
+ print = print_insn_i386;
+ break;
+ case bfd_arch_m68k:
+ print = print_insn_m68k;
+ break;
+ case bfd_arch_a29k:
+ print = print_insn_a29k;
+ break;
+ case bfd_arch_i960:
+ print = print_insn_i960;
+ break;
+ case bfd_arch_z8k:
+ print = print_insn_z8k;
+ break;
+#endif
+ default:
+ fprintf (stderr, "%s: Can't disassemble for architecture %s\n",
+ program_name,
+ bfd_printable_arch_mach (bfd_get_arch (abfd), 0));
+ exit (1);
+ }
+
+ }
+
+ for (section = abfd->sections;
+ section != (asection *) NULL;
+ section = section->next)
+ {
+
+ if ((section->flags & SEC_LOAD)
+ && (only == (char *) NULL || strcmp (only, section->name) == 0))
+ {
+ printf ("Disassembly of section %s:\n", section->name);
+
+ if (bfd_get_section_size_before_reloc (section) == 0)
+ continue;
+
+ data = (bfd_byte *) malloc (bfd_get_section_size_before_reloc (section));
+
+ if (data == (bfd_byte *) NULL)
+ {
+ fprintf (stderr, "%s: memory exhausted.\n", program_name);
+ exit (1);
+ }
+ datasize = bfd_get_section_size_before_reloc (section);
+
+ bfd_get_section_contents (abfd, section, data, 0, bfd_get_section_size_before_reloc (section));
+
+ i = 0;
+ while (i < bfd_get_section_size_before_reloc (section))
+ {
+ if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 &&
+ data[i + 3] == 0)
+ {
+ if (done_dot == false)
+ {
+ printf ("...\n");
+ done_dot = true;
+ }
+ i += 4;
+ }
+ else
+ {
+ done_dot = false;
+ if (with_line_numbers)
+ {
+ static prevline;
+ CONST char *filename;
+ CONST char *functionname;
+ unsigned int line;
+
+ bfd_find_nearest_line (abfd,
+ section,
+ syms,
+ section->vma + i,
+ &filename,
+ &functionname,
+ &line);
+
+ if (filename && functionname && line && line != prevline)
+ {
+ printf ("%s:%u\n", filename, line);
+ prevline = line;
+ }
+ }
+ print_address (section->vma + i, stdout);
+ printf (" ");
+
+ i += print (section->vma + i,
+ data + i,
+ stdout);
+ putchar ('\n');
+ }
+ }
+ free (data);
+ }
+ }
+}
+
+#ifdef ELF_STAB_DISPLAY
+
+/* Define a table of stab values and print-strings. We wish the initializer
+ could be a direct-mapped table, but instead we build one the first
+ time we need it. */
+
+#define STAB_STRING_LENGTH 6
+
+char stab_name[256][STAB_STRING_LENGTH];
+
+struct stab_print {
+ int value;
+ char string[STAB_STRING_LENGTH];
+};
+
+struct stab_print stab_print[] = {
+#define __define_stab(NAME, CODE, STRING) {CODE, STRING},
+#include "aout/stab.def"
+#undef __define_stab
+ {0, 0}
+};
+
+void dump_elf_stabs_1 ();
+
+/* This is a kludge for dumping the stabs section from an ELF file that
+ uses Sun stabs encoding. It has to use some hooks into BFD because
+ string table sections are not normally visible to BFD callers. */
+
+void
+dump_elf_stabs (abfd)
+ bfd *abfd;
+{
+ int i;
+
+ /* Initialize stab name array if first time. */
+ if (stab_name[0][0] == 0)
+ {
+ /* Fill in numeric values for all possible strings. */
+ for (i = 0; i < 256; i++)
+ {
+ sprintf (stab_name[i], "%d", i);
+ }
+ for (i = 0; stab_print[i].string[0]; i++)
+ strcpy (stab_name[stab_print[i].value], stab_print[i].string);
+ }
+
+ if (0 != strncmp ("elf", abfd->xvec->name, 3))
+ {
+ fprintf (stderr, "%s: %s is not in ELF format.\n", program_name,
+ abfd->filename);
+ return;
+ }
+
+ dump_elf_stabs_1 (abfd, ".stab", ".stabstr");
+ dump_elf_stabs_1 (abfd, ".stab.excl", ".stab.exclstr");
+ dump_elf_stabs_1 (abfd, ".stab.index", ".stab.indexstr");
+}
+
+void
+dump_elf_stabs_1 (abfd, name1, name2)
+ bfd *abfd;
+ char *name1; /* Section name of .stab */
+ char *name2; /* Section name of its string section */
+{
+ Elf_Internal_Shdr *stab_hdr, *stabstr_hdr;
+ char *strtab;
+ struct internal_nlist *stabs, *stabs_end;
+ int i;
+ unsigned file_string_table_offset, next_file_string_table_offset;
+
+ stab_hdr = bfd_elf_find_section (abfd, name1);
+ if (0 == stab_hdr)
+ {
+ printf ("Contents of %s section: none.\n\n", name1);
+ return;
+ }
+
+ stabstr_hdr = bfd_elf_find_section (abfd, name2);
+ if (0 == stabstr_hdr)
+ {
+ fprintf (stderr, "%s: %s has no %s section.\n", program_name,
+ abfd->filename, name2);
+ return;
+ }
+
+ stabs = (struct internal_nlist *) xmalloc (stab_hdr ->sh_size);
+ strtab = (char *) xmalloc (stabstr_hdr->sh_size);
+ stabs_end = (struct internal_nlist *) (stab_hdr->sh_size + (char *)stabs);
+
+ if (bfd_seek (abfd, stab_hdr->sh_offset, L_SET) < 0 ||
+ stab_hdr->sh_size != bfd_read ((PTR)stabs, stab_hdr->sh_size, 1, abfd))
+ {
+ fprintf (stderr, "%s: reading %s section of %s failed.\n",
+ program_name, name1,
+ abfd->filename);
+ return;
+ }
+
+ if (bfd_seek (abfd, stabstr_hdr->sh_offset, L_SET) < 0 ||
+ stabstr_hdr->sh_size != bfd_read ((PTR)strtab, stabstr_hdr->sh_size,
+ 1, abfd))
+ {
+ fprintf (stderr, "%s: reading %s section of %s failed.\n",
+ program_name, name2,
+ abfd->filename);
+ return;
+ }
+
+#define SWAP_SYMBOL(symp, abfd) \
+ { \
+ (symp)->n_strx = bfd_h_get_32(abfd, \
+ (unsigned char *)&(symp)->n_strx); \
+ (symp)->n_desc = bfd_h_get_16 (abfd, \
+ (unsigned char *)&(symp)->n_desc); \
+ (symp)->n_value = bfd_h_get_32 (abfd, \
+ (unsigned char *)&(symp)->n_value); \
+ }
+
+ printf ("Contents of %s section:\n\n", name1);
+ printf ("Symnum n_type n_othr n_desc n_value n_strx String\n");
+
+ file_string_table_offset = 0;
+ next_file_string_table_offset = 0;
+
+ /* Loop through all symbols and print them.
+
+ We start the index at -1 because there is a dummy symbol on
+ the front of Sun's stabs-in-elf sections. */
+
+ for (i = -1; stabs < stabs_end; stabs++, i++)
+ {
+ SWAP_SYMBOL (stabs, abfd);
+ printf ("\n%-6d %-6s %-6d %-6d %08x %-6d", i,
+ stab_name [stabs->n_type],
+ stabs->n_other, stabs->n_desc, stabs->n_value,
+ stabs->n_strx);
+
+ /* Symbols with type == 0 (N_UNDF) specify the length of the
+ string table associated with this file. We use that info
+ to know how to relocate the *next* file's string table indices. */
+
+ if (stabs->n_type == N_UNDF)
+ {
+ file_string_table_offset = next_file_string_table_offset;
+ next_file_string_table_offset += stabs->n_value;
+ }
+
+ /* Now, using the possibly updated string table offset, print the
+ string (if any) associated with this symbol. */
+
+ if ((stabs->n_strx + file_string_table_offset) < stabstr_hdr->sh_size)
+ printf (" %s", &strtab[stabs->n_strx + file_string_table_offset]);
+ else
+ printf (" *");
+ }
+ printf ("\n\n");
+}
+#endif /* ELF_STAB_DISPLAY */
+
+display_bfd (abfd)
+ bfd *abfd;
+{
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ fprintf (stderr, "%s: %s not an object file\n", program_name,
+ abfd->filename);
+ return;
+ }
+ printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name);
+ if (dump_ar_hdrs)
+ print_arelt_descr (stdout, abfd, true);
+
+ if (dump_file_header)
+ {
+ char *comma = "";
+
+ printf ("architecture: %s, ",
+ bfd_printable_arch_mach (bfd_get_arch (abfd),
+ bfd_get_mach (abfd)));
+ printf ("flags 0x%08x:\n", abfd->flags);
+
+#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
+ PF (HAS_RELOC, "HAS_RELOC");
+ PF (EXEC_P, "EXEC_P");
+ PF (HAS_LINENO, "HAS_LINENO");
+ PF (HAS_DEBUG, "HAS_DEBUG");
+ PF (HAS_SYMS, "HAS_SYMS");
+ PF (HAS_LOCALS, "HAS_LOCALS");
+ PF (DYNAMIC, "DYNAMIC");
+ PF (WP_TEXT, "WP_TEXT");
+ PF (D_PAGED, "D_PAGED");
+ PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
+ printf ("\nstart address 0x");
+ printf_vma (abfd->start_address);
+ }
+ printf ("\n");
+
+ if (dump_section_headers)
+ dump_headers (abfd);
+ if (dump_symtab || dump_reloc_info || disassemble)
+ {
+ syms = slurp_symtab (abfd);
+ }
+ if (dump_symtab)
+ dump_symbols (abfd);
+#ifdef ELF_STAB_DISPLAY
+ if (dump_stab_section_info)
+ dump_elf_stabs (abfd);
+#endif
+ if (dump_reloc_info)
+ dump_relocs (abfd);
+ if (dump_section_contents)
+ dump_data (abfd);
+ if (disassemble)
+ disassemble_data (abfd);
+}
+
+void
+display_file (filename, target)
+ char *filename;
+ char *target;
+{
+ bfd *file, *arfile = (bfd *) NULL;
+
+ file = bfd_openr (filename, target);
+ if (file == NULL)
+ {
+ bfd_perror (filename);
+ return;
+ }
+
+ if (bfd_check_format (file, bfd_archive) == true)
+ {
+ printf ("In archive %s:\n", bfd_get_filename (file));
+ for (;;)
+ {
+ bfd_error = no_error;
+
+ arfile = bfd_openr_next_archived_file (file, arfile);
+ if (arfile == NULL)
+ {
+ if (bfd_error != no_more_archived_files)
+ bfd_perror (bfd_get_filename (file));
+ return;
+ }
+
+ display_bfd (arfile);
+ /* Don't close the archive elements; we need them for next_archive */
+ }
+ }
+ else
+ display_bfd (file);
+
+ bfd_close (file);
+}
+
+/* Actually display the various requested regions */
+
+void
+dump_data (abfd)
+ bfd *abfd;
+{
+ asection *section;
+ bfd_byte *data = 0;
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+
+ for (section = abfd->sections; section != NULL; section =
+ section->next)
+ {
+ int onaline = 16;
+
+ if (only == (char *) NULL ||
+ strcmp (only, section->name) == 0)
+ {
+ if (section->flags & SEC_HAS_CONTENTS)
+ {
+ printf ("Contents of section %s:\n", section->name);
+
+ if (bfd_get_section_size_before_reloc (section) == 0)
+ continue;
+ data = (bfd_byte *) malloc (bfd_get_section_size_before_reloc (section));
+ if (data == (bfd_byte *) NULL)
+ {
+ fprintf (stderr, "%s: memory exhausted.\n", program_name);
+ exit (1);
+ }
+ datasize = bfd_get_section_size_before_reloc (section);
+
+
+ bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_get_section_size_before_reloc (section));
+
+ for (i = 0; i < bfd_get_section_size_before_reloc (section); i += onaline)
+ {
+ bfd_size_type j;
+
+ printf (" %04lx ", (unsigned long int) (i + section->vma));
+ for (j = i; j < i + onaline; j++)
+ {
+ if (j < bfd_get_section_size_before_reloc (section))
+ printf ("%02x", (unsigned) (data[j]));
+ else
+ printf (" ");
+ if ((j & 3) == 3)
+ printf (" ");
+ }
+
+ printf (" ");
+ for (j = i; j < i + onaline; j++)
+ {
+ if (j >= bfd_get_section_size_before_reloc (section))
+ printf (" ");
+ else
+ printf ("%c", isprint (data[j]) ? data[j] : '.');
+ }
+ putchar ('\n');
+ }
+ }
+ }
+ free (data);
+ }
+}
+
+/* Should perhaps share code and display with nm? */
+void
+dump_symbols (abfd)
+ bfd *abfd;
+{
+
+ unsigned int count;
+ asymbol **current = syms;
+
+ printf ("SYMBOL TABLE:\n");
+
+ for (count = 0; count < symcount; count++)
+ {
+
+ if (*current && (*current)->the_bfd)
+ {
+ bfd_print_symbol ((*current)->the_bfd,
+ stdout,
+ *current, bfd_print_symbol_all);
+
+ printf ("\n");
+
+ }
+ current++;
+ }
+ printf ("\n");
+ printf ("\n");
+}
+
+void
+dump_relocs (abfd)
+ bfd *abfd;
+{
+ arelent **relpp;
+ unsigned int relcount;
+ asection *a;
+
+ for (a = abfd->sections; a != (asection *) NULL; a = a->next)
+ {
+ if (a == &bfd_abs_section)
+ continue;
+ if (a == &bfd_und_section)
+ continue;
+ if (a == &bfd_com_section)
+ continue;
+
+ printf ("RELOCATION RECORDS FOR [%s]:", a->name);
+
+ if (bfd_get_reloc_upper_bound (abfd, a) == 0)
+ {
+ printf (" (none)\n\n");
+ }
+ else
+ {
+ arelent **p;
+
+ relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (abfd, a));
+ relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms);
+ if (relcount == 0)
+ {
+ printf (" (none)\n\n");
+ }
+ else
+ {
+ printf ("\n");
+ printf ("OFFSET TYPE VALUE \n");
+
+ for (p = relpp; relcount && *p != (arelent *) NULL; p++,
+ relcount--)
+ {
+ arelent *q = *p;
+ CONST char *sym_name;
+
+ /* CONST char *section_name = q->section == (asection *)NULL ? "*abs" :*/
+ /* q->section->name;*/
+ CONST char *section_name = (*(q->sym_ptr_ptr))->section->name;
+
+ if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
+ {
+ sym_name = (*(q->sym_ptr_ptr))->name;
+ }
+ else
+ {
+ sym_name = 0;
+ }
+ if (sym_name)
+ {
+ printf_vma (q->address);
+ printf (" %-8s %s",
+ q->howto->name,
+ sym_name);
+ }
+ else
+ {
+ printf_vma (q->address);
+ printf (" %-8s [%s]",
+ q->howto->name,
+ section_name);
+ }
+ if (q->addend)
+ {
+ printf ("+0x");
+ printf_vma (q->addend);
+ }
+ printf ("\n");
+ }
+ printf ("\n\n");
+ free (relpp);
+ }
+ }
+
+ }
+}
+
+#ifdef unix
+#define _DUMMY_NAME_ "/dev/null"
+#else
+#define _DUMMY_NAME_ "##dummy"
+#endif
+static void
+DEFUN (display_info_table, (first, last),
+ int first AND int last)
+{
+ unsigned int i, j;
+ extern bfd_target *target_vector[];
+
+ printf ("\n%12s", " ");
+ for (i = first; i++ < last && target_vector[i];)
+ printf ("%s ", target_vector[i]->name);
+ printf ("\n");
+
+ for (j = (int) bfd_arch_obscure + 1; (int) j < (int) bfd_arch_last; j++)
+ if (strcmp (bfd_printable_arch_mach (j, 0), "UNKNOWN!") != 0)
+ {
+ printf ("%11s ", bfd_printable_arch_mach (j, 0));
+ for (i = first; i++ < last && target_vector[i];)
+ {
+ bfd_target *p = target_vector[i];
+ bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
+ int l = strlen (p->name);
+ int ok;
+ bfd_set_format (abfd, bfd_object);
+ ok = bfd_set_arch_mach (abfd, j, 0);
+
+ if (ok)
+ printf ("%s ", p->name);
+ else
+ {
+ while (l--)
+ printf ("%c", ok ? '*' : '-');
+ printf (" ");
+ }
+ }
+ printf ("\n");
+ }
+}
+
+static void
+DEFUN_VOID (display_info)
+{
+ char *colum;
+ unsigned int i, j, columns;
+ extern bfd_target *target_vector[];
+ extern char *getenv ();
+
+ printf ("BFD header file version %s\n", BFD_VERSION);
+ for (i = 0; target_vector[i]; i++)
+ {
+ bfd_target *p = target_vector[i];
+ bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
+ bfd_set_format (abfd, bfd_object);
+ printf ("%s\n (header %s, data %s)\n", p->name,
+ p->header_byteorder_big_p ? "big endian" : "little endian",
+ p->byteorder_big_p ? "big endian" : "little endian");
+ for (j = (int) bfd_arch_obscure + 1; j < (int) bfd_arch_last; j++)
+ if (bfd_set_arch_mach (abfd, (enum bfd_architecture) j, 0))
+ printf (" %s\n",
+ bfd_printable_arch_mach ((enum bfd_architecture) j, 0));
+ }
+ columns = 0;
+ if (colum = getenv ("COLUMNS"))
+ columns = atoi (colum);
+ if (!columns)
+ columns = 80;
+ for (i = 0; target_vector[i];)
+ {
+ int old;
+ old = i;
+ for (j = 12; target_vector[i] && j < columns; i++)
+ j += strlen (target_vector[i]->name) + 1;
+ i--;
+ if (old == i)
+ break;
+ display_info_table (old, i);
+ }
+}
+
+/** main and like trivia */
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ extern int optind;
+ extern char *optarg;
+ char *target = default_target;
+ boolean seenflag = false;
+ int ind = 0;
+
+ bfd_init ();
+ program_name = *argv;
+
+ while ((c = getopt_long (argc, argv, "ib:m:Vdlfahrtxsj:", long_options, &ind))
+ != EOF)
+ {
+ seenflag = true;
+ switch (c)
+ {
+ case 'm':
+ machine = optarg;
+ break;
+ case 'j':
+ only = optarg;
+ break;
+ case 'l':
+ with_line_numbers = 1;
+ break;
+ case 'b':
+ target = optarg;
+ break;
+ case 'f':
+ dump_file_header = true;
+ break;
+ case 'i':
+ info = true;
+ break;
+ case 'x':
+ dump_symtab = 1;
+ dump_reloc_info = 1;
+ dump_file_header = true;
+ dump_ar_hdrs = 1;
+ dump_section_headers = 1;
+ break;
+ case 0:
+ break; /* we've been given a long option */
+ case 't':
+ dump_symtab = 1;
+ break;
+ case 'd':
+ disassemble = true;
+ break;
+ case 's':
+ dump_section_contents = 1;
+ break;
+ case 'r':
+ dump_reloc_info = 1;
+ break;
+ case 'a':
+ dump_ar_hdrs = 1;
+ break;
+ case 'h':
+ dump_section_headers = 1;
+ break;
+ case 'V':
+ show_version = 1;
+ break;
+ default:
+ usage ();
+ }
+ }
+
+ if (show_version)
+ printf ("%s version %s\n", program_name, program_version);
+
+ if (seenflag == false)
+ usage ();
+
+ if (info)
+ {
+ display_info ();
+ }
+ else
+ {
+ if (optind == argc)
+ display_file ("a.out", target);
+ else
+ for (; optind < argc;)
+ display_file (argv[optind++], target);
+ }
+ return 0;
+}
diff --git a/gnu/usr.bin/gdb/objdump/objdump.h b/gnu/usr.bin/gdb/objdump/objdump.h
new file mode 100644
index 00000000000..14cf8f071a9
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/objdump.h
@@ -0,0 +1,2 @@
+
+int EXFUN(print_address,(bfd_vma, FILE*));
diff --git a/gnu/usr.bin/gdb/objdump/version.c b/gnu/usr.bin/gdb/objdump/version.c
new file mode 100644
index 00000000000..5a19113953e
--- /dev/null
+++ b/gnu/usr.bin/gdb/objdump/version.c
@@ -0,0 +1,5 @@
+/*** version.c -- version number for binutils.
+ They all change in lockstep -- it's easier that way
+*/
+
+char *program_version = VERSION;