386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Thu, 16 Apr 1992 07:00:47 +0000 (23:00 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Thu, 16 Apr 1992 07:00:47 +0000 (23:00 -0800)
Work on file usr/src/sys.386bsd/ddb/db_access.c
Work on file usr/src/sys.386bsd/ddb/db_access.h
Work on file usr/src/sys.386bsd/ddb/db_variables.c
Work on file usr/src/sys.386bsd/ddb/db_command.c
Work on file usr/src/sys.386bsd/ddb/db_break.h
Work on file usr/src/sys.386bsd/ddb/db_command.h
Work on file usr/src/sys.386bsd/ddb/db_expr.c
Work on file usr/src/sys.386bsd/ddb/db_examine.c
Work on file usr/src/sys.386bsd/ddb/db_input.c
Work on file usr/src/sys.386bsd/ddb/db_lex.c
Work on file usr/src/sys.386bsd/ddb/db_lex.h
Work on file usr/src/sys.386bsd/ddb/db_output.c
Work on file usr/src/sys.386bsd/ddb/db_output.h
Work on file usr/src/sys.386bsd/ddb/db_print.c
Work on file usr/src/sys.386bsd/ddb/db_sym.c
Work on file usr/src/sys.386bsd/ddb/db_sym.h
Work on file usr/src/sys.386bsd/ddb/db_trap.c
Work on file usr/src/sys.386bsd/ddb/db_variables.h
Work on file usr/src/sys.386bsd/ddb/db_watch.h
Work on file usr/src/sys.386bsd/ddb/db_watch.c
Work on file usr/src/sys.386bsd/ddb/db_write_cmd.c
Work on file usr/src/sys.386bsd/ddb/db_break.c
Work on file usr/src/sys.386bsd/i386/i386/db_disasm.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

23 files changed:
usr/src/sys.386bsd/ddb/db_access.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_access.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_break.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_break.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_command.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_command.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_examine.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_expr.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_input.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_lex.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_lex.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_output.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_output.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_print.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_sym.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_sym.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_trap.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_variables.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_variables.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_watch.c [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_watch.h [new file with mode: 0644]
usr/src/sys.386bsd/ddb/db_write_cmd.c [new file with mode: 0644]
usr/src/sys.386bsd/i386/i386/db_disasm.c [new file with mode: 0644]

diff --git a/usr/src/sys.386bsd/ddb/db_access.c b/usr/src/sys.386bsd/ddb/db_access.c
new file mode 100644 (file)
index 0000000..63368c0
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_access.c,v $
+ * Revision 1.1  1992/03/25  21:44:50  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:05:44  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:16:22  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:48:20  dbg
+ *     Fix type declarations.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>                /* type definitions */
+
+/*
+ * Access unaligned data items on aligned (longword)
+ * boundaries.
+ */
+
+extern void    db_read_bytes();        /* machine-dependent */
+extern void    db_write_bytes();       /* machine-dependent */
+
+int db_extend[] = {    /* table for sign-extending */
+       0,
+       0xFFFFFF80,
+       0xFFFF8000,
+       0xFF800000
+};
+
+db_expr_t
+db_get_value(addr, size, is_signed)
+       db_addr_t       addr;
+       register int    size;
+       boolean_t       is_signed;
+{
+       char            data[sizeof(int)];
+       register db_expr_t value;
+       register int    i;
+
+       db_read_bytes(addr, size, data);
+
+       value = 0;
+#if    BYTE_MSF
+       for (i = 0; i < size; i++)
+#else  /* BYTE_LSF */
+       for (i = size - 1; i >= 0; i--)
+#endif
+       {
+           value = (value << 8) + (data[i] & 0xFF);
+       }
+           
+       if (size < 4) {
+           if (is_signed && (value & db_extend[size]) != 0)
+               value |= db_extend[size];
+       }
+       return (value);
+}
+
+void
+db_put_value(addr, size, value)
+       db_addr_t       addr;
+       register int    size;
+       register db_expr_t value;
+{
+       char            data[sizeof(int)];
+       register int    i;
+
+#if    BYTE_MSF
+       for (i = size - 1; i >= 0; i--)
+#else  /* BYTE_LSF */
+       for (i = 0; i < size; i++)
+#endif
+       {
+           data[i] = value & 0xFF;
+           value >>= 8;
+       }
+
+       db_write_bytes(addr, size, data);
+}
+
diff --git a/usr/src/sys.386bsd/ddb/db_access.h b/usr/src/sys.386bsd/ddb/db_access.h
new file mode 100644 (file)
index 0000000..ddc5349
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_access.h,v $
+ * Revision 1.1  1992/03/25  21:44:53  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:05:49  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:16:37  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:48:27  dbg
+ *     Created.
+ *     [90/08/07            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Data access functions for debugger.
+ */
+#include <machine/db_machdep.h>                /* expression types */
+
+extern db_expr_t db_get_value(/* db_addr_t addr,
+                                int size,
+                                boolean_t is_signed */);
+extern void     db_put_value(/* db_addr_t addr,
+                                int size,
+                                db_expr_t value */);
diff --git a/usr/src/sys.386bsd/ddb/db_break.c b/usr/src/sys.386bsd/ddb/db_break.c
new file mode 100644 (file)
index 0000000..9db7a04
--- /dev/null
@@ -0,0 +1,387 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_break.c,v $
+ * Revision 1.1  1992/03/25  21:44:57  pace
+ * Initial revision
+ *
+ * Revision 2.7  91/02/05  17:06:00  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:01  mrt]
+ * 
+ * Revision 2.6  91/01/08  15:09:03  rpd
+ *     Added db_map_equal, db_map_current, db_map_addr.
+ *     [90/11/10            rpd]
+ * 
+ * Revision 2.5  90/11/05  14:26:32  rpd
+ *     Initialize db_breakpoints_inserted to TRUE.
+ *     [90/11/04            rpd]
+ * 
+ * Revision 2.4  90/10/25  14:43:33  rwd
+ *     Added map field to breakpoints.
+ *     Added map argument to db_set_breakpoint, db_delete_breakpoint,
+ *     db_find_breakpoint.  Added db_find_breakpoint_here.
+ *     [90/10/18            rpd]
+ * 
+ * Revision 2.3  90/09/28  16:57:07  jsb
+ *     Fixed db_breakpoint_free.
+ *     [90/09/18            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:49:53  dbg
+ *     Reflected changes in db_printsym()'s calling seq.
+ *     [90/08/20            af]
+ *     Clear breakpoints only if inserted.
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Breakpoints.
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>                /* type definitions */
+
+#include <ddb/db_lex.h>
+#include <ddb/db_break.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_break.h>
+
+extern boolean_t db_map_equal();
+extern boolean_t db_map_current();
+extern vm_map_t db_map_addr();
+
+#define        NBREAKPOINTS    100
+struct db_breakpoint   db_break_table[NBREAKPOINTS];
+db_breakpoint_t                db_next_free_breakpoint = &db_break_table[0];
+db_breakpoint_t                db_free_breakpoints = 0;
+db_breakpoint_t                db_breakpoint_list = 0;
+
+db_breakpoint_t
+db_breakpoint_alloc()
+{
+       register db_breakpoint_t        bkpt;
+
+       if ((bkpt = db_free_breakpoints) != 0) {
+           db_free_breakpoints = bkpt->link;
+           return (bkpt);
+       }
+       if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
+           db_printf("All breakpoints used.\n");
+           return (0);
+       }
+       bkpt = db_next_free_breakpoint;
+       db_next_free_breakpoint++;
+
+       return (bkpt);
+}
+
+void
+db_breakpoint_free(bkpt)
+       register db_breakpoint_t        bkpt;
+{
+       bkpt->link = db_free_breakpoints;
+       db_free_breakpoints = bkpt;
+}
+
+void
+db_set_breakpoint(map, addr, count)
+       vm_map_t        map;
+       db_addr_t       addr;
+       int             count;
+{
+       register db_breakpoint_t        bkpt;
+
+       if (db_find_breakpoint(map, addr)) {
+           db_printf("Already set.\n");
+           return;
+       }
+
+       bkpt = db_breakpoint_alloc();
+       if (bkpt == 0) {
+           db_printf("Too many breakpoints.\n");
+           return;
+       }
+
+       bkpt->map = map;
+       bkpt->address = addr;
+       bkpt->flags = 0;
+       bkpt->init_count = count;
+       bkpt->count = count;
+
+       bkpt->link = db_breakpoint_list;
+       db_breakpoint_list = bkpt;
+}
+
+void
+db_delete_breakpoint(map, addr)
+       vm_map_t        map;
+       db_addr_t       addr;
+{
+       register db_breakpoint_t        bkpt;
+       register db_breakpoint_t        *prev;
+
+       for (prev = &db_breakpoint_list;
+            (bkpt = *prev) != 0;
+            prev = &bkpt->link) {
+           if (db_map_equal(bkpt->map, map) &&
+               (bkpt->address == addr)) {
+               *prev = bkpt->link;
+               break;
+           }
+       }
+       if (bkpt == 0) {
+           db_printf("Not set.\n");
+           return;
+       }
+
+       db_breakpoint_free(bkpt);
+}
+
+db_breakpoint_t
+db_find_breakpoint(map, addr)
+       vm_map_t        map;
+       db_addr_t       addr;
+{
+       register db_breakpoint_t        bkpt;
+
+       for (bkpt = db_breakpoint_list;
+            bkpt != 0;
+            bkpt = bkpt->link)
+       {
+           if (db_map_equal(bkpt->map, map) &&
+               (bkpt->address == addr))
+               return (bkpt);
+       }
+       return (0);
+}
+
+db_breakpoint_t
+db_find_breakpoint_here(addr)
+       db_addr_t       addr;
+{
+    return db_find_breakpoint(db_map_addr(addr), addr);
+}
+
+boolean_t      db_breakpoints_inserted = TRUE;
+
+void
+db_set_breakpoints()
+{
+       register db_breakpoint_t        bkpt;
+
+       if (!db_breakpoints_inserted) {
+
+           for (bkpt = db_breakpoint_list;
+                bkpt != 0;
+                bkpt = bkpt->link)
+               if (db_map_current(bkpt->map)) {
+                   bkpt->bkpt_inst = db_get_value(bkpt->address,
+                                                  BKPT_SIZE,
+                                                  FALSE);
+                   db_put_value(bkpt->address,
+                                BKPT_SIZE,
+                                BKPT_SET(bkpt->bkpt_inst));
+               }
+           db_breakpoints_inserted = TRUE;
+       }
+}
+
+void
+db_clear_breakpoints()
+{
+       register db_breakpoint_t        bkpt;
+
+       if (db_breakpoints_inserted) {
+
+           for (bkpt = db_breakpoint_list;
+                bkpt != 0;
+                bkpt = bkpt->link)
+               if (db_map_current(bkpt->map)) {
+                   db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
+               }
+           db_breakpoints_inserted = FALSE;
+       }
+}
+
+/*
+ * Set a temporary breakpoint.
+ * The instruction is changed immediately,
+ * so the breakpoint does not have to be on the breakpoint list.
+ */
+db_breakpoint_t
+db_set_temp_breakpoint(addr)
+       db_addr_t       addr;
+{
+       register db_breakpoint_t        bkpt;
+
+       bkpt = db_breakpoint_alloc();
+       if (bkpt == 0) {
+           db_printf("Too many breakpoints.\n");
+           return 0;
+       }
+
+       bkpt->map = NULL;
+       bkpt->address = addr;
+       bkpt->flags = BKPT_TEMP;
+       bkpt->init_count = 1;
+       bkpt->count = 1;
+
+       bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
+       db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
+       return bkpt;
+}
+
+void
+db_delete_temp_breakpoint(bkpt)
+       db_breakpoint_t bkpt;
+{
+       db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
+       db_breakpoint_free(bkpt);
+}
+
+/*
+ * List breakpoints.
+ */
+void
+db_list_breakpoints()
+{
+       register db_breakpoint_t        bkpt;
+
+       if (db_breakpoint_list == 0) {
+           db_printf("No breakpoints set\n");
+           return;
+       }
+
+       db_printf(" Map      Count    Address\n");
+       for (bkpt = db_breakpoint_list;
+            bkpt != 0;
+            bkpt = bkpt->link)
+       {
+           db_printf("%s%8x %5d    ",
+                     db_map_current(bkpt->map) ? "*" : " ",
+                     bkpt->map, bkpt->init_count);
+           db_printsym(bkpt->address, DB_STGY_PROC);
+           db_printf("\n");
+       }
+}
+
+/* Delete breakpoint */
+/*ARGSUSED*/
+void
+db_delete_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
+}
+
+/* Set breakpoint with skip count */
+/*ARGSUSED*/
+void
+db_breakpoint_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       if (count == -1)
+           count = 1;
+
+       db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
+}
+
+/* list breakpoints */
+void
+db_listbreak_cmd()
+{
+       db_list_breakpoints();
+}
+
+#include <vm/vm_kern.h>
+
+/*
+ *     We want ddb to be usable before most of the kernel has been
+ *     initialized.  In particular, current_thread() or kernel_map
+ *     (or both) may be null.
+ */
+
+boolean_t
+db_map_equal(map1, map2)
+       vm_map_t        map1, map2;
+{
+       return ((map1 == map2) ||
+               ((map1 == NULL) && (map2 == kernel_map)) ||
+               ((map1 == kernel_map) && (map2 == NULL)));
+}
+
+boolean_t
+db_map_current(map)
+       vm_map_t        map;
+{
+#if 0
+       thread_t        thread;
+
+       return ((map == NULL) ||
+               (map == kernel_map) ||
+               (((thread = current_thread()) != NULL) &&
+                (map == thread->task->map)));
+#else
+       return (1);
+#endif
+}
+
+vm_map_t
+db_map_addr(addr)
+       vm_offset_t addr;
+{
+#if 0
+       thread_t        thread;
+
+       /*
+        *      We want to return kernel_map for all
+        *      non-user addresses, even when debugging
+        *      kernel tasks with their own maps.
+        */
+
+       if ((VM_MIN_ADDRESS <= addr) &&
+           (addr < VM_MAX_ADDRESS) &&
+           ((thread = current_thread()) != NULL))
+           return thread->task->map;
+       else
+#endif
+           return kernel_map;
+}
diff --git a/usr/src/sys.386bsd/ddb/db_break.h b/usr/src/sys.386bsd/ddb/db_break.h
new file mode 100644 (file)
index 0000000..874cbcb
--- /dev/null
@@ -0,0 +1,84 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_break.h,v $
+ * Revision 1.1  1992/03/25  21:44:59  pace
+ * Initial revision
+ *
+ * Revision 2.4  91/02/05  17:06:06  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:10  mrt]
+ * 
+ * Revision 2.3  90/10/25  14:43:40  rwd
+ *     Added map field to breakpoints.
+ *     [90/10/18            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:50:00  dbg
+ *     Modularized typedef names.
+ *     [90/08/20            af]
+ *     Add external defintions.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+#ifndef        _DDB_DB_BREAK_H_
+#define        _DDB_DB_BREAK_H_
+
+#include <vm/vm_map.h>
+#include <machine/db_machdep.h>
+
+/*
+ * Breakpoint.
+ */
+
+struct db_breakpoint {
+       vm_map_t map;                   /* in this map */
+       db_addr_t address;              /* set here */
+       int     init_count;             /* number of times to skip bkpt */
+       int     count;                  /* current count */
+       int     flags;                  /* flags: */
+#define        BKPT_SINGLE_STEP        0x2         /* to simulate single step */
+#define        BKPT_TEMP               0x4         /* temporary */
+       int     bkpt_inst;              /* saved instruction at bkpt */
+       struct db_breakpoint *link;     /* link in in-use or free chain */
+};
+typedef struct db_breakpoint *db_breakpoint_t;
+
+extern db_breakpoint_t db_find_breakpoint();
+extern db_breakpoint_t db_find_breakpoint_here();
+extern void            db_set_breakpoints();
+extern void            db_clear_breakpoints();
+
+extern db_breakpoint_t db_set_temp_breakpoint(/* db_addr_t addr */);
+extern void            db_delete_temp_breakpoint(/* db_breakpoint_t bkpt */);
+
+#endif _DDB_DB_BREAK_H_
diff --git a/usr/src/sys.386bsd/ddb/db_command.c b/usr/src/sys.386bsd/ddb/db_command.c
new file mode 100644 (file)
index 0000000..637ba58
--- /dev/null
@@ -0,0 +1,531 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_command.c,v $
+ * Revision 1.1  1992/03/25  21:45:02  pace
+ * Initial revision
+ *
+ * Revision 2.6  91/02/05  17:06:10  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:18  mrt]
+ * 
+ * Revision 2.5  91/01/08  17:31:54  rpd
+ *     Forward reference for db_fncall();
+ *     [91/01/04  12:35:17  rvb]
+ * 
+ *     Add call as a synonym for ! and match for next
+ *     [91/01/04  12:14:48  rvb]
+ * 
+ * Revision 2.4  90/11/07  16:49:15  rpd
+ *     Added search.
+ *     [90/11/06            rpd]
+ * 
+ * Revision 2.3  90/10/25  14:43:45  rwd
+ *     Changed db_fncall to print the result unsigned.
+ *     [90/10/19            rpd]
+ * 
+ *     Added CS_MORE to db_watchpoint_cmd.
+ *     [90/10/17            rpd]
+ *     Added watchpoint commands: watch, dwatch, show watches.
+ *     [90/10/16            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:50:10  dbg
+ *     Remove 'listbreaks' - use 'show breaks' instead.  Change 'show
+ *     threads' to 'show all threads' to avoid clash with 'show thread'.
+ *     Set 'dot' here from db_prev or db_next, depending on 'db_ed_style'
+ *     flag and syntax table.
+ *     [90/08/22            dbg]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Command dispatcher.
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>                /* type definitions */
+
+#include <ddb/db_lex.h>
+#include <ddb/db_output.h>
+
+#include <setjmp.h>
+
+/*
+ * Exported global variables
+ */
+boolean_t      db_cmd_loop_done;
+jmp_buf                db_jmpbuf;
+db_addr_t      db_dot;
+db_addr_t      db_last_addr;
+db_addr_t      db_prev;
+db_addr_t      db_next;
+
+/*
+ * if 'ed' style: 'dot' is set at start of last item printed,
+ * and '+' points to next line.
+ * Otherwise: 'dot' points to next item, '..' points to last.
+ */
+boolean_t      db_ed_style = TRUE;
+
+
+/*
+ * Utility routine - discard tokens through end-of-line.
+ */
+void
+db_skip_to_eol()
+{
+       int     t;
+       do {
+           t = db_read_token();
+       } while (t != tEOL);
+}
+
+/*
+ * Command table
+ */
+struct command {
+       char *  name;           /* command name */
+       void    (*fcn)();       /* function to call */
+       int     flag;           /* extra info: */
+#define        CS_OWN          0x1         /* non-standard syntax */
+#define        CS_MORE         0x2         /* standard syntax, but may have other
+                                      words at end */
+#define        CS_SET_DOT      0x100       /* set dot after command */
+       struct command *more;   /* another level of command */
+};
+
+/*
+ * Results of command search.
+ */
+#define        CMD_UNIQUE      0
+#define        CMD_FOUND       1
+#define        CMD_NONE        2
+#define        CMD_AMBIGUOUS   3
+#define        CMD_HELP        4
+
+/*
+ * Search for command prefix.
+ */
+int
+db_cmd_search(name, table, cmdp)
+       char *          name;
+       struct command  *table;
+       struct command  **cmdp; /* out */
+{
+       struct command  *cmd;
+       int             result = CMD_NONE;
+
+       for (cmd = table; cmd->name != 0; cmd++) {
+           register char *lp;
+           register char *rp;
+           register int  c;
+
+           lp = name;
+           rp = cmd->name;
+           while ((c = *lp) == *rp) {
+               if (c == 0) {
+                   /* complete match */
+                   *cmdp = cmd;
+                   return (CMD_UNIQUE);
+               }
+               lp++;
+               rp++;
+           }
+           if (c == 0) {
+               /* end of name, not end of command -
+                  partial match */
+               if (result == CMD_FOUND) {
+                   result = CMD_AMBIGUOUS;
+                   /* but keep looking for a full match -
+                      this lets us match single letters */
+               }
+               else {
+                   *cmdp = cmd;
+                   result = CMD_FOUND;
+               }
+           }
+       }
+       if (result == CMD_NONE) {
+           /* check for 'help' */
+               if (name[0] == 'h' && name[1] == 'e'
+                   && name[2] == 'l' && name[3] == 'p')
+                       result = CMD_HELP;
+       }
+       return (result);
+}
+
+void
+db_cmd_list(table)
+       struct command *table;
+{
+       register struct command *cmd;
+
+       for (cmd = table; cmd->name != 0; cmd++) {
+           db_printf("%-12s", cmd->name);
+           db_end_line();
+       }
+}
+
+void
+db_command(last_cmdp, cmd_table)
+       struct command  **last_cmdp;    /* IN_OUT */
+       struct command  *cmd_table;
+{
+       struct command  *cmd;
+       int             t;
+       char            modif[TOK_STRING_SIZE];
+       db_expr_t       addr, count;
+       boolean_t       have_addr;
+       int             result;
+
+       t = db_read_token();
+       if (t == tEOL) {
+           /* empty line repeats last command, at 'next' */
+           cmd = *last_cmdp;
+           addr = (db_expr_t)db_next;
+           have_addr = FALSE;
+           count = 1;
+           modif[0] = '\0';
+       }
+       else if (t == tEXCL) {
+           void db_fncall();
+           db_fncall();
+           return;
+       }
+       else if (t != tIDENT) {
+           db_printf("?\n");
+           db_flush_lex();
+           return;
+       }
+       else {
+           /*
+            * Search for command
+            */
+           while (cmd_table) {
+               result = db_cmd_search(db_tok_string,
+                                      cmd_table,
+                                      &cmd);
+               switch (result) {
+                   case CMD_NONE:
+                       db_printf("No such command\n");
+                       db_flush_lex();
+                       return;
+                   case CMD_AMBIGUOUS:
+                       db_printf("Ambiguous\n");
+                       db_flush_lex();
+                       return;
+                   case CMD_HELP:
+                       db_cmd_list(cmd_table);
+                       db_flush_lex();
+                       return;
+                   default:
+                       break;
+               }
+               if ((cmd_table = cmd->more) != 0) {
+                   t = db_read_token();
+                   if (t != tIDENT) {
+                       db_cmd_list(cmd_table);
+                       db_flush_lex();
+                       return;
+                   }
+               }
+           }
+
+           if ((cmd->flag & CS_OWN) == 0) {
+               /*
+                * Standard syntax:
+                * command [/modifier] [addr] [,count]
+                */
+               t = db_read_token();
+               if (t == tSLASH) {
+                   t = db_read_token();
+                   if (t != tIDENT) {
+                       db_printf("Bad modifier\n");
+                       db_flush_lex();
+                       return;
+                   }
+                   db_strcpy(modif, db_tok_string);
+               }
+               else {
+                   db_unread_token(t);
+                   modif[0] = '\0';
+               }
+
+               if (db_expression(&addr)) {
+                   db_dot = (db_addr_t) addr;
+                   db_last_addr = db_dot;
+                   have_addr = TRUE;
+               }
+               else {
+                   addr = (db_expr_t) db_dot;
+                   have_addr = FALSE;
+               }
+               t = db_read_token();
+               if (t == tCOMMA) {
+                   if (!db_expression(&count)) {
+                       db_printf("Count missing\n");
+                       db_flush_lex();
+                       return;
+                   }
+               }
+               else {
+                   db_unread_token(t);
+                   count = -1;
+               }
+               if ((cmd->flag & CS_MORE) == 0) {
+                   db_skip_to_eol();
+               }
+           }
+       }
+       *last_cmdp = cmd;
+       if (cmd != 0) {
+           /*
+            * Execute the command.
+            */
+           (*cmd->fcn)(addr, have_addr, count, modif);
+
+           if (cmd->flag & CS_SET_DOT) {
+               /*
+                * If command changes dot, set dot to
+                * previous address displayed (if 'ed' style).
+                */
+               if (db_ed_style) {
+                   db_dot = db_prev;
+               }
+               else {
+                   db_dot = db_next;
+               }
+           }
+           else {
+               /*
+                * If command does not change dot,
+                * set 'next' location to be the same.
+                */
+               db_next = db_dot;
+           }
+       }
+}
+
+/*
+ * 'show' commands
+ */
+extern void    db_listbreak_cmd();
+extern void    db_listwatch_cmd();
+extern void    db_show_regs(), db_show_one_thread(), db_show_all_threads();
+extern void    vm_map_print(), vm_object_print(), vm_page_print();
+extern void    ipc_port_print();
+void           db_show_help();
+
+struct command db_show_all_cmds[] = {
+#if 0
+       { "threads",    db_show_all_threads,0,  0 },
+#endif
+       { (char *)0 }
+};
+
+struct command db_show_cmds[] = {
+       { "all",        0,                      0,      db_show_all_cmds },
+       { "registers",  db_show_regs,           0,      0 },
+       { "breaks",     db_listbreak_cmd,       0,      0 },
+       { "watches",    db_listwatch_cmd,       0,      0 },
+#if 0
+       { "thread",     db_show_one_thread,     0,      0 },
+#endif
+       { "map",        vm_map_print,           0,      0 },
+       { "object",     vm_object_print,        0,      0 },
+#if 0
+       { "page",       vm_page_print,          0,      0 },
+#endif
+#if 0
+       { "port",       ipc_port_print,         0,      0 },
+#endif
+       { (char *)0, }
+};
+
+extern void    db_print_cmd(), db_examine_cmd(), db_set_cmd();
+extern void    db_search_cmd();
+extern void    db_write_cmd();
+extern void    db_delete_cmd(), db_breakpoint_cmd();
+extern void    db_deletewatch_cmd(), db_watchpoint_cmd();
+extern void    db_single_step_cmd(), db_trace_until_call_cmd(),
+               db_trace_until_matching_cmd(), db_continue_cmd();
+extern void    db_stack_trace_cmd();
+void           db_help_cmd();
+void           db_fncall();
+
+struct command db_command_table[] = {
+       { "print",      db_print_cmd,           0,      0 },
+       { "examine",    db_examine_cmd,         CS_SET_DOT, 0 },
+       { "x",          db_examine_cmd,         CS_SET_DOT, 0 },
+       { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
+       { "set",        db_set_cmd,             CS_OWN, 0 },
+       { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
+       { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
+       { "delete",     db_delete_cmd,          0,      0 },
+       { "d",          db_delete_cmd,          0,      0 },
+       { "break",      db_breakpoint_cmd,      0,      0 },
+       { "dwatch",     db_deletewatch_cmd,     0,      0 },
+       { "watch",      db_watchpoint_cmd,      CS_MORE,0 },
+       { "step",       db_single_step_cmd,     0,      0 },
+       { "s",          db_single_step_cmd,     0,      0 },
+       { "continue",   db_continue_cmd,        0,      0 },
+       { "c",          db_continue_cmd,        0,      0 },
+       { "until",      db_trace_until_call_cmd,0,      0 },
+       { "next",       db_trace_until_matching_cmd,0,  0 },
+       { "match",      db_trace_until_matching_cmd,0,  0 },
+       { "trace",      db_stack_trace_cmd,     0,      0 },
+       { "call",       db_fncall,              CS_OWN, 0 },
+       { "show",       0,                      0,      db_show_cmds },
+       { (char *)0, }
+};
+
+struct command *db_last_command = 0;
+
+void
+db_help_cmd()
+{
+       struct command *cmd = db_command_table;
+
+       while (cmd->name != 0) {
+           db_printf("%-12s", cmd->name);
+           db_end_line();
+           cmd++;
+       }
+}
+
+void
+db_command_loop()
+{
+       /*
+        * Initialize 'prev' and 'next' to dot.
+        */
+       db_prev = db_dot;
+       db_next = db_dot;
+
+       db_cmd_loop_done = 0;
+       while (!db_cmd_loop_done) {
+
+           (void) setjmp(db_jmpbuf);
+           if (db_print_position() != 0)
+               db_printf("\n");
+
+           db_printf("db> ");
+           (void) db_read_line();
+
+           db_command(&db_last_command, db_command_table);
+       }
+}
+
+void
+db_error(s)
+       char *s;
+{
+       if (s)
+           db_printf(s);
+       db_flush_lex();
+       longjmp(db_jmpbuf, 1);
+}
+
+
+/*
+ * Call random function:
+ * !expr(arg,arg,arg)
+ */
+void
+db_fncall()
+{
+       db_expr_t       fn_addr;
+#define        MAXARGS         11
+       db_expr_t       args[MAXARGS];
+       int             nargs = 0;
+       db_expr_t       retval;
+       db_expr_t       (*func)();
+       int             t;
+
+       if (!db_expression(&fn_addr)) {
+           db_printf("Bad function\n");
+           db_flush_lex();
+           return;
+       }
+       func = (db_expr_t (*) ()) fn_addr;
+
+       t = db_read_token();
+       if (t == tLPAREN) {
+           if (db_expression(&args[0])) {
+               nargs++;
+               while ((t = db_read_token()) == tCOMMA) {
+                   if (nargs == MAXARGS) {
+                       db_printf("Too many arguments\n");
+                       db_flush_lex();
+                       return;
+                   }
+                   if (!db_expression(&args[nargs])) {
+                       db_printf("Argument missing\n");
+                       db_flush_lex();
+                       return;
+                   }
+                   nargs++;
+               }
+               db_unread_token(t);
+           }
+           if (db_read_token() != tRPAREN) {
+               db_printf("?\n");
+               db_flush_lex();
+               return;
+           }
+       }
+       db_skip_to_eol();
+
+       while (nargs < MAXARGS) {
+           args[nargs++] = 0;
+       }
+
+       retval = (*func)(args[0], args[1], args[2], args[3], args[4],
+                        args[5], args[6], args[7], args[8], args[9] );
+       db_printf("%#n\n", retval);
+}
+
+int
+strcmp(s1, s2)
+       register const char *s1, *s2;
+{
+       while (*s1 == *s2++)
+               if (*s1++ == 0)
+                       return (0);
+       return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+}
+
+               
+
+       
diff --git a/usr/src/sys.386bsd/ddb/db_command.h b/usr/src/sys.386bsd/ddb/db_command.h
new file mode 100644 (file)
index 0000000..938a3d6
--- /dev/null
@@ -0,0 +1,67 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_command.h,v $
+ * Revision 1.1  1992/03/25  21:45:05  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:15  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:28  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:50:19  dbg
+ *     Replace db_last_address_examined with db_prev, db_next.
+ *     [90/08/22            dbg]
+ *     Created.
+ *     [90/08/07            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Command loop declarations.
+ */
+
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+
+extern void    db_command_loop();
+extern void    db_skip_to_eol();
+
+extern void    db_error(/* char * */); /* report error */
+
+extern db_addr_t       db_dot;         /* current location */
+extern db_addr_t       db_last_addr;   /* last explicit address typed */
+extern db_addr_t       db_prev;        /* last address examined
+                                          or written */
+extern db_addr_t       db_next;        /* next address to be examined
+                                          or written */
+
+
diff --git a/usr/src/sys.386bsd/ddb/db_examine.c b/usr/src/sys.386bsd/ddb/db_examine.c
new file mode 100644 (file)
index 0000000..66f5f68
--- /dev/null
@@ -0,0 +1,364 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_examine.c,v $
+ * Revision 1.1  1992/03/25  21:45:07  pace
+ * Initial revision
+ *
+ * Revision 2.4  91/02/05  17:06:20  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:37  mrt]
+ * 
+ * Revision 2.3  90/11/07  16:49:23  rpd
+ *     Added db_search_cmd, db_search.
+ *     [90/11/06            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:50:38  dbg
+ *     Add 'r', 'z' to print and examine formats.
+ *     Change calling sequence of db_disasm.
+ *     db_examine sets db_prev and db_next instead of explicitly
+ *     advancing dot.
+ *     [90/08/20            dbg]
+ *     Reflected changes in db_printsym()'s calling seq.
+ *     [90/08/20            af]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>                /* type definitions */
+
+#include <ddb/db_lex.h>
+#include <ddb/db_output.h>
+#include <ddb/db_command.h>
+#include <ddb/db_sym.h>
+
+char   db_examine_format[TOK_STRING_SIZE] = "x";
+
+extern db_addr_t db_disasm(/* db_addr_t, boolean_t */);
+                       /* instruction disassembler */
+
+/*
+ * Examine (print) data.
+ */
+/*ARGSUSED*/
+void
+db_examine_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       if (modif[0] != '\0')
+           db_strcpy(db_examine_format, modif);
+
+       if (count == -1)
+           count = 1;
+
+       db_examine((db_addr_t) addr, db_examine_format, count);
+}
+
+db_examine(addr, fmt, count)
+       register
+       db_addr_t       addr;
+       char *          fmt;    /* format string */
+       int             count;  /* repeat count */
+{
+       int             c;
+       db_expr_t       value;
+       int             size;
+       int             width;
+       char *          fp;
+
+       while (--count >= 0) {
+           fp = fmt;
+           size = 4;
+           width = 16;
+           while ((c = *fp++) != 0) {
+               switch (c) {
+                   case 'b':
+                       size = 1;
+                       width = 4;
+                       break;
+                   case 'h':
+                       size = 2;
+                       width = 8;
+                       break;
+                   case 'l':
+                       size = 4;
+                       width = 16;
+                       break;
+                   case 'a':   /* address */
+                       /* always forces a new line */
+                       if (db_print_position() != 0)
+                           db_printf("\n");
+                       db_prev = addr;
+                       db_printsym(addr, DB_STGY_ANY);
+                       db_printf(":\t");
+                       break;
+                   default:
+                       if (db_print_position() == 0) {
+                           /* If we hit a new symbol, print it */
+                           char *      name;
+                           db_expr_t   off;
+
+                           db_find_sym_and_offset(addr, &name, &off);
+                           if (off == 0)
+                               db_printf("%s:\t", name);
+                           else
+                               db_printf("\t\t");
+
+                           db_prev = addr;
+                       }
+
+                       switch (c) {
+                           case 'r':   /* signed, current radix */
+                               value = db_get_value(addr, size, TRUE);
+                               addr += size;
+                               db_printf("%-*r", width, value);
+                               break;
+                           case 'x':   /* unsigned hex */
+                               value = db_get_value(addr, size, FALSE);
+                               addr += size;
+                               db_printf("%-*x", width, value);
+                               break;
+                           case 'z':   /* signed hex */
+                               value = db_get_value(addr, size, TRUE);
+                               addr += size;
+                               db_printf("%-*z", width, value);
+                               break;
+                           case 'd':   /* signed decimal */
+                               value = db_get_value(addr, size, TRUE);
+                               addr += size;
+                               db_printf("%-*d", width, value);
+                               break;
+                           case 'u':   /* unsigned decimal */
+                               value = db_get_value(addr, size, FALSE);
+                               addr += size;
+                               db_printf("%-*u", width, value);
+                               break;
+                           case 'o':   /* unsigned octal */
+                               value = db_get_value(addr, size, FALSE);
+                               addr += size;
+                               db_printf("%-*o", width, value);
+                               break;
+                           case 'c':   /* character */
+                               value = db_get_value(addr, 1, FALSE);
+                               addr += 1;
+                               if (value >= ' ' && value <= '~')
+                                   db_printf("%c", value);
+                               else
+                                   db_printf("\\%03o", value);
+                               break;
+                           case 's':   /* null-terminated string */
+                               for (;;) {
+                                   value = db_get_value(addr, 1, FALSE);
+                                   addr += 1;
+                                   if (value == 0)
+                                       break;
+                                   if (value >= ' ' && value <= '~')
+                                       db_printf("%c", value);
+                                   else
+                                       db_printf("\\%03o", value);
+                               }
+                               break;
+                           case 'i':   /* instruction */
+                               addr = db_disasm(addr, FALSE);
+                               break;
+                           case 'I':   /* instruction, alternate form */
+                               addr = db_disasm(addr, TRUE);
+                               break;
+                           default:
+                               break;
+                       }
+                       if (db_print_position() != 0)
+                           db_end_line();
+                       break;
+               }
+           }
+       }
+       db_next = addr;
+}
+
+/*
+ * Print value.
+ */
+char   db_print_format = 'x';
+
+/*ARGSUSED*/
+void
+db_print_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       db_expr_t       value;
+
+       if (modif[0] != '\0')
+           db_print_format = modif[0];
+
+       switch (db_print_format) {
+           case 'a':
+               db_printsym((db_addr_t)addr, DB_STGY_ANY);
+               break;
+           case 'r':
+               db_printf("%11r", addr);
+               break;
+           case 'x':
+               db_printf("%8x", addr);
+               break;
+           case 'z':
+               db_printf("%8z", addr);
+               break;
+           case 'd':
+               db_printf("%11d", addr);
+               break;
+           case 'u':
+               db_printf("%11u", addr);
+               break;
+           case 'o':
+               db_printf("%16o", addr);
+               break;
+           case 'c':
+               value = addr & 0xFF;
+               if (value >= ' ' && value <= '~')
+                   db_printf("%c", value);
+               else
+                   db_printf("\\%03o", value);
+               break;
+       }
+       db_printf("\n");
+}
+
+db_print_loc_and_inst(loc)
+       db_addr_t       loc;
+{
+       db_printsym(loc, DB_STGY_PROC);
+       db_printf(":\t");
+       (void) db_disasm(loc, TRUE);
+}
+
+db_strcpy(dst, src)
+       register char *dst;
+       register char *src;
+{
+       while (*dst++ = *src++)
+           ;
+}
+
+/*
+ * Search for a value in memory.
+ * Syntax: search [/bhl] addr value [mask] [,count]
+ */
+void
+db_search_cmd()
+{
+       int             t;
+       db_addr_t       addr;
+       int             size;
+       db_expr_t       value;
+       db_expr_t       mask;
+       unsigned int    count;
+
+       t = db_read_token();
+       if (t == tSLASH) {
+           t = db_read_token();
+           if (t != tIDENT) {
+             bad_modifier:
+               db_printf("Bad modifier\n");
+               db_flush_lex();
+               return;
+           }
+
+           if (!strcmp(db_tok_string, "b"))
+               size = 1;
+           else if (!strcmp(db_tok_string, "h"))
+               size = 2;
+           else if (!strcmp(db_tok_string, "l"))
+               size = 4;
+           else
+               goto bad_modifier;
+       } else {
+           db_unread_token(t);
+           size = 4;
+       }
+
+       if (!db_expression(&addr)) {
+           db_printf("Address missing\n");
+           db_flush_lex();
+           return;
+       }
+
+       if (!db_expression(&value)) {
+           db_printf("Value missing\n");
+           db_flush_lex();
+           return;
+       }
+
+       if (!db_expression(&mask))
+           mask = 0xffffffff;
+
+       t = db_read_token();
+       if (t == tCOMMA) {
+           if (!db_expression(&count)) {
+               db_printf("Count missing\n");
+               db_flush_lex();
+               return;
+           }
+       } else {
+           db_unread_token(t);
+           count = -1;         /* effectively forever */
+       }
+       db_skip_to_eol();
+
+       db_search(addr, size, value, mask, count);
+}
+
+db_search(addr, size, value, mask, count)
+       register
+       db_addr_t       addr;
+       int             size;
+       db_expr_t       value;
+       db_expr_t       mask;
+       unsigned int    count;
+{
+       while (count-- != 0) {
+               db_prev = addr;
+               if ((db_get_value(addr, size, FALSE) & mask) == value)
+                       break;
+               addr += size;
+       }
+       db_next = addr;
+}
diff --git a/usr/src/sys.386bsd/ddb/db_expr.c b/usr/src/sys.386bsd/ddb/db_expr.c
new file mode 100644 (file)
index 0000000..062662c
--- /dev/null
@@ -0,0 +1,248 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_expr.c,v $
+ * Revision 1.1  1992/03/25  21:45:09  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:25  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:17:46  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:50:57  dbg
+ *     Use '..' instead of '$$' for db_prev.
+ *     Use '+' for db_next.
+ *     [90/08/22            dbg]
+ * 
+ *     Allow repeated unary operators.
+ *     [90/08/20            dbg]
+ * 
+ *     Reflected back rename of db_symbol_value->db_value_of_name
+ *     [90/08/20            af]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+#include <ddb/db_lex.h>
+#include <ddb/db_access.h>
+#include <ddb/db_command.h>
+
+boolean_t
+db_term(valuep)
+       db_expr_t *valuep;
+{
+       int     t;
+
+       t = db_read_token();
+       if (t == tIDENT) {
+           if (!db_value_of_name(db_tok_string, valuep)) {
+               db_error("Symbol not found\n");
+               /*NOTREACHED*/
+           }
+           return (TRUE);
+       }
+       if (t == tNUMBER) {
+           *valuep = (db_expr_t)db_tok_number;
+           return (TRUE);
+       }
+       if (t == tDOT) {
+           *valuep = (db_expr_t)db_dot;
+           return (TRUE);
+       }
+       if (t == tDOTDOT) {
+           *valuep = (db_expr_t)db_prev;
+           return (TRUE);
+       }
+       if (t == tPLUS) {
+           *valuep = (db_expr_t) db_next;
+           return (TRUE);
+       }
+       if (t == tDITTO) {
+           *valuep = (db_expr_t)db_last_addr;
+           return (TRUE);
+       }
+       if (t == tDOLLAR) {
+           if (!db_get_variable(valuep))
+               return (FALSE);
+           return (TRUE);
+       }
+       if (t == tLPAREN) {
+           if (!db_expression(valuep)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           t = db_read_token();
+           if (t != tRPAREN) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           return (TRUE);
+       }
+       db_unread_token(t);
+       return (FALSE);
+}
+
+boolean_t
+db_unary(valuep)
+       db_expr_t *valuep;
+{
+       int     t;
+
+       t = db_read_token();
+       if (t == tMINUS) {
+           if (!db_unary(valuep)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           *valuep = -*valuep;
+           return (TRUE);
+       }
+       if (t == tSTAR) {
+           /* indirection */
+           if (!db_unary(valuep)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           *valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE);
+           return (TRUE);
+       }
+       db_unread_token(t);
+       return (db_term(valuep));
+}
+
+boolean_t
+db_mult_expr(valuep)
+       db_expr_t *valuep;
+{
+       db_expr_t       lhs, rhs;
+       int             t;
+
+       if (!db_unary(&lhs))
+           return (FALSE);
+
+       t = db_read_token();
+       while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
+           if (!db_term(&rhs)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           if (t == tSTAR)
+               lhs *= rhs;
+           else {
+               if (rhs == 0) {
+                   db_error("Divide by 0\n");
+                   /*NOTREACHED*/
+               }
+               if (t == tSLASH)
+                   lhs /= rhs;
+               else if (t == tPCT)
+                   lhs %= rhs;
+               else
+                   lhs = ((lhs+rhs-1)/rhs)*rhs;
+           }
+           t = db_read_token();
+       }
+       db_unread_token(t);
+       *valuep = lhs;
+       return (TRUE);
+}
+
+boolean_t
+db_add_expr(valuep)
+       db_expr_t *valuep;
+{
+       db_expr_t       lhs, rhs;
+       int             t;
+
+       if (!db_mult_expr(&lhs))
+           return (FALSE);
+
+       t = db_read_token();
+       while (t == tPLUS || t == tMINUS) {
+           if (!db_mult_expr(&rhs)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           if (t == tPLUS)
+               lhs += rhs;
+           else
+               lhs -= rhs;
+           t = db_read_token();
+       }
+       db_unread_token(t);
+       *valuep = lhs;
+       return (TRUE);
+}
+
+boolean_t
+db_shift_expr(valuep)
+       db_expr_t *valuep;
+{
+       db_expr_t       lhs, rhs;
+       int             t;
+
+       if (!db_add_expr(&lhs))
+           return (FALSE);
+
+       t = db_read_token();
+       while (t == tSHIFT_L || t == tSHIFT_R) {
+           if (!db_add_expr(&rhs)) {
+               db_error("Syntax error\n");
+               /*NOTREACHED*/
+           }
+           if (rhs < 0) {
+               db_error("Negative shift amount\n");
+               /*NOTREACHED*/
+           }
+           if (t == tSHIFT_L)
+               lhs <<= rhs;
+           else {
+               /* Shift right is unsigned */
+               lhs = (unsigned) lhs >> rhs;
+           }
+           t = db_read_token();
+       }
+       db_unread_token(t);
+       *valuep = lhs;
+       return (TRUE);
+}
+
+int
+db_expression(valuep)
+       db_expr_t *valuep;
+{
+       return (db_shift_expr(valuep));
+}
diff --git a/usr/src/sys.386bsd/ddb/db_input.c b/usr/src/sys.386bsd/ddb/db_input.c
new file mode 100644 (file)
index 0000000..5ec7824
--- /dev/null
@@ -0,0 +1,268 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_input.c,v $
+ * Revision 1.1  1992/03/25  21:45:10  pace
+ * Initial revision
+ *
+ * Revision 2.4  91/02/14  14:41:53  mrt
+ *     Add input line editing.
+ *     [90/11/11            dbg]
+ * 
+ * Revision 2.3  91/02/05  17:06:32  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:13  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:51:03  dbg
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+#include "param.h"
+#include "proc.h"
+#include <ddb/db_output.h>
+
+/*
+ * Character input and editing.
+ */
+
+/*
+ * We don't track output position while editing input,
+ * since input always ends with a new-line.  We just
+ * reset the line position at the end.
+ */
+char * db_lbuf_start;  /* start of input line buffer */
+char * db_lbuf_end;    /* end of input line buffer */
+char * db_lc;          /* current character */
+char * db_le;          /* one past last character */
+
+#define        CTRL(c)         ((c) & 0x1f)
+#define        isspace(c)      ((c) == ' ' || (c) == '\t')
+#define        BLANK           ' '
+#define        BACKUP          '\b'
+
+void
+db_putstring(s, count)
+       char    *s;
+       int     count;
+{
+       while (--count >= 0)
+           cnputc(*s++);
+}
+
+void
+db_putnchars(c, count)
+       int     c;
+       int     count;
+{
+       while (--count >= 0)
+           cnputc(c);
+}
+
+/*
+ * Delete N characters, forward or backward
+ */
+#define        DEL_FWD         0
+#define        DEL_BWD         1
+void
+db_delete(n, bwd)
+       int     n;
+       int     bwd;
+{
+       register char *p;
+
+       if (bwd) {
+           db_lc -= n;
+           db_putnchars(BACKUP, n);
+       }
+       for (p = db_lc; p < db_le-n; p++) {
+           *p = *(p+n);
+           cnputc(*p);
+       }
+       db_putnchars(BLANK, n);
+       db_putnchars(BACKUP, db_le - db_lc);
+       db_le -= n;
+}
+
+/* returns TRUE at end-of-line */
+int
+db_inputchar(c)
+       int     c;
+{
+       switch (c) {
+           case CTRL('b'):
+               /* back up one character */
+               if (db_lc > db_lbuf_start) {
+                   cnputc(BACKUP);
+                   db_lc--;
+               }
+               break;
+           case CTRL('f'):
+               /* forward one character */
+               if (db_lc < db_le) {
+                   cnputc(*db_lc);
+                   db_lc++;
+               }
+               break;
+           case CTRL('a'):
+               /* beginning of line */
+               while (db_lc > db_lbuf_start) {
+                   cnputc(BACKUP);
+                   db_lc--;
+               }
+               break;
+           case CTRL('e'):
+               /* end of line */
+               while (db_lc < db_le) {
+                   cnputc(*db_lc);
+                   db_lc++;
+               }
+               break;
+           case CTRL('h'):
+           case 0177:
+               /* erase previous character */
+               if (db_lc > db_lbuf_start)
+                   db_delete(1, DEL_BWD);
+               break;
+           case CTRL('d'):
+               /* erase next character */
+               if (db_lc < db_le)
+                   db_delete(1, DEL_FWD);
+               break;
+           case CTRL('k'):
+               /* delete to end of line */
+               if (db_lc < db_le)
+                   db_delete(db_le - db_lc, DEL_FWD);
+               break;
+           case CTRL('t'):
+               /* twiddle last 2 characters */
+               if (db_lc >= db_lbuf_start + 2) {
+                   c = db_lc[-2];
+                   db_lc[-2] = db_lc[-1];
+                   db_lc[-1] = c;
+                   cnputc(BACKUP);
+                   cnputc(BACKUP);
+                   cnputc(db_lc[-2]);
+                   cnputc(db_lc[-1]);
+               }
+               break;
+           case CTRL('r'):
+               db_putstring("^R\n", 3);
+               if (db_le > db_lbuf_start) {
+                   db_putstring(db_lbuf_start, db_le - db_lbuf_start);
+                   db_putnchars(BACKUP, db_le - db_lc);
+               }
+               break;
+           case '\n':
+           case '\r':
+               *db_le++ = c;
+               return (1);
+           default:
+               if (db_le == db_lbuf_end) {
+                   cnputc('\007');
+               }
+               else if (c >= ' ' && c <= '~') {
+                   register char *p;
+
+                   for (p = db_le; p > db_lc; p--)
+                       *p = *(p-1);
+                   *db_lc++ = c;
+                   db_le++;
+                   cnputc(c);
+                   db_putstring(db_lc, db_le - db_lc);
+                   db_putnchars(BACKUP, db_le - db_lc);
+               }
+               break;
+       }
+       return (0);
+}
+
+int
+db_readline(lstart, lsize)
+       char *  lstart;
+       int     lsize;
+{
+       db_force_whitespace();  /* synch output position */
+
+       db_lbuf_start = lstart;
+       db_lbuf_end   = lstart + lsize;
+       db_lc = lstart;
+       db_le = lstart;
+
+       while (!db_inputchar(cngetc()))
+           continue;
+
+       db_putchar('\n');       /* synch output position */
+
+       *db_le = 0;
+       return (db_le - db_lbuf_start);
+}
+
+void
+db_check_interrupt()
+{
+       register int    c;
+
+       c = cnmaygetc();
+       switch (c) {
+           case -1:            /* no character */
+               return;
+
+           case CTRL('c'):
+               db_error((char *)0);
+               /*NOTREACHED*/
+
+           case CTRL('s'):
+               do {
+                   c = cnmaygetc();
+                   if (c == CTRL('c'))
+                       db_error((char *)0);
+               } while (c != CTRL('q'));
+               break;
+
+           default:
+               /* drop on floor */
+               break;
+       }
+}
+
+cnmaygetc ()
+{
+       return (-1);
+}
+
+/* called from kdb_trap in db_interface.c */
+cnpollc (flag)
+{
+}      
diff --git a/usr/src/sys.386bsd/ddb/db_lex.c b/usr/src/sys.386bsd/ddb/db_lex.c
new file mode 100644 (file)
index 0000000..dcfd900
--- /dev/null
@@ -0,0 +1,295 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_lex.c,v $
+ * Revision 1.1  1992/03/25  21:45:13  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:36  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:20  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:51:10  dbg
+ *     Add 'dotdot' token.
+ *     [90/08/22            dbg]
+ * 
+ *     Allow backslash to quote any character into an identifier.
+ *     Allow colon in identifier for symbol table qualification.
+ *     [90/08/16            dbg]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Lexical analyzer.
+ */
+#include <ddb/db_lex.h>
+
+char   db_line[120];
+char * db_lp, *db_endlp;
+
+int
+db_read_line()
+{
+       int     i;
+
+       i = db_readline(db_line, sizeof(db_line));
+       if (i == 0)
+           return (0); /* EOI */
+       db_lp = db_line;
+       db_endlp = db_lp + i;
+       return (i);
+}
+
+void
+db_flush_line()
+{
+       db_lp = db_line;
+       db_endlp = db_line;
+}
+
+int    db_look_char = 0;
+
+int
+db_read_char()
+{
+       int     c;
+
+       if (db_look_char != 0) {
+           c = db_look_char;
+           db_look_char = 0;
+       }
+       else if (db_lp >= db_endlp)
+           c = -1;
+       else 
+           c = *db_lp++;
+       return (c);
+}
+
+void
+db_unread_char(c)
+{
+       db_look_char = c;
+}
+
+int    db_look_token = 0;
+
+void
+db_unread_token(t)
+       int     t;
+{
+       db_look_token = t;
+}
+
+int
+db_read_token()
+{
+       int     t;
+
+       if (db_look_token) {
+           t = db_look_token;
+           db_look_token = 0;
+       }
+       else
+           t = db_lex();
+       return (t);
+}
+
+int    db_tok_number;
+char   db_tok_string[TOK_STRING_SIZE];
+
+int    db_radix = 16;
+
+void
+db_flush_lex()
+{
+       db_flush_line();
+       db_look_char = 0;
+       db_look_token = 0;
+}
+
+int
+db_lex()
+{
+       int     c;
+
+       c = db_read_char();
+       while (c <= ' ' || c > '~') {
+           if (c == '\n' || c == -1)
+               return (tEOL);
+           c = db_read_char();
+       }
+
+       if (c >= '0' && c <= '9') {
+           /* number */
+           int r, digit;
+
+           if (c > '0')
+               r = db_radix;
+           else {
+               c = db_read_char();
+               if (c == 'O' || c == 'o')
+                   r = 8;
+               else if (c == 'T' || c == 't')
+                   r = 10;
+               else if (c == 'X' || c == 'x')
+                   r = 16;
+               else {
+                   r = db_radix;
+                   db_unread_char(c);
+               }
+               c = db_read_char();
+           }
+           db_tok_number = 0;
+           for (;;) {
+               if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
+                   digit = c - '0';
+               else if (r == 16 && ((c >= 'A' && c <= 'F') ||
+                                    (c >= 'a' && c <= 'f'))) {
+                   if (c >= 'a')
+                       digit = c - 'a' + 10;
+                   else if (c >= 'A')
+                       digit = c - 'A' + 10;
+               }
+               else
+                   break;
+               db_tok_number = db_tok_number * r + digit;
+               c = db_read_char();
+           }
+           if ((c >= '0' && c <= '9') ||
+               (c >= 'A' && c <= 'Z') ||
+               (c >= 'a' && c <= 'z') ||
+               (c == '_'))
+           {
+               db_error("Bad character in number\n");
+               db_flush_lex();
+               return (tEOF);
+           }
+           db_unread_char(c);
+           return (tNUMBER);
+       }
+       if ((c >= 'A' && c <= 'Z') ||
+           (c >= 'a' && c <= 'z') ||
+           c == '_' || c == '\\')
+       {
+           /* string */
+           char *cp;
+
+           cp = db_tok_string;
+           if (c == '\\') {
+               c = db_read_char();
+               if (c == '\n' || c == -1)
+                   db_error("Bad escape\n");
+           }
+           *cp++ = c;
+           while (1) {
+               c = db_read_char();
+               if ((c >= 'A' && c <= 'Z') ||
+                   (c >= 'a' && c <= 'z') ||
+                   (c >= '0' && c <= '9') ||
+                   c == '_' || c == '\\' || c == ':')
+               {
+                   if (c == '\\') {
+                       c = db_read_char();
+                       if (c == '\n' || c == -1)
+                           db_error("Bad escape\n");
+                   }
+                   *cp++ = c;
+                   if (cp == db_tok_string+sizeof(db_tok_string)) {
+                       db_error("String too long\n");
+                       db_flush_lex();
+                       return (tEOF);
+                   }
+                   continue;
+               }
+               else {
+                   *cp = '\0';
+                   break;
+               }
+           }
+           db_unread_char(c);
+           return (tIDENT);
+       }
+
+       switch (c) {
+           case '+':
+               return (tPLUS);
+           case '-':
+               return (tMINUS);
+           case '.':
+               c = db_read_char();
+               if (c == '.')
+                   return (tDOTDOT);
+               db_unread_char(c);
+               return (tDOT);
+           case '*':
+               return (tSTAR);
+           case '/':
+               return (tSLASH);
+           case '=':
+               return (tEQ);
+           case '%':
+               return (tPCT);
+           case '#':
+               return (tHASH);
+           case '(':
+               return (tLPAREN);
+           case ')':
+               return (tRPAREN);
+           case ',':
+               return (tCOMMA);
+           case '"':
+               return (tDITTO);
+           case '$':
+               return (tDOLLAR);
+           case '!':
+               return (tEXCL);
+           case '<':
+               c = db_read_char();
+               if (c == '<')
+                   return (tSHIFT_L);
+               db_unread_char(c);
+               break;
+           case '>':
+               c = db_read_char();
+               if (c == '>')
+                   return (tSHIFT_R);
+               db_unread_char(c);
+               break;
+           case -1:
+               return (tEOF);
+       }
+       db_printf("Bad character\n");
+       db_flush_lex();
+       return (tEOF);
+}
diff --git a/usr/src/sys.386bsd/ddb/db_lex.h b/usr/src/sys.386bsd/ddb/db_lex.h
new file mode 100644 (file)
index 0000000..56c5569
--- /dev/null
@@ -0,0 +1,89 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_lex.h,v $
+ * Revision 1.1  1992/03/25  21:45:15  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:41  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:28  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:51:16  dbg
+ *     Add 'dotdot' token.
+ *     [90/08/22            dbg]
+ *     Export db_flush_lex.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+/*
+ * Lexical analyzer.
+ */
+extern int     db_read_line();
+extern void    db_flush_line();
+extern int     db_read_char();
+extern void    db_unread_char(/* char c */);
+extern int     db_read_token();
+extern void    db_unread_token(/* int t */);
+extern void    db_flush_lex();
+
+extern int     db_tok_number;
+#define        TOK_STRING_SIZE         120 
+extern char    db_tok_string[TOK_STRING_SIZE];
+extern int     db_radix;
+
+#define        tEOF            (-1)
+#define        tEOL            1
+#define        tNUMBER         2
+#define        tIDENT          3
+#define        tPLUS           4
+#define        tMINUS          5
+#define        tDOT            6
+#define        tSTAR           7
+#define        tSLASH          8
+#define        tEQ             9
+#define        tLPAREN         10
+#define        tRPAREN         11
+#define        tPCT            12
+#define        tHASH           13
+#define        tCOMMA          14
+#define        tDITTO          15
+#define        tDOLLAR         16
+#define        tEXCL           17
+#define        tSHIFT_L        18
+#define        tSHIFT_R        19
+#define        tDOTDOT         20
+
+
+
+
diff --git a/usr/src/sys.386bsd/ddb/db_output.c b/usr/src/sys.386bsd/ddb/db_output.c
new file mode 100644 (file)
index 0000000..5b1a986
--- /dev/null
@@ -0,0 +1,379 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_output.c,v $
+ * Revision 1.1  1992/03/25  21:45:18  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:45  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:41  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:51:25  dbg
+ *     Put extra features of db_doprnt in _doprnt.
+ *     [90/08/20            dbg]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+/*
+ * Printf and character output for debugger.
+ */
+
+#include "param.h"
+#include <machine/stdarg.h>
+
+/*
+ *     Character output - tracks position in line.
+ *     To do this correctly, we should know how wide
+ *     the output device is - then we could zero
+ *     the line position when the output device wraps
+ *     around to the start of the next line.
+ *
+ *     Instead, we count the number of spaces printed
+ *     since the last printing character so that we
+ *     don't print trailing spaces.  This avoids most
+ *     of the wraparounds.
+ */
+int    db_output_position = 0;         /* output column */
+int    db_last_non_space = 0;          /* last non-space character */
+int    db_tab_stop_width = 8;          /* how wide are tab stops? */
+#define        NEXT_TAB(i) \
+       ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
+int    db_max_width = 80;              /* output line width */
+
+extern void    db_check_interrupt();
+
+/*
+ * Force pending whitespace.
+ */
+void
+db_force_whitespace()
+{
+       register int last_print, next_tab;
+
+       last_print = db_last_non_space;
+       while (last_print < db_output_position) {
+           next_tab = NEXT_TAB(last_print);
+           if (next_tab <= db_output_position) {
+               cnputc('\t');
+               last_print = next_tab;
+           }
+           else {
+               cnputc(' ');
+               last_print++;
+           }
+       }
+       db_last_non_space = db_output_position;
+}
+
+/*
+ * Output character.  Buffer whitespace.
+ */
+db_putchar(c)
+       int     c;              /* character to output */
+{
+       if (c > ' ' && c <= '~') {
+           /*
+            * Printing character.
+            * If we have spaces to print, print them first.
+            * Use tabs if possible.
+            */
+           db_force_whitespace();
+           cnputc(c);
+           db_output_position++;
+           db_last_non_space = db_output_position;
+       }
+       else if (c == '\n') {
+           /* Return */
+           cnputc(c);
+           db_output_position = 0;
+           db_last_non_space = 0;
+           db_check_interrupt();
+       }
+       else if (c == '\t') {
+           /* assume tabs every 8 positions */
+           db_output_position = NEXT_TAB(db_output_position);
+       }
+       else if (c == ' ') {
+           /* space */
+           db_output_position++;
+       }
+       else if (c == '\007') {
+           /* bell */
+           cnputc(c);
+       }
+       /* other characters are assumed non-printing */
+}
+
+/*
+ * Return output position
+ */
+int
+db_print_position()
+{
+       return (db_output_position);
+}
+
+/*
+ * End line if too long.
+ */
+void
+db_end_line()
+{
+       if (db_output_position >= db_max_width)
+           db_printf("\n");
+}
+
+/*
+ * Printing
+ */
+extern int     db_radix;
+
+/*VARARGS1*/
+db_printf(char *fmt, ...)
+{
+       va_list listp;
+       va_start(listp, fmt);
+       db_printf_guts (fmt, listp);
+       va_end(listp);
+}
+
+/* alternate name */
+
+/*VARARGS1*/
+kdbprintf(char *fmt, ...)
+{
+       va_list listp;
+       va_start(listp, fmt);
+       db_printf_guts (fmt, listp);
+       va_end(listp);
+}
+
+/*
+ * Put a number (base <= 16) in a buffer in reverse order; return an
+ * optional length and a pointer to the NULL terminated (preceded?)
+ * buffer.
+ */
+static char *
+db_ksprintn(ul, base, lenp)
+       register u_long ul;
+       register int base, *lenp;
+{                                      /* A long in base 8, plus NULL. */
+       static char buf[sizeof(long) * NBBY / 3 + 2];
+       register char *p;
+
+       p = buf;
+       do {
+               *++p = "0123456789abcdef"[ul % base];
+       } while (ul /= base);
+       if (lenp)
+               *lenp = p - buf;
+       return (p);
+}
+
+db_printf_guts(fmt, ap)
+       register const char *fmt;
+       va_list ap;
+{
+       register char *p;
+       register int ch, n;
+       u_long ul;
+       int base, lflag, tmp, width;
+       char padc;
+       int ladjust;
+       int sharpflag;
+       int neg;
+
+       for (;;) {
+               padc = ' ';
+               width = 0;
+               while ((ch = *(u_char *)fmt++) != '%') {
+                       if (ch == '\0')
+                               return;
+                       db_putchar(ch);
+               }
+               lflag = 0;
+               ladjust = 0;
+               sharpflag = 0;
+               neg = 0;
+reswitch:      switch (ch = *(u_char *)fmt++) {
+               case '0':
+                       padc = '0';
+                       goto reswitch;
+               case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       for (width = 0;; ++fmt) {
+                               width = width * 10 + ch - '0';
+                               ch = *fmt;
+                               if (ch < '0' || ch > '9')
+                                       break;
+                       }
+                       goto reswitch;
+               case 'l':
+                       lflag = 1;
+                       goto reswitch;
+               case '-':
+                       ladjust = 1;
+                       goto reswitch;
+               case '#':
+                       sharpflag = 1;
+                       goto reswitch;
+               case 'b':
+                       ul = va_arg(ap, int);
+                       p = va_arg(ap, char *);
+                       for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;)
+                               db_putchar(ch);
+
+                       if (!ul)
+                               break;
+
+                       for (tmp = 0; n = *p++;) {
+                               if (ul & (1 << (n - 1))) {
+                                       db_putchar(tmp ? ',' : '<');
+                                       for (; (n = *p) > ' '; ++p)
+                                               db_putchar(n);
+                                       tmp = 1;
+                               } else
+                                       for (; *p > ' '; ++p);
+                       }
+                       if (tmp)
+                               db_putchar('>');
+                       break;
+               case '*':
+                       width = va_arg (ap, int);
+                       if (width < 0) {
+                               ladjust = !ladjust;
+                               width = -width;
+                       }
+                       goto reswitch;
+               case 'c':
+                       db_putchar(va_arg(ap, int));
+                       break;
+               case 's':
+                       p = va_arg(ap, char *);
+                       width -= strlen (p);
+                       if (!ladjust && width > 0)
+                               while (width--)
+                                       db_putchar (padc);
+                       while (ch = *p++)
+                               db_putchar(ch);
+                       if (ladjust && width > 0)
+                               while (width--)
+                                       db_putchar (padc);
+                       break;
+               case 'r':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       if ((long)ul < 0) {
+                               neg = 1;
+                               ul = -(long)ul;
+                       }
+                       base = db_radix;
+                       if (base < 8 || base > 16)
+                               base = 10;
+                       goto number;
+               case 'n':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       base = db_radix;
+                       if (base < 8 || base > 16)
+                               base = 10;
+                       goto number;
+               case 'd':
+                       ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
+                       if ((long)ul < 0) {
+                               neg = 1;
+                               ul = -(long)ul;
+                       }
+                       base = 10;
+                       goto number;
+               case 'o':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       base = 8;
+                       goto number;
+               case 'u':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       base = 10;
+                       goto number;
+               case 'z':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       if ((long)ul < 0) {
+                               neg = 1;
+                               ul = -(long)ul;
+                       }
+                       base = 16;
+                       goto number;
+               case 'x':
+                       ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
+                       base = 16;
+number:                        p = (char *)db_ksprintn(ul, base, &tmp);
+                       if (sharpflag && ul != 0) {
+                               if (base == 8)
+                                       tmp++;
+                               else if (base == 16)
+                                       tmp += 2;
+                       }
+                       if (neg)
+                               tmp++;
+
+                       if (!ladjust && width && (width -= tmp) > 0)
+                               while (width--)
+                                       db_putchar(padc);
+                       if (neg)
+                               db_putchar ('-');
+                       if (sharpflag && ul != 0) {
+                               if (base == 8) {
+                                       db_putchar ('0');
+                               } else if (base == 16) {
+                                       db_putchar ('0');
+                                       db_putchar ('x');
+                               }
+                       }
+                       if (ladjust && width && (width -= tmp) > 0)
+                               while (width--)
+                                       db_putchar(padc);
+
+                       while (ch = *p--)
+                               db_putchar(ch);
+                       break;
+               default:
+                       db_putchar('%');
+                       if (lflag)
+                               db_putchar('l');
+                       /* FALLTHROUGH */
+               case '%':
+                       db_putchar(ch);
+               }
+       }
+}
+
diff --git a/usr/src/sys.386bsd/ddb/db_output.h b/usr/src/sys.386bsd/ddb/db_output.h
new file mode 100644 (file)
index 0000000..3ad599d
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_output.h,v $
+ * Revision 1.1  1992/03/25  21:45:20  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:06:49  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:48  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:51:32  dbg
+ *     Created.
+ *     [90/08/07            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   8/90
+ */
+
+/*
+ * Printing routines for kernel debugger.
+ */
+
+extern void    db_force_whitespace();
+extern int     db_print_position();
+extern void    db_end_line();
+extern int     db_printf();
diff --git a/usr/src/sys.386bsd/ddb/db_print.c b/usr/src/sys.386bsd/ddb/db_print.c
new file mode 100644 (file)
index 0000000..48eef38
--- /dev/null
@@ -0,0 +1,104 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_print.c,v $
+ * Revision 1.1  1992/03/25  21:45:22  pace
+ * Initial revision
+ *
+ * Revision 2.5  91/02/05  17:06:53  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:18:56  mrt]
+ * 
+ * Revision 2.4  90/10/25  14:43:54  rwd
+ *     Changed db_show_regs to print unsigned.
+ *     [90/10/19            rpd]
+ *     Generalized the watchpoint support.
+ *     [90/10/16            rwd]
+ * 
+ * Revision 2.3  90/09/09  23:19:52  rpd
+ *     Avoid totally incorrect guesses of symbol names for small values.
+ *     [90/08/30  17:39:08  af]
+ * 
+ * Revision 2.2  90/08/27  21:51:49  dbg
+ *     Insist that 'show thread' be called with an explicit address.
+ *     [90/08/22            dbg]
+ * 
+ *     Fix type for db_maxoff.
+ *     [90/08/20            dbg]
+ * 
+ *     Do not dereference the "valuep" field of a variable directly,
+ *     call the new db_read/write_variable functions instead.
+ *     Reflected changes in symbol lookup functions.
+ *     [90/08/20            af]
+ *     Reduce lint.
+ *     [90/08/10  14:33:44  dbg]
+ * 
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+/*
+ * Miscellaneous printing.
+ */
+#include "param.h"
+#include "proc.h"
+
+#include <machine/db_machdep.h>
+
+#include <ddb/db_lex.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_sym.h>
+
+extern unsigned int    db_maxoff;
+
+void
+db_show_regs()
+{
+       int     (*func)();
+       register struct db_variable *regp;
+       db_expr_t       value, offset;
+       char *          name;
+
+       for (regp = db_regs; regp < db_eregs; regp++) {
+           db_read_variable(regp, &value);
+           db_printf("%-12s%#10n", regp->name, value);
+           db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset);
+           if (name != 0 && offset <= db_maxoff && offset != value) {
+               db_printf("\t%s", name);
+               if (offset != 0)
+                   db_printf("+%#r", offset);
+           }
+           db_printf("\n");
+       }
+       db_print_loc_and_inst(PC_REGS(DDB_REGS));
+}
+
diff --git a/usr/src/sys.386bsd/ddb/db_sym.c b/usr/src/sys.386bsd/ddb/db_sym.c
new file mode 100644 (file)
index 0000000..0517c68
--- /dev/null
@@ -0,0 +1,360 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_sym.c,v $
+ * Revision 1.1  1992/03/25  21:45:27  pace
+ * Initial revision
+ *
+ * Revision 2.5  91/02/05  17:07:07  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:19:17  mrt]
+ * 
+ * Revision 2.4  90/10/25  14:44:05  rwd
+ *     Changed db_printsym to print unsigned.
+ *     [90/10/19            rpd]
+ * 
+ * Revision 2.3  90/09/09  23:19:56  rpd
+ *     Avoid totally incorrect guesses of symbol names for small values.
+ *     [90/08/30  17:39:48  af]
+ * 
+ * Revision 2.2  90/08/27  21:52:18  dbg
+ *     Removed nlist.h.  Fixed some type declarations.
+ *     Qualifier character is ':'.
+ *     [90/08/20            dbg]
+ *     Modularized symtab info into a new db_symtab_t type.
+ *     Modified db_add_symbol_table  and others accordingly.
+ *     Defined db_sym_t, a new (opaque) type used to represent
+ *     symbols.  This should support all sort of future symtable
+ *     formats. Functions like db_qualify take a db_sym_t now.
+ *     New db_symbol_values() function to explode the content
+ *     of a db_sym_t.
+ *     db_search_symbol() replaces db_find_sym_and_offset(), which is
+ *     now a macro defined in our (new) header file.  This new
+ *     function accepts more restrictive searches, which are
+ *     entirely delegated to the symtab-specific code.
+ *     Accordingly, db_printsym() accepts a strategy parameter.
+ *     New db_line_at_pc() function.
+ *     Renamed misleading db_eqsym into db_eqname.
+ *     [90/08/20  10:47:06  af]
+ * 
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ * Revision 2.1  90/07/26  16:43:52  dbg
+ * Created.
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+
+/*
+ * We import from the symbol-table dependent routines:
+ */
+extern db_sym_t        X_db_lookup();
+extern db_sym_t        X_db_search_symbol();
+extern boolean_t X_db_line_at_pc();
+extern void    X_db_symbol_values();
+
+/*
+ * Multiple symbol tables
+ */
+#define        MAXNOSYMTABS    3       /* mach, ux, emulator */
+
+db_symtab_t    db_symtabs[MAXNOSYMTABS] = {{0,},};
+int db_nsymtab = 0;
+
+db_symtab_t    *db_last_symtab;
+
+db_sym_t       db_lookup();    /* forward */
+
+/*
+ * Add symbol table, with given name, to list of symbol tables.
+ */
+void
+db_add_symbol_table(start, end, name, ref)
+       char *start;
+       char *end;
+       char *name;
+       char *ref;
+{
+       if (db_nsymtab >= MAXNOSYMTABS) {
+               printf ("No slots left for %s symbol table", name);
+               panic ("db_sym.c: db_add_symbol_table");
+       }
+
+       db_symtabs[db_nsymtab].start = start;
+       db_symtabs[db_nsymtab].end = end;
+       db_symtabs[db_nsymtab].name = name;
+       db_symtabs[db_nsymtab].private = ref;
+       db_nsymtab++;
+}
+
+/*
+ *  db_qualify("vm_map", "ux") returns "unix:vm_map".
+ *
+ *  Note: return value points to static data whose content is
+ *  overwritten by each call... but in practice this seems okay.
+ */
+static char *
+db_qualify(sym, symtabname)
+       db_sym_t        sym;
+       register char   *symtabname;
+{
+       char            *symname;
+       static char     tmp[256];
+       register char   *s;
+
+       db_symbol_values(sym, &symname, 0);
+       s = tmp;
+       while (*s++ = *symtabname++) {
+       }
+       s[-1] = ':';
+       while (*s++ = *symname++) {
+       }
+       return tmp;
+}
+
+
+boolean_t
+db_eqname(src, dst, c)
+       char *src;
+       char *dst;
+       char c;
+{
+       if (!strcmp(src, dst))
+           return (TRUE);
+       if (src[0] == c)
+           return (!strcmp(src+1,dst));
+       return (FALSE);
+}
+
+boolean_t
+db_value_of_name(name, valuep)
+       char            *name;
+       db_expr_t       *valuep;
+{
+       db_sym_t        sym;
+
+       sym = db_lookup(name);
+       if (sym == DB_SYM_NULL)
+           return (FALSE);
+       db_symbol_values(sym, &name, valuep);
+       return (TRUE);
+}
+
+
+/*
+ * Lookup a symbol.
+ * If the symbol has a qualifier (e.g., ux:vm_map),
+ * then only the specified symbol table will be searched;
+ * otherwise, all symbol tables will be searched.
+ */
+db_sym_t
+db_lookup(symstr)
+       char *symstr;
+{
+       db_sym_t sp;
+       register int i;
+       int symtab_start = 0;
+       int symtab_end = db_nsymtab;
+       register char *cp;
+
+       /*
+        * Look for, remove, and remember any symbol table specifier.
+        */
+       for (cp = symstr; *cp; cp++) {
+               if (*cp == ':') {
+                       *cp = '\0';
+                       for (i = 0; i < db_nsymtab; i++) {
+                               if (! strcmp(symstr, db_symtabs[i].name)) {
+                                       symtab_start = i;
+                                       symtab_end = i + 1;
+                                       break;
+                               }
+                       }
+                       *cp = ':';
+                       if (i == db_nsymtab) {
+                               db_error("invalid symbol table name");
+                       }
+                       symstr = cp+1;
+               }
+       }
+
+       /*
+        * Look in the specified set of symbol tables.
+        * Return on first match.
+        */
+       for (i = symtab_start; i < symtab_end; i++) {
+               if (sp = X_db_lookup(&db_symtabs[i], symstr)) {
+                       db_last_symtab = &db_symtabs[i];
+                       return sp;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Does this symbol name appear in more than one symbol table?
+ * Used by db_symbol_values to decide whether to qualify a symbol.
+ */
+boolean_t db_qualify_ambiguous_names = FALSE;
+
+boolean_t
+db_symbol_is_ambiguous(sym)
+       db_sym_t        sym;
+{
+       char            *sym_name;
+       register int    i;
+       register
+       boolean_t       found_once = FALSE;
+
+       if (!db_qualify_ambiguous_names)
+               return FALSE;
+
+       db_symbol_values(sym, &sym_name, 0);
+       for (i = 0; i < db_nsymtab; i++) {
+               if (X_db_lookup(&db_symtabs[i], sym_name)) {
+                       if (found_once)
+                               return TRUE;
+                       found_once = TRUE;
+               }
+       }
+       return FALSE;
+}
+
+/*
+ * Find the closest symbol to val, and return its name
+ * and the difference between val and the symbol found.
+ */
+db_sym_t
+db_search_symbol( val, strategy, offp)
+       register db_addr_t      val;
+       db_strategy_t           strategy;
+       db_expr_t               *offp;
+{
+       register
+       unsigned int    diff;
+       unsigned int    newdiff;
+       register int    i;
+       db_sym_t        ret = DB_SYM_NULL, sym;
+
+       newdiff = diff = ~0;
+       db_last_symtab = 0;
+       for (i = 0; i < db_nsymtab; i++) {
+           sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
+           if (newdiff < diff) {
+               db_last_symtab = &db_symtabs[i];
+               diff = newdiff;
+               ret = sym;
+           }
+       }
+       *offp = diff;
+       return ret;
+}
+
+/*
+ * Return name and value of a symbol
+ */
+void
+db_symbol_values(sym, namep, valuep)
+       db_sym_t        sym;
+       char            **namep;
+       db_expr_t       *valuep;
+{
+       db_expr_t       value;
+
+       if (sym == DB_SYM_NULL) {
+               *namep = 0;
+               return;
+       }
+
+       X_db_symbol_values(sym, namep, &value);
+
+       if (db_symbol_is_ambiguous(sym))
+               *namep = db_qualify(sym, db_last_symtab->name);
+       if (valuep)
+               *valuep = value;
+}
+
+
+/*
+ * Print a the closest symbol to value
+ *
+ * After matching the symbol according to the given strategy
+ * we print it in the name+offset format, provided the symbol's
+ * value is close enough (eg smaller than db_maxoff).
+ * We also attempt to print [filename:linenum] when applicable
+ * (eg for procedure names).
+ *
+ * If we could not find a reasonable name+offset representation,
+ * then we just print the value in hex.  Small values might get
+ * bogus symbol associations, e.g. 3 might get some absolute
+ * value like _INCLUDE_VERSION or something, therefore we do
+ * not accept symbols whose value is zero (and use plain hex).
+ */
+
+unsigned int   db_maxoff = 0x10000000;
+
+void
+db_printsym(off, strategy)
+       db_expr_t       off;
+       db_strategy_t   strategy;
+{
+       db_expr_t       d;
+       char            *filename;
+       char            *name;
+       db_expr_t       value;
+       int             linenum;
+       db_sym_t        cursym;
+
+       cursym = db_search_symbol(off, strategy, &d);
+       db_symbol_values(cursym, &name, &value);
+       if (name == 0 || d >= db_maxoff || value == 0) {
+               db_printf("%#n", off);
+               return;
+       }
+       db_printf("%s", name);
+       if (d)
+               db_printf("+%#r", d);
+       if (strategy == DB_STGY_PROC) {
+               if (db_line_at_pc(cursym, &filename, &linenum, off))
+                       db_printf(" [%s:%d]", filename, linenum);
+       }
+}
+
+
+boolean_t
+db_line_at_pc( sym, filename, linenum, pc)
+{
+       return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
+}
diff --git a/usr/src/sys.386bsd/ddb/db_sym.h b/usr/src/sys.386bsd/ddb/db_sym.h
new file mode 100644 (file)
index 0000000..663f1cd
--- /dev/null
@@ -0,0 +1,114 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_sym.h,v $
+ * Revision 1.1  1992/03/25  21:45:29  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:07:12  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:19:27  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:52:39  dbg
+ *     Changed type of db_sym_t to char * - it's a better type for an
+ *     opaque pointer.
+ *     [90/08/22            dbg]
+ * 
+ *     Created.
+ *     [90/08/19            af]
+ * 
+ */
+/*
+ *     Author: Alessandro Forin, Carnegie Mellon University
+ *     Date:   8/90
+ */
+
+/*
+ * This module can handle multiple symbol tables
+ */
+typedef struct {
+       char            *name;          /* symtab name */
+       char            *start;         /* symtab location */
+       char            *end;
+       char            *private;       /* optional machdep pointer */
+} db_symtab_t;
+
+extern db_symtab_t     *db_last_symtab; /* where last symbol was found */
+
+/*
+ * Symbol representation is specific to the symtab style:
+ * BSD compilers use dbx' nlist, other compilers might use
+ * a different one
+ */
+typedef        char *          db_sym_t;       /* opaque handle on symbols */
+#define        DB_SYM_NULL     ((db_sym_t)0)
+
+/*
+ * Non-stripped symbol tables will have duplicates, for instance
+ * the same string could match a parameter name, a local var, a
+ * global var, etc.
+ * We are most concern with the following matches.
+ */
+typedef int            db_strategy_t;  /* search strategy */
+
+#define        DB_STGY_ANY     0                       /* anything goes */
+#define DB_STGY_XTRN   1                       /* only external symbols */
+#define DB_STGY_PROC   2                       /* only procedures */
+
+extern boolean_t       db_qualify_ambiguous_names;
+                                       /* if TRUE, check across symbol tables
+                                        * for multiple occurrences of a name.
+                                        * Might slow down quite a bit */
+
+/*
+ * Functions exported by the symtable module
+ */
+extern void    db_add_symbol_table();
+                                       /* extend the list of symbol tables */
+
+extern int     db_value_of_name(/* char*, db_expr_t* */);
+                                       /* find symbol value given name */
+
+extern db_sym_t        db_search_symbol(/* db_expr_t, db_strategy_t, int* */);
+                                       /* find symbol given value */
+
+extern void    db_symbol_values(/* db_sym_t, char**, db_expr_t* */);
+                                       /* return name and value of symbol */
+
+#define db_find_sym_and_offset(val,namep,offp) \
+       db_symbol_values(db_search_symbol(val,DB_STGY_ANY,offp),namep,0)
+                                       /* find name&value given approx val */
+
+#define db_find_xtrn_sym_and_offset(val,namep,offp)    \
+       db_symbol_values(db_search_symbol(val,DB_STGY_XTRN,offp),namep,0)
+                                       /* ditto, but no locals */
+
+extern int     db_eqname(/* char*, char*, char */);
+                                       /* strcmp, modulo leading char */
+
+extern void    db_printsym(/* db_expr_t, db_strategy_t */);
+                                       /* print closest symbol to a value */
diff --git a/usr/src/sys.386bsd/ddb/db_trap.c b/usr/src/sys.386bsd/ddb/db_trap.c
new file mode 100644 (file)
index 0000000..099fab1
--- /dev/null
@@ -0,0 +1,106 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_trap.c,v $
+ * Revision 1.1  1992/03/25  21:45:31  pace
+ * Initial revision
+ *
+ * Revision 2.5  91/02/05  17:07:16  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:19:35  mrt]
+ * 
+ * Revision 2.4  91/01/08  15:09:17  rpd
+ *     Changed db_stop_at_pc's arguments.
+ *     Print db_inst_count, db_load_count, db_store_count.
+ *     [90/11/27            rpd]
+ * 
+ * Revision 2.3  90/10/25  14:44:11  rwd
+ *     From rpd.
+ *     [90/10/19  17:03:17  rwd]
+ * 
+ *     Generalized the watchpoint support.
+ *     [90/10/16            rwd]
+ *     Added watchpoint support.
+ *     [90/10/16            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:52:52  dbg
+ *     Assign to db_dot before calling the print function.
+ *     [90/08/20            af]
+ *     Reduce lint.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+/*
+ * Trap entry point to kernel debugger.
+ */
+#include "param.h"
+#include "proc.h"
+#include <ddb/db_command.h>
+#include <ddb/db_break.h>
+
+extern void            db_restart_at_pc();
+extern boolean_t       db_stop_at_pc();
+
+extern int             db_inst_count;
+extern int             db_load_count;
+extern int             db_store_count;
+
+db_trap(type, code)
+       int     type, code;
+{
+       boolean_t       bkpt;
+       boolean_t       watchpt;
+
+       bkpt = IS_BREAKPOINT_TRAP(type, code);
+       watchpt = IS_WATCHPOINT_TRAP(type, code);
+
+       if (db_stop_at_pc(&bkpt)) {
+           if (db_inst_count) {
+               db_printf("After %d instructions (%d loads, %d stores),\n",
+                         db_inst_count, db_load_count, db_store_count);
+           }
+           if (bkpt)
+               db_printf("Breakpoint at\t");
+           else if (watchpt)
+               db_printf("Watchpoint at\t");
+           else
+               db_printf("Stopped at\t");
+           db_dot = PC_REGS(DDB_REGS);
+           db_print_loc_and_inst(db_dot);
+
+           db_command_loop();
+       }
+
+       db_restart_at_pc(watchpt);
+}
diff --git a/usr/src/sys.386bsd/ddb/db_variables.c b/usr/src/sys.386bsd/ddb/db_variables.c
new file mode 100644 (file)
index 0000000..ed9512d
--- /dev/null
@@ -0,0 +1,186 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_variables.c,v $
+ * Revision 1.1  1992/03/25  21:45:33  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:07:19  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:19:46  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:53:24  dbg
+ *     New db_read/write_variable functions.  Should be used instead
+ *     of dereferencing valuep directly, which might not be a true
+ *     pointer if there is an fcn() access function.
+ *     [90/08/20            af]
+ * 
+ *     Fix declarations.
+ *     Check for trailing garbage after last expression on command line.
+ *     [90/08/10  14:34:54  dbg]
+ * 
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+
+#include <ddb/db_lex.h>
+#include <ddb/db_variables.h>
+
+extern unsigned int    db_maxoff;
+
+extern int     db_radix;
+extern int     db_max_width;
+extern int     db_tab_stop_width;
+
+struct db_variable db_vars[] = {
+       { "radix",      &db_radix, FCN_NULL },
+       { "maxoff",     (int *)&db_maxoff, FCN_NULL },
+       { "maxwidth",   &db_max_width, FCN_NULL },
+       { "tabstops",   &db_tab_stop_width, FCN_NULL },
+};
+struct db_variable *db_evars = db_vars + sizeof(db_vars)/sizeof(db_vars[0]);
+
+int
+db_find_variable(varp)
+       struct db_variable      **varp;
+{
+       int     t;
+       struct db_variable *vp;
+
+       t = db_read_token();
+       if (t == tIDENT) {
+           for (vp = db_vars; vp < db_evars; vp++) {
+               if (!strcmp(db_tok_string, vp->name)) {
+                   *varp = vp;
+                   return (1);
+               }
+           }
+           for (vp = db_regs; vp < db_eregs; vp++) {
+               if (!strcmp(db_tok_string, vp->name)) {
+                   *varp = vp;
+                   return (1);
+               }
+           }
+       }
+       db_error("Unknown variable\n");
+       return (0);
+}
+
+int
+db_get_variable(valuep)
+       db_expr_t       *valuep;
+{
+       struct db_variable *vp;
+
+       if (!db_find_variable(&vp))
+           return (0);
+
+       db_read_variable(vp, valuep);
+
+       return (1);
+}
+
+int
+db_set_variable(value)
+       db_expr_t       value;
+{
+       struct db_variable *vp;
+
+       if (!db_find_variable(&vp))
+           return (0);
+
+       db_write_variable(vp, &value);
+
+       return (1);
+}
+
+
+db_read_variable(vp, valuep)
+       struct db_variable *vp;
+       db_expr_t       *valuep;
+{
+       int     (*func)() = vp->fcn;
+
+       if (func == FCN_NULL)
+           *valuep = *(vp->valuep);
+       else
+           (*func)(vp, valuep, DB_VAR_GET);
+}
+
+db_write_variable(vp, valuep)
+       struct db_variable *vp;
+       db_expr_t       *valuep;
+{
+       int     (*func)() = vp->fcn;
+
+       if (func == FCN_NULL)
+           *(vp->valuep) = *valuep;
+       else
+           (*func)(vp, valuep, DB_VAR_SET);
+}
+
+void
+db_set_cmd()
+{
+       db_expr_t       value;
+       int     (*func)();
+       struct db_variable *vp;
+       int     t;
+
+       t = db_read_token();
+       if (t != tDOLLAR) {
+           db_error("Unknown variable\n");
+           return;
+       }
+       if (!db_find_variable(&vp)) {
+           db_error("Unknown variable\n");
+           return;
+       }
+
+       t = db_read_token();
+       if (t != tEQ)
+           db_unread_token(t);
+
+       if (!db_expression(&value)) {
+           db_error("No value\n");
+           return;
+       }
+       if (db_read_token() != tEOL) {
+           db_error("?\n");
+       }
+
+       db_write_variable(vp, &value);
+}
diff --git a/usr/src/sys.386bsd/ddb/db_variables.h b/usr/src/sys.386bsd/ddb/db_variables.h
new file mode 100644 (file)
index 0000000..f958d2c
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_variables.h,v $
+ * Revision 1.1  1992/03/25  21:45:35  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:07:23  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:19:54  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:53:40  dbg
+ *     Modularized typedef name.  Documented the calling sequence of
+ *     the (optional) access function of a variable.  Now the valuep
+ *     field can be made opaque, eg be an offset that fcn() resolves.
+ *     [90/08/20            af]
+ * 
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+#ifndef        _DB_VARIABLES_H_
+#define        _DB_VARIABLES_H_
+
+/*
+ * Debugger variables.
+ */
+struct db_variable {
+       char    *name;          /* Name of variable */
+       int     *valuep;        /* value of variable */
+                               /* function to call when reading/writing */
+       int     (*fcn)(/* db_variable *vp, db_expr_t *valuep, int op */);
+#define DB_VAR_GET     0
+#define DB_VAR_SET     1
+};
+#define        FCN_NULL        ((int (*)())0)
+
+extern struct db_variable      db_vars[];      /* debugger variables */
+extern struct db_variable      *db_evars;
+extern struct db_variable      db_regs[];      /* machine registers */
+extern struct db_variable      *db_eregs;
+
+#endif /* _DB_VARIABLES_H_ */
diff --git a/usr/src/sys.386bsd/ddb/db_watch.c b/usr/src/sys.386bsd/ddb/db_watch.c
new file mode 100644 (file)
index 0000000..e69d906
--- /dev/null
@@ -0,0 +1,294 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_watch.c,v $
+ * Revision 1.1  1992/03/25  21:45:37  pace
+ * Initial revision
+ *
+ * Revision 2.5  91/02/05  17:07:27  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:20:02  mrt]
+ * 
+ * Revision 2.4  91/01/08  15:09:24  rpd
+ *     Use db_map_equal, db_map_current, db_map_addr.
+ *     [90/11/10            rpd]
+ * 
+ * Revision 2.3  90/11/05  14:26:39  rpd
+ *     Initialize db_watchpoints_inserted to TRUE.
+ *     [90/11/04            rpd]
+ * 
+ * Revision 2.2  90/10/25  14:44:16  rwd
+ *     Made db_watchpoint_cmd parse a size argument.
+ *     [90/10/17            rpd]
+ *     Generalized the watchpoint support.
+ *     [90/10/16            rwd]
+ *     Created.
+ *     [90/10/16            rpd]
+ * 
+ */
+/*
+ *     Author: Richard P. Draves, Carnegie Mellon University
+ *     Date:   10/90
+ */
+
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+
+#include <vm/vm_map.h>
+#include <ddb/db_lex.h>
+#include <ddb/db_watch.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <machine/db_machdep.h>
+
+/*
+ * Watchpoints.
+ */
+
+extern boolean_t db_map_equal();
+extern boolean_t db_map_current();
+extern vm_map_t db_map_addr();
+
+boolean_t      db_watchpoints_inserted = TRUE;
+
+#define        NWATCHPOINTS    100
+struct db_watchpoint   db_watch_table[NWATCHPOINTS];
+db_watchpoint_t                db_next_free_watchpoint = &db_watch_table[0];
+db_watchpoint_t                db_free_watchpoints = 0;
+db_watchpoint_t                db_watchpoint_list = 0;
+
+db_watchpoint_t
+db_watchpoint_alloc()
+{
+       register db_watchpoint_t        watch;
+
+       if ((watch = db_free_watchpoints) != 0) {
+           db_free_watchpoints = watch->link;
+           return (watch);
+       }
+       if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
+           db_printf("All watchpoints used.\n");
+           return (0);
+       }
+       watch = db_next_free_watchpoint;
+       db_next_free_watchpoint++;
+
+       return (watch);
+}
+
+void
+db_watchpoint_free(watch)
+       register db_watchpoint_t        watch;
+{
+       watch->link = db_free_watchpoints;
+       db_free_watchpoints = watch;
+}
+
+void
+db_set_watchpoint(map, addr, size)
+       vm_map_t        map;
+       db_addr_t       addr;
+       vm_size_t       size;
+{
+       register db_watchpoint_t        watch;
+
+       if (map == NULL) {
+           db_printf("No map.\n");
+           return;
+       }
+
+       /*
+        *      Should we do anything fancy with overlapping regions?
+        */
+
+       for (watch = db_watchpoint_list;
+            watch != 0;
+            watch = watch->link)
+           if (db_map_equal(watch->map, map) &&
+               (watch->loaddr == addr) &&
+               (watch->hiaddr == addr+size)) {
+               db_printf("Already set.\n");
+               return;
+           }
+
+       watch = db_watchpoint_alloc();
+       if (watch == 0) {
+           db_printf("Too many watchpoints.\n");
+           return;
+       }
+
+       watch->map = map;
+       watch->loaddr = addr;
+       watch->hiaddr = addr+size;
+
+       watch->link = db_watchpoint_list;
+       db_watchpoint_list = watch;
+
+       db_watchpoints_inserted = FALSE;
+}
+
+void
+db_delete_watchpoint(map, addr)
+       vm_map_t        map;
+       db_addr_t       addr;
+{
+       register db_watchpoint_t        watch;
+       register db_watchpoint_t        *prev;
+
+       for (prev = &db_watchpoint_list;
+            (watch = *prev) != 0;
+            prev = &watch->link)
+           if (db_map_equal(watch->map, map) &&
+               (watch->loaddr <= addr) &&
+               (addr < watch->hiaddr)) {
+               *prev = watch->link;
+               db_watchpoint_free(watch);
+               return;
+           }
+
+       db_printf("Not set.\n");
+}
+
+void
+db_list_watchpoints()
+{
+       register db_watchpoint_t        watch;
+
+       if (db_watchpoint_list == 0) {
+           db_printf("No watchpoints set\n");
+           return;
+       }
+
+       db_printf(" Map        Address  Size\n");
+       for (watch = db_watchpoint_list;
+            watch != 0;
+            watch = watch->link)
+           db_printf("%s%8x  %8x  %x\n",
+                     db_map_current(watch->map) ? "*" : " ",
+                     watch->map, watch->loaddr,
+                     watch->hiaddr - watch->loaddr);
+}
+
+/* Delete watchpoint */
+/*ARGSUSED*/
+void
+db_deletewatch_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       db_delete_watchpoint(db_map_addr(addr), addr);
+}
+
+/* Set watchpoint */
+/*ARGSUSED*/
+void
+db_watchpoint_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       vm_size_t       size;
+       db_expr_t       value;
+
+       if (db_expression(&value))
+           size = (vm_size_t) value;
+       else
+           size = 4;
+       db_skip_to_eol();
+
+       db_set_watchpoint(db_map_addr(addr), addr, size);
+}
+
+/* list watchpoints */
+void
+db_listwatch_cmd()
+{
+       db_list_watchpoints();
+}
+
+void
+db_set_watchpoints()
+{
+       register db_watchpoint_t        watch;
+
+       if (!db_watchpoints_inserted) {
+           for (watch = db_watchpoint_list;
+                watch != 0;
+                watch = watch->link)
+               pmap_protect(watch->map->pmap,
+                            trunc_page(watch->loaddr),
+                            round_page(watch->hiaddr),
+                            VM_PROT_READ);
+
+           db_watchpoints_inserted = TRUE;
+       }
+}
+
+void
+db_clear_watchpoints()
+{
+       db_watchpoints_inserted = FALSE;
+}
+
+boolean_t
+db_find_watchpoint(map, addr, regs)
+       vm_map_t        map;
+       db_addr_t       addr;
+       db_regs_t       *regs;
+{
+       register db_watchpoint_t watch;
+       db_watchpoint_t found = 0;
+
+       for (watch = db_watchpoint_list;
+            watch != 0;
+            watch = watch->link)
+           if (db_map_equal(watch->map, map)) {
+               if ((watch->loaddr <= addr) &&
+                   (addr < watch->hiaddr))
+                   return (TRUE);
+               else if ((trunc_page(watch->loaddr) <= addr) &&
+                        (addr < round_page(watch->hiaddr)))
+                   found = watch;
+           }
+
+       /*
+        *      We didn't hit exactly on a watchpoint, but we are
+        *      in a protected region.  We want to single-step
+        *      and then re-protect.
+        */
+
+       if (found) {
+           db_watchpoints_inserted = FALSE;
+           db_single_step(regs);
+       }
+
+       return (FALSE);
+}
diff --git a/usr/src/sys.386bsd/ddb/db_watch.h b/usr/src/sys.386bsd/ddb/db_watch.h
new file mode 100644 (file)
index 0000000..9795755
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_watch.h,v $
+ * Revision 1.1  1992/03/25  21:45:40  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:07:31  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:20:09  mrt]
+ * 
+ * Revision 2.2  90/10/25  14:44:21  rwd
+ *     Generalized the watchpoint support.
+ *     [90/10/16            rwd]
+ *     Created.
+ *     [90/10/16            rpd]
+ * 
+ */
+/*
+ *     Author: David B. Golub, Carnegie Mellon University
+ *     Date:   10/90
+ */
+
+#ifndef        _DDB_DB_WATCH_
+#define        _DDB_DB_WATCH_
+
+#include <vm/vm_map.h>
+#include <machine/db_machdep.h>
+
+/*
+ * Watchpoint.
+ */
+
+typedef struct db_watchpoint {
+       vm_map_t map;                   /* in this map */
+       db_addr_t loaddr;               /* from this address */
+       db_addr_t hiaddr;               /* to this address */
+       struct db_watchpoint *link;     /* link in in-use or free chain */
+} *db_watchpoint_t;
+
+extern boolean_t db_find_watchpoint(/* vm_map_t map, db_addr_t addr,
+                                    db_regs_t *regs */);
+extern void db_set_watchpoints();
+extern void db_clear_watchpoints();
+
+extern void db_set_watchpoint(/* vm_map_t map, db_addr_t addr, vm_size_t size */);
+extern void db_delete_watchpoint(/* vm_map_t map, db_addr_t addr */);
+extern void db_list_watchpoints();
+
+#endif _DDB_DB_WATCH_
diff --git a/usr/src/sys.386bsd/ddb/db_write_cmd.c b/usr/src/sys.386bsd/ddb/db_write_cmd.c
new file mode 100644 (file)
index 0000000..dce22a9
--- /dev/null
@@ -0,0 +1,120 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_write_cmd.c,v $
+ * Revision 1.1  1992/03/25  21:45:42  pace
+ * Initial revision
+ *
+ * Revision 2.4  91/02/05  17:07:35  mrt
+ *     Changed to new Mach copyright
+ *     [91/01/31  16:20:19  mrt]
+ * 
+ * Revision 2.3  90/10/25  14:44:26  rwd
+ *     Changed db_write_cmd to print unsigned.
+ *     [90/10/19            rpd]
+ * 
+ * Revision 2.2  90/08/27  21:53:54  dbg
+ *     Set db_prev and db_next instead of explicitly advancing dot.
+ *     [90/08/22            dbg]
+ *     Reflected changes in db_printsym()'s calling seq.
+ *     [90/08/20            af]
+ *     Warn user if nothing was written.
+ *     [90/08/07            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+/*
+ *     Author: David B. Golub,  Carnegie Mellon University
+ *     Date:   7/90
+ */
+
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+
+#include <ddb/db_lex.h>
+#include <ddb/db_access.h>
+#include <ddb/db_command.h>
+#include <ddb/db_sym.h>
+
+/*
+ * Write to file.
+ */
+/*ARGSUSED*/
+void
+db_write_cmd(address, have_addr, count, modif)
+       db_expr_t       address;
+       boolean_t       have_addr;
+       db_expr_t       count;
+       char *          modif;
+{
+       register
+       db_addr_t       addr;
+       register
+       db_expr_t       old_value;
+       db_expr_t       new_value;
+       register int    size;
+       boolean_t       wrote_one = FALSE;
+
+       addr = (db_addr_t) address;
+
+       switch (modif[0]) {
+           case 'b':
+               size = 1;
+               break;
+           case 'h':
+               size = 2;
+               break;
+           case 'l':
+           case '\0':
+               size = 4;
+               break;
+           default:
+               db_error("Unknown size\n");
+               return;
+       }
+
+       while (db_expression(&new_value)) {
+           old_value = db_get_value(addr, size, FALSE);
+           db_printsym(addr, DB_STGY_ANY);
+           db_printf("\t\t%#8n\t=\t%#8n\n", old_value, new_value);
+           db_put_value(addr, size, new_value);
+           addr += size;
+
+           wrote_one = TRUE;
+       }
+
+       if (!wrote_one)
+           db_error("Nothing written.\n");
+
+       db_next = addr;
+       db_prev = addr - size;
+
+       db_skip_to_eol();
+}
+
diff --git a/usr/src/sys.386bsd/i386/i386/db_disasm.c b/usr/src/sys.386bsd/i386/i386/db_disasm.c
new file mode 100644 (file)
index 0000000..20430b6
--- /dev/null
@@ -0,0 +1,1397 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_disasm.c,v $
+ * Revision 1.1  1992/03/25  21:42:01  pace
+ * Initial revision
+ *
+ * Revision 2.3  91/02/05  17:11:03  mrt
+ *     Changed to new Mach copyright
+ *     [91/02/01  17:31:03  mrt]
+ * 
+ * Revision 2.2  90/08/27  21:55:56  dbg
+ *     Fix register operand for move to/from control/test/debug
+ *     register instructions.  Add i486 instructions.
+ *     [90/08/27            dbg]
+ * 
+ *     Import db_sym.h.  Print instruction displacements in
+ *     current radix (signed).  Change calling sequence of
+ *     db_disasm.
+ *     [90/08/21            dbg]
+ *     Fix includes.
+ *     [90/08/08            dbg]
+ *     Created.
+ *     [90/07/25            dbg]
+ * 
+ */
+
+/*
+ * Instruction disassembler.
+ */
+#include "param.h"
+#include "proc.h"
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+/*
+ * Size attributes
+ */
+#define        BYTE    0
+#define        WORD    1
+#define        LONG    2
+#define        QUAD    3
+#define        SNGL    4
+#define        DBLR    5
+#define        EXTR    6
+#define        SDEP    7
+#define        NONE    8
+
+/*
+ * Addressing modes
+ */
+#define        E       1                       /* general effective address */
+#define        Eind    2                       /* indirect address (jump, call) */
+#define        Ew      3                       /* address, word size */
+#define        Eb      4                       /* address, byte size */
+#define        R       5                       /* register, in 'reg' field */
+#define        Rw      6                       /* word register, in 'reg' field */
+#define        Ri      7                       /* register in instruction */
+#define        S       8                       /* segment reg, in 'reg' field */
+#define        Si      9                       /* segment reg, in instruction */
+#define        A       10                      /* accumulator */
+#define        BX      11                      /* (bx) */
+#define        CL      12                      /* cl, for shifts */
+#define        DX      13                      /* dx, for IO */
+#define        SI      14                      /* si */
+#define        DI      15                      /* di */
+#define        CR      16                      /* control register */
+#define        DR      17                      /* debug register */
+#define        TR      18                      /* test register */
+#define        I       19                      /* immediate, unsigned */
+#define        Is      20                      /* immediate, signed */
+#define        Ib      21                      /* byte immediate, unsigned */
+#define        Ibs     22                      /* byte immediate, signed */
+#define        Iw      23                      /* word immediate, unsigned */
+#define        Il      24                      /* long immediate */
+#define        O       25                      /* direct address */
+#define        Db      26                      /* byte displacement from EIP */
+#define        Dl      27                      /* long displacement from EIP */
+#define        o1      28                      /* constant 1 */
+#define        o3      29                      /* constant 3 */
+#define        OS      30                      /* immediate offset/segment */
+#define        ST      31                      /* FP stack top */
+#define        STI     32                      /* FP stack */
+#define        X       33                      /* extended FP op */
+#define        XA      34                      /* for 'fstcw %ax' */
+
+struct inst {
+       char *  i_name;                 /* name */
+       short   i_has_modrm;            /* has regmodrm byte */
+       short   i_size;                 /* operand size */
+       int     i_mode;                 /* addressing modes */
+       char *  i_extra;                /* pointer to extra opcode table */
+};
+
+#define        op1(x)          (x)
+#define        op2(x,y)        ((x)|((y)<<8))
+#define        op3(x,y,z)      ((x)|((y)<<8)|((z)<<16))
+
+struct finst {
+       char *  f_name;                 /* name for memory instruction */
+       int     f_size;                 /* size for memory instruction */
+       int     f_rrmode;               /* mode for rr instruction */
+       char *  f_rrname;               /* name for rr instruction
+                                          (or pointer to table) */
+};
+
+char * db_Grp6[] = {
+       "sldt",
+       "str",
+       "lldt",
+       "ltr",
+       "verr",
+       "verw",
+       "",
+       ""
+};
+
+char * db_Grp7[] = {
+       "sgdt",
+       "sidt",
+       "lgdt",
+       "lidt",
+       "smsw",
+       "",
+       "lmsw",
+       "invlpg"
+};
+
+char * db_Grp8[] = {
+       "",
+       "",
+       "",
+       "",
+       "bt",
+       "bts",
+       "btr",
+       "btc"
+};
+
+struct inst db_inst_0f0x[] = {
+/*00*/ { "",      TRUE,  NONE,  op1(Ew),     (char *)db_Grp6 },
+/*01*/ { "",      TRUE,  NONE,  op1(Ew),     (char *)db_Grp7 },
+/*02*/ { "lar",   TRUE,  LONG,  op2(E,R),    0 },
+/*03*/ { "lsl",   TRUE,  LONG,  op2(E,R),    0 },
+/*04*/ { "",      FALSE, NONE,  0,           0 },
+/*05*/ { "",      FALSE, NONE,  0,           0 },
+/*06*/ { "clts",  FALSE, NONE,  0,           0 },
+/*07*/ { "",      FALSE, NONE,  0,           0 },
+
+/*08*/ { "invd",  FALSE, NONE,  0,           0 },
+/*09*/ { "wbinvd",FALSE, NONE,  0,           0 },
+/*0a*/ { "",      FALSE, NONE,  0,           0 },
+/*0b*/ { "",      FALSE, NONE,  0,           0 },
+/*0c*/ { "",      FALSE, NONE,  0,           0 },
+/*0d*/ { "",      FALSE, NONE,  0,           0 },
+/*0e*/ { "",      FALSE, NONE,  0,           0 },
+/*0f*/ { "",      FALSE, NONE,  0,           0 },
+};
+
+struct inst    db_inst_0f2x[] = {
+/*20*/ { "mov",   TRUE,  LONG,  op2(CR,E),   0 }, /* use E for reg */
+/*21*/ { "mov",   TRUE,  LONG,  op2(DR,E),   0 }, /* since mod == 11 */
+/*22*/ { "mov",   TRUE,  LONG,  op2(E,CR),   0 },
+/*23*/ { "mov",   TRUE,  LONG,  op2(E,DR),   0 },
+/*24*/ { "mov",   TRUE,  LONG,  op2(TR,E),   0 },
+/*25*/ { "",      FALSE, NONE,  0,           0 },
+/*26*/ { "mov",   TRUE,  LONG,  op2(E,TR),   0 },
+/*27*/ { "",      FALSE, NONE,  0,           0 },
+
+/*28*/ { "",      FALSE, NONE,  0,           0 },
+/*29*/ { "",      FALSE, NONE,  0,           0 },
+/*2a*/ { "",      FALSE, NONE,  0,           0 },
+/*2b*/ { "",      FALSE, NONE,  0,           0 },
+/*2c*/ { "",      FALSE, NONE,  0,           0 },
+/*2d*/ { "",      FALSE, NONE,  0,           0 },
+/*2e*/ { "",      FALSE, NONE,  0,           0 },
+/*2f*/ { "",      FALSE, NONE,  0,           0 },
+};
+
+struct inst    db_inst_0f8x[] = {
+/*80*/ { "jo",    FALSE, NONE,  op1(Dl),     0 },
+/*81*/ { "jno",   FALSE, NONE,  op1(Dl),     0 },
+/*82*/ { "jb",    FALSE, NONE,  op1(Dl),     0 },
+/*83*/ { "jnb",   FALSE, NONE,  op1(Dl),     0 },
+/*84*/ { "jz",    FALSE, NONE,  op1(Dl),     0 },
+/*85*/ { "jnz",   FALSE, NONE,  op1(Dl),     0 },
+/*86*/ { "jbe",   FALSE, NONE,  op1(Dl),     0 },
+/*87*/ { "jnbe",  FALSE, NONE,  op1(Dl),     0 },
+
+/*88*/ { "js",    FALSE, NONE,  op1(Dl),     0 },
+/*89*/ { "jns",   FALSE, NONE,  op1(Dl),     0 },
+/*8a*/ { "jp",    FALSE, NONE,  op1(Dl),     0 },
+/*8b*/ { "jnp",   FALSE, NONE,  op1(Dl),     0 },
+/*8c*/ { "jl",    FALSE, NONE,  op1(Dl),     0 },
+/*8d*/ { "jnl",   FALSE, NONE,  op1(Dl),     0 },
+/*8e*/ { "jle",   FALSE, NONE,  op1(Dl),     0 },
+/*8f*/ { "jnle",  FALSE, NONE,  op1(Dl),     0 },
+};
+
+struct inst    db_inst_0f9x[] = {
+/*90*/ { "seto",  TRUE,  NONE,  op1(Eb),     0 },
+/*91*/ { "setno", TRUE,  NONE,  op1(Eb),     0 },
+/*92*/ { "setb",  TRUE,  NONE,  op1(Eb),     0 },
+/*93*/ { "setnb", TRUE,  NONE,  op1(Eb),     0 },
+/*94*/ { "setz",  TRUE,  NONE,  op1(Eb),     0 },
+/*95*/ { "setnz", TRUE,  NONE,  op1(Eb),     0 },
+/*96*/ { "setbe", TRUE,  NONE,  op1(Eb),     0 },
+/*97*/ { "setnbe",TRUE,  NONE,  op1(Eb),     0 },
+
+/*98*/ { "sets",  TRUE,  NONE,  op1(Eb),     0 },
+/*99*/ { "setns", TRUE,  NONE,  op1(Eb),     0 },
+/*9a*/ { "setp",  TRUE,  NONE,  op1(Eb),     0 },
+/*9b*/ { "setnp", TRUE,  NONE,  op1(Eb),     0 },
+/*9c*/ { "setl",  TRUE,  NONE,  op1(Eb),     0 },
+/*9d*/ { "setnl", TRUE,  NONE,  op1(Eb),     0 },
+/*9e*/ { "setle", TRUE,  NONE,  op1(Eb),     0 },
+/*9f*/ { "setnle",TRUE,  NONE,  op1(Eb),     0 },
+};
+
+struct inst    db_inst_0fax[] = {
+/*a0*/ { "push",  FALSE, NONE,  op1(Si),     0 },
+/*a1*/ { "pop",   FALSE, NONE,  op1(Si),     0 },
+/*a2*/ { "",      FALSE, NONE,  0,           0 },
+/*a3*/ { "bt",    TRUE,  LONG,  op2(E,R),    0 },
+/*a4*/ { "shld",  TRUE,  LONG,  op3(Ib,E,R), 0 },
+/*a5*/ { "shld",  TRUE,  LONG,  op3(CL,E,R), 0 },
+/*a6*/ { "",      FALSE, NONE,  0,           0 },
+/*a7*/ { "",      FALSE, NONE,  0,           0 },
+
+/*a8*/ { "push",  FALSE, NONE,  op1(Si),     0 },
+/*a9*/ { "pop",   FALSE, NONE,  op1(Si),     0 },
+/*aa*/ { "",      FALSE, NONE,  0,           0 },
+/*ab*/ { "bts",   TRUE,  LONG,  op2(E,R),    0 },
+/*ac*/ { "shrd",  TRUE,  LONG,  op3(Ib,E,R), 0 },
+/*ad*/ { "shrd",  TRUE,  LONG,  op3(CL,E,R), 0 },
+/*a6*/ { "",      FALSE, NONE,  0,           0 },
+/*a7*/ { "imul",  TRUE,  LONG,  op2(E,R),    0 },
+};
+
+struct inst    db_inst_0fbx[] = {
+/*b0*/ { "",      FALSE, NONE,  0,           0 },
+/*b1*/ { "",      FALSE, NONE,  0,           0 },
+/*b2*/ { "lss",   TRUE,  LONG,  op2(E, R),   0 },
+/*b3*/ { "bts",   TRUE,  LONG,  op2(R, E),   0 },
+/*b4*/ { "lfs",   TRUE,  LONG,  op2(E, R),   0 },
+/*b5*/ { "lgs",   TRUE,  LONG,  op2(E, R),   0 },
+/*b6*/ { "movzb", TRUE,  LONG,  op2(E, R),   0 },
+/*b7*/ { "movzw", TRUE,  LONG,  op2(E, R),   0 },
+
+/*b8*/ { "",      FALSE, NONE,  0,           0 },
+/*b9*/ { "",      FALSE, NONE,  0,           0 },
+/*ba*/ { "",      TRUE,  LONG,  op2(Is, E),  (char *)db_Grp8 },
+/*bb*/ { "btc",   TRUE,  LONG,  op2(R, E),   0 },
+/*bc*/ { "bsf",   TRUE,  LONG,  op2(E, R),   0 },
+/*bd*/ { "bsr",   TRUE,  LONG,  op2(E, R),   0 },
+/*be*/ { "movsb", TRUE,  LONG,  op2(E, R),   0 },
+/*bf*/ { "movsw", TRUE,  LONG,  op2(E, R),   0 },
+};
+
+struct inst    db_inst_0fcx[] = {
+/*c0*/ { "xadd",  TRUE,  BYTE,  op2(R, E),   0 },
+/*c1*/ { "xadd",  TRUE,  LONG,  op2(R, E),   0 },
+/*c2*/ { "",      FALSE, NONE,  0,           0 },
+/*c3*/ { "",      FALSE, NONE,  0,           0 },
+/*c4*/ { "",      FALSE, NONE,  0,           0 },
+/*c5*/ { "",      FALSE, NONE,  0,           0 },
+/*c6*/ { "",      FALSE, NONE,  0,           0 },
+/*c7*/ { "",      FALSE, NONE,  0,           0 },
+/*c8*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*c9*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*ca*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*cb*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*cc*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*cd*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*ce*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+/*cf*/ { "bswap", FALSE, LONG,  op1(Ri),     0 },
+};
+
+struct inst    db_inst_0fdx[] = {
+/*c0*/ { "cmpxchg",TRUE, BYTE,  op2(R, E),   0 },
+/*c1*/ { "cmpxchg",TRUE, LONG,  op2(R, E),   0 },
+/*c2*/ { "",      FALSE, NONE,  0,           0 },
+/*c3*/ { "",      FALSE, NONE,  0,           0 },
+/*c4*/ { "",      FALSE, NONE,  0,           0 },
+/*c5*/ { "",      FALSE, NONE,  0,           0 },
+/*c6*/ { "",      FALSE, NONE,  0,           0 },
+/*c7*/ { "",      FALSE, NONE,  0,           0 },
+/*c8*/ { "",      FALSE, NONE,  0,           0 },
+/*c9*/ { "",      FALSE, NONE,  0,           0 },
+/*ca*/ { "",      FALSE, NONE,  0,           0 },
+/*cb*/ { "",      FALSE, NONE,  0,           0 },
+/*cc*/ { "",      FALSE, NONE,  0,           0 },
+/*cd*/ { "",      FALSE, NONE,  0,           0 },
+/*ce*/ { "",      FALSE, NONE,  0,           0 },
+/*cf*/ { "",      FALSE, NONE,  0,           0 },
+};
+
+struct inst *db_inst_0f[] = {
+       db_inst_0f0x,
+       0,
+       db_inst_0f2x,
+       0,
+       0,
+       0,
+       0,
+       0,
+       db_inst_0f8x,
+       db_inst_0f9x,
+       db_inst_0fax,
+       db_inst_0fbx,
+       db_inst_0fcx,
+       db_inst_0fdx,
+       0,
+       0
+};
+
+char * db_Esc92[] = {
+       "fnop", "",     "",     "",     "",     "",     "",     ""
+};
+char * db_Esc93[] = {
+       "",     "",     "",     "",     "",     "",     "",     ""
+};
+char * db_Esc94[] = {
+       "fchs", "fabs", "",     "",     "ftst", "fxam", "",     ""
+};
+char * db_Esc95[] = {
+       "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz",""
+};
+char * db_Esc96[] = {
+       "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp",
+       "fincstp"
+};
+char * db_Esc97[] = {
+       "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"
+};
+
+char * db_Esca4[] = {
+       "",     "fucompp","",   "",     "",     "",     "",     ""
+};
+
+char * db_Escb4[] = {
+       "",     "",     "fnclex","fninit","",   "",     "",     ""
+};
+
+char * db_Esce3[] = {
+       "",     "fcompp","",    "",     "",     "",     "",     ""
+};
+
+char * db_Escf4[] = {
+       "fnstsw","",    "",     "",     "",     "",     "",     ""
+};
+
+struct finst db_Esc8[] = {
+/*0*/  { "fadd",   SNGL,  op2(STI,ST), 0 },
+/*1*/  { "fmul",   SNGL,  op2(STI,ST), 0 },
+/*2*/  { "fcom",   SNGL,  op2(STI,ST), 0 },
+/*3*/  { "fcomp",  SNGL,  op2(STI,ST), 0 },
+/*4*/  { "fsub",   SNGL,  op2(STI,ST), 0 },
+/*5*/  { "fsubr",  SNGL,  op2(STI,ST), 0 },
+/*6*/  { "fdiv",   SNGL,  op2(STI,ST), 0 },
+/*7*/  { "fdivr",  SNGL,  op2(STI,ST), 0 },
+};
+
+struct finst db_Esc9[] = {
+/*0*/  { "fld",    SNGL,  op1(STI),    0 },
+/*1*/  { "",       NONE,  op1(STI),    "fxch" },
+/*2*/  { "fst",    SNGL,  op1(X),      (char *)db_Esc92 },
+/*3*/  { "fstp",   SNGL,  op1(X),      (char *)db_Esc93 },
+/*4*/  { "fldenv", NONE,  op1(X),      (char *)db_Esc94 },
+/*5*/  { "fldcw",  NONE,  op1(X),      (char *)db_Esc95 },
+/*6*/  { "fnstenv",NONE,  op1(X),      (char *)db_Esc96 },
+/*7*/  { "fnstcw", NONE,  op1(X),      (char *)db_Esc97 },
+};
+
+struct finst db_Esca[] = {
+/*0*/  { "fiadd",  WORD,  0,           0 },
+/*1*/  { "fimul",  WORD,  0,           0 },
+/*2*/  { "ficom",  WORD,  0,           0 },
+/*3*/  { "ficomp", WORD,  0,           0 },
+/*4*/  { "fisub",  WORD,  op1(X),      (char *)db_Esca4 },
+/*5*/  { "fisubr", WORD,  0,           0 },
+/*6*/  { "fidiv",  WORD,  0,           0 },
+/*7*/  { "fidivr", WORD,  0,           0 }
+};
+
+struct finst db_Escb[] = {
+/*0*/  { "fild",   WORD,  0,           0 },
+/*1*/  { "",       NONE,  0,           0 },
+/*2*/  { "fist",   WORD,  0,           0 },
+/*3*/  { "fistp",  WORD,  0,           0 },
+/*4*/  { "",       WORD,  op1(X),      (char *)db_Escb4 },
+/*5*/  { "fld",    EXTR,  0,           0 },
+/*6*/  { "",       WORD,  0,           0 },
+/*7*/  { "fstp",   EXTR,  0,           0 },
+};
+
+struct finst db_Escc[] = {
+/*0*/  { "fadd",   DBLR,  op2(ST,STI), 0 },
+/*1*/  { "fmul",   DBLR,  op2(ST,STI), 0 },
+/*2*/  { "fcom",   DBLR,  op2(ST,STI), 0 },
+/*3*/  { "fcomp",  DBLR,  op2(ST,STI), 0 },
+/*4*/  { "fsub",   DBLR,  op2(ST,STI), "fsubr" },
+/*5*/  { "fsubr",  DBLR,  op2(ST,STI), "fsub" },
+/*6*/  { "fdiv",   DBLR,  op2(ST,STI), "fdivr" },
+/*7*/  { "fdivr",  DBLR,  op2(ST,STI), "fdiv" },
+};
+
+struct finst db_Escd[] = {
+/*0*/  { "fld",    DBLR,  op1(STI),    "ffree" },
+/*1*/  { "",       NONE,  0,           0 },
+/*2*/  { "fst",    DBLR,  op1(STI),    0 },
+/*3*/  { "fstp",   DBLR,  op1(STI),    0 },
+/*4*/  { "frstor", NONE,  op1(STI),    "fucom" },
+/*5*/  { "",       NONE,  op1(STI),    "fucomp" },
+/*6*/  { "fnsave", NONE,  0,           0 },
+/*7*/  { "fnstsw", NONE,  0,           0 },
+};
+
+struct finst db_Esce[] = {
+/*0*/  { "fiadd",  LONG,  op2(ST,STI), "faddp" },
+/*1*/  { "fimul",  LONG,  op2(ST,STI), "fmulp" },
+/*2*/  { "ficom",  LONG,  0,           0 },
+/*3*/  { "ficomp", LONG,  op1(X),      (char *)db_Esce3 },
+/*4*/  { "fisub",  LONG,  op2(ST,STI), "fsubrp" },
+/*5*/  { "fisubr", LONG,  op2(ST,STI), "fsubp" },
+/*6*/  { "fidiv",  LONG,  op2(ST,STI), "fdivrp" },
+/*7*/  { "fidivr", LONG,  op2(ST,STI), "fdivp" },
+};
+
+struct finst db_Escf[] = {
+/*0*/  { "fild",   LONG,  0,           0 },
+/*1*/  { "",       LONG,  0,           0 },
+/*2*/  { "fist",   LONG,  0,           0 },
+/*3*/  { "fistp",  LONG,  0,           0 },
+/*4*/  { "fbld",   NONE,  op1(XA),     (char *)db_Escf4 },
+/*5*/  { "fld",    QUAD,  0,           0 },
+/*6*/  { "fbstp",  NONE,  0,           0 },
+/*7*/  { "fstp",   QUAD,  0,           0 },
+};
+
+struct finst *db_Esc_inst[] = {
+       db_Esc8, db_Esc9, db_Esca, db_Escb,
+       db_Escc, db_Escd, db_Esce, db_Escf
+};
+
+char * db_Grp1[] = {
+       "add",
+       "or",
+       "adc",
+       "sbb",
+       "and",
+       "sub",
+       "xor",
+       "cmp"
+};
+
+char * db_Grp2[] = {
+       "rol",
+       "ror",
+       "rcl",
+       "rcr",
+       "shl",
+       "shr",
+       "shl",
+       "sar"
+};
+
+struct inst db_Grp3[] = {
+       { "test",  TRUE, NONE, op2(I,E), 0 },
+       { "test",  TRUE, NONE, op2(I,E), 0 },
+       { "not",   TRUE, NONE, op1(E),   0 },
+       { "neg",   TRUE, NONE, op1(E),   0 },
+       { "mul",   TRUE, NONE, op2(E,A), 0 },
+       { "imul",  TRUE, NONE, op2(E,A), 0 },
+       { "div",   TRUE, NONE, op2(E,A), 0 },
+       { "idiv",  TRUE, NONE, op2(E,A), 0 },
+};
+
+struct inst    db_Grp4[] = {
+       { "inc",   TRUE, BYTE, op1(E),   0 },
+       { "dec",   TRUE, BYTE, op1(E),   0 },
+       { "",      TRUE, NONE, 0,        0 },
+       { "",      TRUE, NONE, 0,        0 },
+       { "",      TRUE, NONE, 0,        0 },
+       { "",      TRUE, NONE, 0,        0 },
+       { "",      TRUE, NONE, 0,        0 },
+       { "",      TRUE, NONE, 0,        0 }
+};
+
+struct inst    db_Grp5[] = {
+       { "inc",   TRUE, LONG, op1(E),   0 },
+       { "dec",   TRUE, LONG, op1(E),   0 },
+       { "call",  TRUE, NONE, op1(Eind),0 },
+       { "lcall", TRUE, NONE, op1(Eind),0 },
+       { "jmp",   TRUE, NONE, op1(Eind),0 },
+       { "ljmp",  TRUE, NONE, op1(Eind),0 },
+       { "push",  TRUE, LONG, op1(E),   0 },
+       { "",      TRUE, NONE, 0,        0 }
+};
+
+struct inst db_inst_table[256] = {
+/*00*/ { "add",   TRUE,  BYTE,  op2(R, E),  0 },
+/*01*/ { "add",   TRUE,  LONG,  op2(R, E),  0 },
+/*02*/ { "add",   TRUE,  BYTE,  op2(E, R),  0 },
+/*03*/ { "add",   TRUE,  LONG,  op2(E, R),  0 },
+/*04*/ { "add",   FALSE, BYTE,  op2(Is, A), 0 },
+/*05*/ { "add",   FALSE, LONG,  op2(Is, A), 0 },
+/*06*/ { "push",  FALSE, NONE,  op1(Si),    0 },
+/*07*/ { "pop",   FALSE, NONE,  op1(Si),    0 },
+
+/*08*/ { "or",    TRUE,  BYTE,  op2(R, E),  0 },
+/*09*/ { "or",    TRUE,  LONG,  op2(R, E),  0 },
+/*0a*/ { "or",    TRUE,  BYTE,  op2(E, R),  0 },
+/*0b*/ { "or",    TRUE,  LONG,  op2(E, R),  0 },
+/*0c*/ { "or",    FALSE, BYTE,  op2(I, A),  0 },
+/*0d*/ { "or",    FALSE, LONG,  op2(I, A),  0 },
+/*0e*/ { "push",  FALSE, NONE,  op1(Si),    0 },
+/*0f*/ { "",      FALSE, NONE,  0,          0 },
+
+/*10*/ { "adc",   TRUE,  BYTE,  op2(R, E),  0 },
+/*11*/ { "adc",   TRUE,  LONG,  op2(R, E),  0 },
+/*12*/ { "adc",   TRUE,  BYTE,  op2(E, R),  0 },
+/*13*/ { "adc",   TRUE,  LONG,  op2(E, R),  0 },
+/*14*/ { "adc",   FALSE, BYTE,  op2(Is, A), 0 },
+/*15*/ { "adc",   FALSE, LONG,  op2(Is, A), 0 },
+/*16*/ { "push",  FALSE, NONE,  op1(Si),    0 },
+/*17*/ { "pop",   FALSE, NONE,  op1(Si),    0 },
+
+/*18*/ { "sbb",   TRUE,  BYTE,  op2(R, E),  0 },
+/*19*/ { "sbb",   TRUE,  LONG,  op2(R, E),  0 },
+/*1a*/ { "sbb",   TRUE,  BYTE,  op2(E, R),  0 },
+/*1b*/ { "sbb",   TRUE,  LONG,  op2(E, R),  0 },
+/*1c*/ { "sbb",   FALSE, BYTE,  op2(Is, A), 0 },
+/*1d*/ { "sbb",   FALSE, LONG,  op2(Is, A), 0 },
+/*1e*/ { "push",  FALSE, NONE,  op1(Si),    0 },
+/*1f*/ { "pop",   FALSE, NONE,  op1(Si),    0 },
+
+/*20*/ { "and",   TRUE,  BYTE,  op2(R, E),  0 },
+/*21*/ { "and",   TRUE,  LONG,  op2(R, E),  0 },
+/*22*/ { "and",   TRUE,  BYTE,  op2(E, R),  0 },
+/*23*/ { "and",   TRUE,  LONG,  op2(E, R),  0 },
+/*24*/ { "and",   FALSE, BYTE,  op2(I, A),  0 },
+/*25*/ { "and",   FALSE, LONG,  op2(I, A),  0 },
+/*26*/ { "",      FALSE, NONE,  0,          0 },
+/*27*/ { "aaa",   FALSE, NONE,  0,          0 },
+
+/*28*/ { "sub",   TRUE,  BYTE,  op2(R, E),  0 },
+/*29*/ { "sub",   TRUE,  LONG,  op2(R, E),  0 },
+/*2a*/ { "sub",   TRUE,  BYTE,  op2(E, R),  0 },
+/*2b*/ { "sub",   TRUE,  LONG,  op2(E, R),  0 },
+/*2c*/ { "sub",   FALSE, BYTE,  op2(Is, A), 0 },
+/*2d*/ { "sub",   FALSE, LONG,  op2(Is, A), 0 },
+/*2e*/ { "",      FALSE, NONE,  0,          0 },
+/*2f*/ { "das",   FALSE, NONE,  0,          0 },
+
+/*30*/ { "xor",   TRUE,  BYTE,  op2(R, E),  0 },
+/*31*/ { "xor",   TRUE,  LONG,  op2(R, E),  0 },
+/*32*/ { "xor",   TRUE,  BYTE,  op2(E, R),  0 },
+/*33*/ { "xor",   TRUE,  LONG,  op2(E, R),  0 },
+/*34*/ { "xor",   FALSE, BYTE,  op2(I, A),  0 },
+/*35*/ { "xor",   FALSE, LONG,  op2(I, A),  0 },
+/*36*/ { "",      FALSE, NONE,  0,          0 },
+/*37*/ { "daa",   FALSE, NONE,  0,          0 },
+
+/*38*/ { "cmp",   TRUE,  BYTE,  op2(R, E),  0 },
+/*39*/ { "cmp",   TRUE,  LONG,  op2(R, E),  0 },
+/*3a*/ { "cmp",   TRUE,  BYTE,  op2(E, R),  0 },
+/*3b*/ { "cmp",   TRUE,  LONG,  op2(E, R),  0 },
+/*3c*/ { "cmp",   FALSE, BYTE,  op2(Is, A), 0 },
+/*3d*/ { "cmp",   FALSE, LONG,  op2(Is, A), 0 },
+/*3e*/ { "",      FALSE, NONE,  0,          0 },
+/*3f*/ { "aas",   FALSE, NONE,  0,          0 },
+
+/*40*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*41*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*42*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*43*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*44*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*45*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*46*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+/*47*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
+
+/*48*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*49*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4a*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4b*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4c*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4d*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4e*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*4f*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+
+/*50*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*51*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*52*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*53*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*54*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*55*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*56*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+/*57*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
+
+/*58*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*59*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5a*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5b*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5c*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5d*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5e*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+/*5f*/ { "pop",   FALSE, LONG,  op1(Ri),    0 },
+
+/*60*/ { "pusha", FALSE, LONG,  0,          0 },
+/*61*/ { "popa",  FALSE, LONG,  0,          0 },
+/*62*/  { "bound", TRUE,  LONG,  op2(E, R),  0 },
+/*63*/ { "arpl",  TRUE,  NONE,  op2(Ew,Rw), 0 },
+
+/*64*/ { "",      FALSE, NONE,  0,          0 },
+/*65*/ { "",      FALSE, NONE,  0,          0 },
+/*66*/ { "",      FALSE, NONE,  0,          0 },
+/*67*/ { "",      FALSE, NONE,  0,          0 },
+
+/*68*/ { "push",  FALSE, LONG,  op1(I),     0 },
+/*69*/  { "imul",  TRUE,  LONG,  op3(I,E,R), 0 },
+/*6a*/ { "push",  FALSE, LONG,  op1(Ib),    0 },
+/*6b*/  { "imul",  TRUE,  LONG,  op3(Ibs,E,R),0 },
+/*6c*/ { "ins",   FALSE, BYTE,  op2(DX, DI), 0 },
+/*6d*/ { "ins",   FALSE, LONG,  op2(DX, DI), 0 },
+/*6e*/ { "outs",  FALSE, BYTE,  op2(SI, DX), 0 },
+/*6f*/ { "outs",  FALSE, LONG,  op2(SI, DX), 0 },
+
+/*70*/ { "jo",    FALSE, NONE,  op1(Db),     0 },
+/*71*/ { "jno",   FALSE, NONE,  op1(Db),     0 },
+/*72*/ { "jb",    FALSE, NONE,  op1(Db),     0 },
+/*73*/ { "jnb",   FALSE, NONE,  op1(Db),     0 },
+/*74*/ { "jz",    FALSE, NONE,  op1(Db),     0 },
+/*75*/ { "jnz",   FALSE, NONE,  op1(Db),     0 },
+/*76*/ { "jbe",   FALSE, NONE,  op1(Db),     0 },
+/*77*/ { "jnbe",  FALSE, NONE,  op1(Db),     0 },
+
+/*78*/ { "js",    FALSE, NONE,  op1(Db),     0 },
+/*79*/ { "jns",   FALSE, NONE,  op1(Db),     0 },
+/*7a*/ { "jp",    FALSE, NONE,  op1(Db),     0 },
+/*7b*/ { "jnp",   FALSE, NONE,  op1(Db),     0 },
+/*7c*/ { "jl",    FALSE, NONE,  op1(Db),     0 },
+/*7d*/ { "jnl",   FALSE, NONE,  op1(Db),     0 },
+/*7e*/ { "jle",   FALSE, NONE,  op1(Db),     0 },
+/*7f*/ { "jnle",  FALSE, NONE,  op1(Db),     0 },
+
+/*80*/  { "",     TRUE,  BYTE,  op2(I, E),   (char *)db_Grp1 },
+/*81*/  { "",     TRUE,  LONG,  op2(I, E),   (char *)db_Grp1 },
+/*82*/  { "",     TRUE,  BYTE,  op2(Is,E),   (char *)db_Grp1 },
+/*83*/  { "",     TRUE,  LONG,  op2(Ibs,E),  (char *)db_Grp1 },
+/*84*/ { "test",  TRUE,  BYTE,  op2(R, E),   0 },
+/*85*/ { "test",  TRUE,  LONG,  op2(R, E),   0 },
+/*86*/ { "xchg",  TRUE,  BYTE,  op2(R, E),   0 },
+/*87*/ { "xchg",  TRUE,  LONG,  op2(R, E),   0 },
+
+/*88*/ { "mov",   TRUE,  BYTE,  op2(R, E),   0 },
+/*89*/ { "mov",   TRUE,  LONG,  op2(R, E),   0 },
+/*8a*/ { "mov",   TRUE,  BYTE,  op2(E, R),   0 },
+/*8b*/ { "mov",   TRUE,  LONG,  op2(E, R),   0 },
+/*8c*/  { "mov",   TRUE,  NONE,  op2(S, Ew),  0 },
+/*8d*/ { "lea",   TRUE,  LONG,  op2(E, R),   0 },
+/*8e*/ { "mov",   TRUE,  NONE,  op2(Ew, S),  0 },
+/*8f*/ { "pop",   TRUE,  LONG,  op1(E),      0 },
+
+/*90*/ { "nop",   FALSE, NONE,  0,           0 },
+/*91*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*92*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*93*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*94*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*95*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*96*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+/*97*/ { "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
+
+/*98*/ { "cbw",   FALSE, SDEP,  0,           "cwde" }, /* cbw/cwde */
+/*99*/ { "cwd",   FALSE, SDEP,  0,           "cdq"  }, /* cwd/cdq */
+/*9a*/ { "lcall", FALSE, NONE,  op1(OS),     0 },
+/*9b*/ { "wait",  FALSE, NONE,  0,           0 },
+/*9c*/ { "pushf", FALSE, LONG,  0,           0 },
+/*9d*/ { "popf",  FALSE, LONG,  0,           0 },
+/*9e*/ { "sahf",  FALSE, NONE,  0,           0 },
+/*9f*/ { "lahf",  FALSE, NONE,  0,           0 },
+
+/*a0*/ { "mov",   FALSE, BYTE,  op2(O, A),   0 },
+/*a1*/ { "mov",   FALSE, LONG,  op2(O, A),   0 },
+/*a2*/ { "mov",   FALSE, BYTE,  op2(A, O),   0 },
+/*a3*/ { "mov",   FALSE, LONG,  op2(A, O),   0 },
+/*a4*/ { "movs",  FALSE, BYTE,  op2(SI,DI),  0 },
+/*a5*/ { "movs",  FALSE, LONG,  op2(SI,DI),  0 },
+/*a6*/ { "cmps",  FALSE, BYTE,  op2(SI,DI),  0 },
+/*a7*/ { "cmps",  FALSE, LONG,  op2(SI,DI),  0 },
+
+/*a8*/ { "test",  FALSE, BYTE,  op2(I, A),   0 },
+/*a9*/ { "test",  FALSE, LONG,  op2(I, A),   0 },
+/*aa*/ { "stos",  FALSE, BYTE,  op1(DI),     0 },
+/*ab*/ { "stos",  FALSE, LONG,  op1(DI),     0 },
+/*ac*/ { "ldos",  FALSE, BYTE,  op1(SI),     0 },
+/*ad*/ { "ldos",  FALSE, LONG,  op1(SI),     0 },
+/*ae*/ { "scas",  FALSE, BYTE,  op1(SI),     0 },
+/*af*/ { "scas",  FALSE, LONG,  op1(SI),     0 },
+
+/*b0*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b1*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b2*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b3*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b4*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b5*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b6*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+/*b7*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
+
+/*b8*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*b9*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*ba*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*bb*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*bc*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*bd*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*be*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*bf*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+
+/*c0*/ { "",      TRUE,  BYTE,  op2(Ib, E),  (char *)db_Grp2 },
+/*c1*/ { "",      TRUE,  LONG,  op2(Ib, E),  (char *)db_Grp2 },
+/*c2*/ { "ret",   FALSE, NONE,  op1(Iw),     0 },
+/*c3*/ { "ret",   FALSE, NONE,  0,           0 },
+/*c4*/ { "les",   TRUE,  LONG,  op2(E, R),   0 },
+/*c5*/ { "lds",   TRUE,  LONG,  op2(E, R),   0 },
+/*c6*/ { "mov",   TRUE,  BYTE,  op2(I, E),   0 },
+/*c7*/ { "mov",   TRUE,  LONG,  op2(I, E),   0 },
+
+/*c8*/ { "enter", FALSE, NONE,  op2(Ib, Iw), 0 },
+/*c9*/ { "leave", FALSE, NONE,  0,           0 },
+/*ca*/ { "lret",  FALSE, NONE,  op1(Iw),     0 },
+/*cb*/ { "lret",  FALSE, NONE,  0,           0 },
+/*cc*/ { "int",   FALSE, NONE,  op1(o3),     0 },
+/*cd*/ { "int",   FALSE, NONE,  op1(Ib),     0 },
+/*ce*/ { "into",  FALSE, NONE,  0,           0 },
+/*cf*/ { "iret",  FALSE, NONE,  0,           0 },
+
+/*d0*/ { "",      TRUE,  BYTE,  op2(o1, E),  (char *)db_Grp2 },
+/*d1*/ { "",      TRUE,  LONG,  op2(o1, E),  (char *)db_Grp2 },
+/*d2*/ { "",      TRUE,  BYTE,  op2(CL, E),  (char *)db_Grp2 },
+/*d3*/ { "",      TRUE,  LONG,  op2(CL, E),  (char *)db_Grp2 },
+/*d4*/ { "aam",   TRUE,  NONE,  0,           0 },
+/*d5*/ { "aad",   TRUE,  NONE,  0,           0 },
+/*d6*/ { "",      FALSE, NONE,  0,           0 },
+/*d7*/ { "xlat",  FALSE, BYTE,  op1(BX),     0 },
+
+/*d8*/  { "",      TRUE,  NONE,  0,          (char *)db_Esc8 },
+/*d9*/  { "",      TRUE,  NONE,  0,          (char *)db_Esc9 },
+/*da*/  { "",      TRUE,  NONE,  0,          (char *)db_Esca },
+/*db*/  { "",      TRUE,  NONE,  0,          (char *)db_Escb },
+/*dc*/  { "",      TRUE,  NONE,  0,          (char *)db_Escc },
+/*dd*/  { "",      TRUE,  NONE,  0,          (char *)db_Escd },
+/*de*/  { "",      TRUE,  NONE,  0,          (char *)db_Esce },
+/*df*/  { "",      TRUE,  NONE,  0,          (char *)db_Escf },
+
+/*e0*/ { "loopne",FALSE, NONE,  op1(Db),     0 },
+/*e1*/ { "loope", FALSE, NONE,  op1(Db),     0 },
+/*e2*/ { "loop",  FALSE, NONE,  op1(Db),     0 },
+/*e3*/ { "jcxz",  FALSE, SDEP,  op1(Db),     "jecxz" },
+/*e4*/ { "in",    FALSE, BYTE,  op2(Ib, A),  0 },
+/*e5*/ { "in",    FALSE, LONG,  op2(Ib, A) , 0 },
+/*e6*/ { "out",   FALSE, BYTE,  op2(A, Ib),  0 },
+/*e7*/ { "out",   FALSE, LONG,  op2(A, Ib) , 0 },
+
+/*e8*/ { "call",  FALSE, NONE,  op1(Dl),     0 },
+/*e9*/ { "jmp",   FALSE, NONE,  op1(Dl),     0 },
+/*ea*/ { "ljmp",  FALSE, NONE,  op1(OS),     0 },
+/*eb*/ { "jmp",   FALSE, NONE,  op1(Db),     0 },
+/*ec*/ { "in",    FALSE, BYTE,  op2(DX, A),  0 },
+/*ed*/ { "in",    FALSE, LONG,  op2(DX, A) , 0 },
+/*ee*/ { "out",   FALSE, BYTE,  op2(A, DX),  0 },
+/*ef*/ { "out",   FALSE, LONG,  op2(A, DX) , 0 },
+
+/*f0*/ { "",      FALSE, NONE,  0,          0 },
+/*f1*/ { "",      FALSE, NONE,  0,          0 },
+/*f2*/ { "",      FALSE, NONE,  0,          0 },
+/*f3*/ { "",      FALSE, NONE,  0,          0 },
+/*f4*/ { "hlt",   FALSE, NONE,  0,          0 },
+/*f5*/ { "cmc",   FALSE, NONE,  0,          0 },
+/*f6*/ { "",      TRUE,  BYTE,  0,          (char *)db_Grp3 },
+/*f7*/ { "",      TRUE,  LONG,  0,          (char *)db_Grp3 },
+
+/*f8*/ { "clc",   FALSE, NONE,  0,          0 },
+/*f9*/ { "stc",   FALSE, NONE,  0,          0 },
+/*fa*/ { "cli",   FALSE, NONE,  0,          0 },
+/*fb*/ { "sti",   FALSE, NONE,  0,          0 },
+/*fc*/ { "cld",   FALSE, NONE,  0,          0 },
+/*fd*/ { "std",   FALSE, NONE,  0,          0 },
+/*fe*/ { "",      TRUE,  NONE,  0,          (char *)db_Grp4 },
+/*ff*/ { "",      TRUE,  NONE,  0,          (char *)db_Grp5 },
+};
+
+struct inst    db_bad_inst =
+       { "???",   FALSE, NONE,  0,           0 }
+;
+
+#define        f_mod(byte)     ((byte)>>6)
+#define        f_reg(byte)     (((byte)>>3)&0x7)
+#define        f_rm(byte)      ((byte)&0x7)
+
+#define        sib_ss(byte)    ((byte)>>6)
+#define        sib_index(byte) (((byte)>>3)&0x7)
+#define        sib_base(byte)  ((byte)&0x7)
+
+struct i_addr {
+       int             is_reg; /* if reg, reg number is in 'disp' */
+       int             disp;
+       char *          base;
+       char *          index;
+       int             ss;
+};
+
+char * db_index_reg_16[8] = {
+       "%bx,%si",
+       "%bx,%di",
+       "%bp,%si",
+       "%bp,%di",
+       "%si",
+       "%di",
+       "%bp",
+       "%bx"
+};
+
+char * db_reg[3][8] = {
+       "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh",
+       "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
+       "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
+};
+
+char * db_seg_reg[8] = {
+       "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", ""
+};
+
+/*
+ * lengths for size attributes
+ */
+int db_lengths[] = {
+       1,      /* BYTE */
+       2,      /* WORD */
+       4,      /* LONG */
+       8,      /* QUAD */
+       4,      /* SNGL */
+       8,      /* DBLR */
+       10,     /* EXTR */
+};
+
+#define        get_value_inc(result, loc, size, is_signed) \
+       result = db_get_value((loc), (size), (is_signed)); \
+       (loc) += (size);
+
+/*
+ * Read address at location and return updated location.
+ */
+db_addr_t
+db_read_address(loc, short_addr, regmodrm, addrp)
+       db_addr_t       loc;
+       int             short_addr;
+       int             regmodrm;
+       struct i_addr   *addrp;         /* out */
+{
+       int             mod, rm, sib, index, ss, disp;
+
+       mod = f_mod(regmodrm);
+       rm  = f_rm(regmodrm);
+
+       if (mod == 3) {
+           addrp->is_reg = TRUE;
+           addrp->disp = rm;
+           return (loc);
+       }
+       addrp->is_reg = FALSE;
+       addrp->index = 0;
+
+       if (short_addr) {
+           addrp->index = 0;
+           addrp->ss = 0;
+           switch (mod) {
+               case 0:
+                   if (rm == 6) {
+                       get_value_inc(disp, loc, 2, TRUE);
+                       addrp->disp = disp;
+                       addrp->base = 0;
+                   }
+                   else {
+                       addrp->disp = 0;
+                       addrp->base = db_index_reg_16[rm];
+                   }
+                   break;
+               case 1:
+                   get_value_inc(disp, loc, 1, TRUE);
+                   addrp->disp = disp;
+                   addrp->base = db_index_reg_16[rm];
+                   break;
+               case 2:
+                   get_value_inc(disp, loc, 2, TRUE);
+                   addrp->disp = disp;
+                   addrp->base = db_index_reg_16[rm];
+                   break;
+           }
+       }
+       else {
+           if (mod != 3 && rm == 4) {
+               get_value_inc(sib, loc, 1, FALSE);
+               rm = sib_base(sib);
+               index = sib_index(sib);
+               if (index != 4)
+                   addrp->index = db_reg[LONG][index];
+               addrp->ss = sib_ss(sib);
+           }
+
+           switch (mod) {
+               case 0:
+                   if (rm == 5) {
+                       get_value_inc(addrp->disp, loc, 4, FALSE);
+                       addrp->base = 0;
+                   }
+                   else {
+                       addrp->disp = 0;
+                       addrp->base = db_reg[LONG][rm];
+                   }
+                   break;
+
+               case 1:
+                   get_value_inc(disp, loc, 1, TRUE);
+                   addrp->disp = disp;
+                   addrp->base = db_reg[LONG][rm];
+                   break;
+
+               case 2:
+                   get_value_inc(disp, loc, 4, FALSE);
+                   addrp->disp = disp;
+                   addrp->base = db_reg[LONG][rm];
+                   break;
+           }
+       }
+       return (loc);
+}
+
+void
+db_print_address(seg, size, addrp)
+       char *          seg;
+       int             size;
+       struct i_addr   *addrp;
+{
+       if (addrp->is_reg) {
+           db_printf("%s", db_reg[size][addrp->disp]);
+           return;
+       }
+
+       if (seg) {
+           db_printf("%s:", seg);
+       }
+
+       db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
+       if (addrp->base != 0 || addrp->index != 0) {
+           db_printf("(");
+           if (addrp->base)
+               db_printf("%s", addrp->base);
+           if (addrp->index)
+               db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
+           db_printf(")");
+       }
+}
+
+/*
+ * Disassemble floating-point ("escape") instruction
+ * and return updated location.
+ */
+db_addr_t
+db_disasm_esc(loc, inst, short_addr, size, seg)
+       db_addr_t       loc;
+       int             inst;
+       int             short_addr;
+       int             size;
+       char *          seg;
+{
+       int             regmodrm;
+       struct finst    *fp;
+       int             mod;
+       struct i_addr   address;
+       char *          name;
+
+       get_value_inc(regmodrm, loc, 1, FALSE);
+       fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
+       mod = f_mod(regmodrm);
+       if (mod != 3) {
+           /*
+            * Normal address modes.
+            */
+           loc = db_read_address(loc, short_addr, regmodrm, &address);
+           db_printf(fp->f_name);
+           switch(fp->f_size) {
+               case SNGL:
+                   db_printf("s");
+                   break;
+               case DBLR:
+                   db_printf("l");
+                   break;
+               case EXTR:
+                   db_printf("t");
+                   break;
+               case WORD:
+                   db_printf("s");
+                   break;
+               case LONG:
+                   db_printf("l");
+                   break;
+               case QUAD:
+                   db_printf("q");
+                   break;
+               default:
+                   break;
+           }
+           db_printf("\t");
+           db_print_address(seg, BYTE, &address);
+       }
+       else {
+           /*
+            * 'reg-reg' - special formats
+            */
+           switch (fp->f_rrmode) {
+               case op2(ST,STI):
+                   name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
+                   db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm));
+                   break;
+               case op2(STI,ST):
+                   name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
+                   db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm));
+                   break;
+               case op1(STI):
+                   name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
+                   db_printf("%s\t%%st(%d)",name, f_rm(regmodrm));
+                   break;
+               case op1(X):
+                   db_printf("%s", ((char **)fp->f_rrname)[f_rm(regmodrm)]);
+                   break;
+               case op1(XA):
+                   db_printf("%s\t%%ax",
+                                ((char **)fp->f_rrname)[f_rm(regmodrm)]);
+                   break;
+               default:
+                   db_printf("<bad instruction>");
+                   break;
+           }
+       }
+
+       return (loc);
+}
+
+/*
+ * Disassemble instruction at 'loc'.  'altfmt' specifies an
+ * (optional) alternate format.  Return address of start of
+ * next instruction.
+ */
+db_addr_t
+db_disasm(loc, altfmt)
+       db_addr_t       loc;
+       boolean_t       altfmt;
+{
+       int     inst;
+       int     size;
+       int     short_addr;
+       char *  seg;
+       struct inst *   ip;
+       char *  i_name;
+       int     i_size;
+       int     i_mode;
+       int     regmodrm;
+       boolean_t       first;
+       int     displ;
+       int     prefix;
+       int     imm;
+       int     imm2;
+       int     len;
+       struct i_addr   address;
+
+       get_value_inc(inst, loc, 1, FALSE);
+       short_addr = FALSE;
+       size = LONG;
+       seg = 0;
+
+       /*
+        * Get prefixes
+        */
+       prefix = TRUE;
+       do {
+           switch (inst) {
+               case 0x66:              /* data16 */
+                   size = WORD;
+                   break;
+               case 0x67:
+                   short_addr = TRUE;
+                   break;
+               case 0x26:
+                   seg = "%es";
+                   break;
+               case 0x36:
+                   seg = "%ss";
+                   break;
+               case 0x2e:
+                   seg = "%cs";
+                   break;
+               case 0x3e:
+                   seg = "%ds";
+                   break;
+               case 0x64:
+                   seg = "%fs";
+                   break;
+               case 0x65:
+                   seg = "%gs";
+                   break;
+               case 0xf0:
+                   db_printf("lock ");
+                   break;
+               case 0xf2:
+                   db_printf("repne ");
+                   break;
+               case 0xf3:
+                   db_printf("repe "); /* XXX repe VS rep */
+                   break;
+               default:
+                   prefix = FALSE;
+                   break;
+           }
+           if (prefix) {
+               get_value_inc(inst, loc, 1, FALSE);
+           }
+       } while (prefix);
+
+       if (inst >= 0xd8 && inst <= 0xdf) {
+           loc = db_disasm_esc(loc, inst, short_addr, size, seg);
+           db_printf("\n");
+           return (loc);
+       }
+
+       if (inst == 0x0f) {
+           get_value_inc(inst, loc, 1, FALSE);
+           ip = db_inst_0f[inst>>4];
+           if (ip == 0) {
+               ip = &db_bad_inst;
+           }
+           else {
+               ip = &ip[inst&0xf];
+           }
+       }
+       else
+           ip = &db_inst_table[inst];
+
+       if (ip->i_has_modrm) {
+           get_value_inc(regmodrm, loc, 1, FALSE);
+           loc = db_read_address(loc, short_addr, regmodrm, &address);
+       }
+
+       i_name = ip->i_name;
+       i_size = ip->i_size;
+       i_mode = ip->i_mode;
+
+       if (ip->i_extra == (char *)db_Grp1 ||
+           ip->i_extra == (char *)db_Grp2 ||
+           ip->i_extra == (char *)db_Grp6 ||
+           ip->i_extra == (char *)db_Grp7 ||
+           ip->i_extra == (char *)db_Grp8) {
+           i_name = ((char **)ip->i_extra)[f_reg(regmodrm)];
+       }
+       else if (ip->i_extra == (char *)db_Grp3) {
+           ip = (struct inst *)ip->i_extra;
+           ip = &ip[f_reg(regmodrm)];
+           i_name = ip->i_name;
+           i_mode = ip->i_mode;
+       }
+       else if (ip->i_extra == (char *)db_Grp4 ||
+                ip->i_extra == (char *)db_Grp5) {
+           ip = (struct inst *)ip->i_extra;
+           ip = &ip[f_reg(regmodrm)];
+           i_name = ip->i_name;
+           i_mode = ip->i_mode;
+           i_size = ip->i_size;
+       }
+
+       if (i_size == SDEP) {
+           if (size == WORD)
+               db_printf(i_name);
+           else
+               db_printf(ip->i_extra);
+       }
+       else {
+           db_printf(i_name);
+           if (i_size != NONE) {
+               if (i_size == BYTE) {
+                   db_printf("b");
+                   size = BYTE;
+               }
+               else if (i_size == WORD) {
+                   db_printf("w");
+                   size = WORD;
+               }
+               else if (size == WORD)
+                   db_printf("w");
+               else
+                   db_printf("l");
+           }
+       }
+       db_printf("\t");
+       for (first = TRUE;
+            i_mode != 0;
+            i_mode >>= 8, first = FALSE)
+       {
+           if (!first)
+               db_printf(",");
+
+           switch (i_mode & 0xFF) {
+
+               case E:
+                   db_print_address(seg, size, &address);
+                   break;
+
+               case Eind:
+                   db_printf("*");
+                   db_print_address(seg, size, &address);
+                   break;
+
+               case Ew:
+                   db_print_address(seg, WORD, &address);
+                   break;
+
+               case Eb:
+                   db_print_address(seg, BYTE, &address);
+                   break;
+
+               case R:
+                   db_printf("%s", db_reg[size][f_reg(regmodrm)]);
+                   break;
+
+               case Rw:
+                   db_printf("%s", db_reg[WORD][f_reg(regmodrm)]);
+                   break;
+
+               case Ri:
+                   db_printf("%s", db_reg[size][f_rm(inst)]);
+                   break;
+
+               case S:
+                   db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
+                   break;
+
+               case Si:
+                   db_printf("%s", db_seg_reg[f_reg(inst)]);
+                   break;
+
+               case A:
+                   db_printf("%s", db_reg[size][0]);   /* acc */
+                   break;
+
+               case BX:
+                   if (seg)
+                       db_printf("%s:", seg);
+                   db_printf("(%s)", short_addr ? "%bx" : "%ebx");
+                   break;
+
+               case CL:
+                   db_printf("%%cl");
+                   break;
+
+               case DX:
+                   db_printf("%%dx");
+                   break;
+
+               case SI:
+                   if (seg)
+                       db_printf("%s:", seg);
+                   db_printf("(%s)", short_addr ? "%si" : "%esi");
+                   break;
+
+               case DI:
+                   db_printf("%%es:(%s)", short_addr ? "%di" : "%edi");
+                   break;
+
+               case CR:
+                   db_printf("%%cr%d", f_reg(regmodrm));
+                   break;
+
+               case DR:
+                   db_printf("%%dr%d", f_reg(regmodrm));
+                   break;
+
+               case TR:
+                   db_printf("%%tr%d", f_reg(regmodrm));
+                   break;
+
+               case I:
+                   len = db_lengths[size];
+                   get_value_inc(imm, loc, len, FALSE);/* unsigned */
+                   db_printf("$%#n", imm);
+                   break;
+
+               case Is:
+                   len = db_lengths[size];
+                   get_value_inc(imm, loc, len, TRUE); /* signed */
+                   db_printf("$%#r", imm);
+                   break;
+
+               case Ib:
+                   get_value_inc(imm, loc, 1, FALSE);  /* unsigned */
+                   db_printf("$%#n", imm);
+                   break;
+
+               case Ibs:
+                   get_value_inc(imm, loc, 1, TRUE);   /* signed */
+                   db_printf("$%#r", imm);
+                   break;
+
+               case Iw:
+                   get_value_inc(imm, loc, 2, FALSE);  /* unsigned */
+                   db_printf("$%#n", imm);
+                   break;
+
+               case Il:
+                   get_value_inc(imm, loc, 4, FALSE);
+                   db_printf("$%#n", imm);
+                   break;
+
+               case O:
+                   if (short_addr) {
+                       get_value_inc(displ, loc, 2, TRUE);
+                   }
+                   else {
+                       get_value_inc(displ, loc, 4, TRUE);
+                   }
+                   if (seg)
+                       db_printf("%s:%#r",seg, displ);
+                   else
+                       db_printsym((db_addr_t)displ, DB_STGY_ANY);
+                   break;
+
+               case Db:
+                   get_value_inc(displ, loc, 1, TRUE);
+                   db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN);
+                   break;
+
+               case Dl:
+                   get_value_inc(displ, loc, 4, TRUE);
+                   db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN);
+                   break;
+
+               case o1:
+                   db_printf("$1");
+                   break;
+
+               case o3:
+                   db_printf("$3");
+                   break;
+
+               case OS:
+                   get_value_inc(imm, loc, 4, FALSE);  /* offset */
+                   get_value_inc(imm2, loc, 2, FALSE); /* segment */
+                   db_printf("$%#n,%#n", imm2, imm);
+                   break;
+           }
+       }
+
+       if (altfmt == 0) {
+           if (inst == 0xe9 || inst == 0xeb) {
+               /*
+                * GAS pads to longword boundary after unconditional jumps.
+                */
+               loc = (loc + (4-1)) & ~(4-1);
+           }
+       }
+       db_printf("\n");
+       return (loc);
+}
+