Initial revision
authorJohn Gilmore <gnu@cygnus>
Fri, 5 Apr 1991 09:01:15 +0000 (09:01 +0000)
committerJohn Gilmore <gnu@cygnus>
Fri, 5 Apr 1991 09:01:15 +0000 (09:01 +0000)
24 files changed:
gdb/convx-opcode.h [new file with mode: 0644]
gdb/doc/all.m4 [new file with mode: 0644]
gdb/doc/amd29k.m4 [new file with mode: 0644]
gdb/doc/gen.m4 [new file with mode: 0644]
gdb/doc/i80386.m4 [new file with mode: 0644]
gdb/doc/i960.m4 [new file with mode: 0644]
gdb/doc/m680x0.m4 [new file with mode: 0644]
gdb/doc/none.m4 [new file with mode: 0644]
gdb/doc/pretex.m4 [new file with mode: 0644]
gdb/doc/sparc.m4 [new file with mode: 0644]
gdb/doc/vax.m4 [new file with mode: 0644]
gdb/hp300ux-xdep.c [new file with mode: 0644]
gdb/infrun.hacked.c [new file with mode: 0644]
gdb/mtrace.awk [new file with mode: 0755]
gdb/mtrace.c [new file with mode: 0755]
gdb/rem-m68k.shar [new file with mode: 0755]
gdb/rem-multi.shar [new file with mode: 0644]
gdb/remote-sa.sparc.c [new file with mode: 0644]
gdb/remote-vx.68.c [new file with mode: 0644]
gdb/symm-tdep.c [new file with mode: 0644]
gdb/symm-xdep.c [new file with mode: 0644]
gdb/tm-vx68.h [new file with mode: 0644]
gdb/tm-vx960.h [new file with mode: 0644]
gdb/xm-i386sco.h [new file with mode: 0644]

diff --git a/gdb/convx-opcode.h b/gdb/convx-opcode.h
new file mode 100644 (file)
index 0000000..523c874
--- /dev/null
@@ -0,0 +1,1677 @@
+/* Include information for instruction dissasembly on the Convex.
+   Copyright (C) 1989, Free Software Foundation.  
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define xxx 0
+#define rrr 1
+#define rr 2
+#define rxr 3
+#define r 4
+#define nops 5
+#define nr 6
+#define pcrel 7
+#define lr 8
+#define rxl 9
+#define rlr 10
+#define rrl 11
+#define iml 12
+#define imr 13
+#define a1r 14
+#define a1l 15
+#define a2r 16
+#define a2l 17
+#define a3 18
+#define a4 19
+#define a5 20
+#define V 1
+#define S 2
+#define VM 3
+#define A 4
+#define VL 5
+#define VS 6
+#define VLS 7
+#define PSW 8
+/* Prevent an error during "make depend".  */
+#if !defined (PC)
+#define PC 9
+#endif
+#define ITR 10
+#define VV 11
+#define ITSR 12
+#define TOC 13
+#define CIR 14
+#define TTR 15
+#define VMU 16
+#define VML 17
+#define ICR 18
+#define TCPU 19
+#define CPUID 20
+#define TID 21
+char *op[] = {
+  "",
+  "v0\0v1\0v2\0v3\0v4\0v5\0v6\0v7",
+  "s0\0s1\0s2\0s3\0s4\0s5\0s6\0s7",
+  "vm",
+  "sp\0a1\0a2\0a3\0a4\0a5\0ap\0fp",
+  "vl",
+  "vs",
+  "vls",
+  "psw",
+  "pc",
+  "itr",
+  "vv",
+  "itsr",
+  "toc",
+  "cir",
+  "ttr",
+  "vmu",
+  "vml",
+  "icr",
+  "tcpu",
+  "cpuid",
+  "tid",
+};
+struct formstr format0[] = {
+  {0,0,rrr,V,S,S},     /* mov */
+  {0,0,rrr,S,S,V},     /* mov */
+  {1,1,rrr,V,V,V},     /* merg.t */
+  {2,1,rrr,V,V,V},     /* mask.t */
+  {1,2,rrr,V,S,V},     /* merg.f */
+  {2,2,rrr,V,S,V},     /* mask.f */
+  {1,1,rrr,V,S,V},     /* merg.t */
+  {2,1,rrr,V,S,V},     /* mask.t */
+  {3,3,rrr,V,V,V},     /* mul.s */
+  {3,4,rrr,V,V,V},     /* mul.d */
+  {4,3,rrr,V,V,V},     /* div.s */
+  {4,4,rrr,V,V,V},     /* div.d */
+  {3,3,rrr,V,S,V},     /* mul.s */
+  {3,4,rrr,V,S,V},     /* mul.d */
+  {4,3,rrr,V,S,V},     /* div.s */
+  {4,4,rrr,V,S,V},     /* div.d */
+  {5,0,rrr,V,V,V},     /* and */
+  {6,0,rrr,V,V,V},     /* or */
+  {7,0,rrr,V,V,V},     /* xor */
+  {8,0,rrr,V,V,V},     /* shf */
+  {5,0,rrr,V,S,V},     /* and */
+  {6,0,rrr,V,S,V},     /* or */
+  {7,0,rrr,V,S,V},     /* xor */
+  {8,0,rrr,V,S,V},     /* shf */
+  {9,3,rrr,V,V,V},     /* add.s */
+  {9,4,rrr,V,V,V},     /* add.d */
+  {10,3,rrr,V,V,V},    /* sub.s */
+  {10,4,rrr,V,V,V},    /* sub.d */
+  {9,3,rrr,V,S,V},     /* add.s */
+  {9,4,rrr,V,S,V},     /* add.d */
+  {10,3,rrr,V,S,V},    /* sub.s */
+  {10,4,rrr,V,S,V},    /* sub.d */
+  {9,5,rrr,V,V,V},     /* add.b */
+  {9,6,rrr,V,V,V},     /* add.h */
+  {9,7,rrr,V,V,V},     /* add.w */
+  {9,8,rrr,V,V,V},     /* add.l */
+  {9,5,rrr,V,S,V},     /* add.b */
+  {9,6,rrr,V,S,V},     /* add.h */
+  {9,7,rrr,V,S,V},     /* add.w */
+  {9,8,rrr,V,S,V},     /* add.l */
+  {10,5,rrr,V,V,V},    /* sub.b */
+  {10,6,rrr,V,V,V},    /* sub.h */
+  {10,7,rrr,V,V,V},    /* sub.w */
+  {10,8,rrr,V,V,V},    /* sub.l */
+  {10,5,rrr,V,S,V},    /* sub.b */
+  {10,6,rrr,V,S,V},    /* sub.h */
+  {10,7,rrr,V,S,V},    /* sub.w */
+  {10,8,rrr,V,S,V},    /* sub.l */
+  {3,5,rrr,V,V,V},     /* mul.b */
+  {3,6,rrr,V,V,V},     /* mul.h */
+  {3,7,rrr,V,V,V},     /* mul.w */
+  {3,8,rrr,V,V,V},     /* mul.l */
+  {3,5,rrr,V,S,V},     /* mul.b */
+  {3,6,rrr,V,S,V},     /* mul.h */
+  {3,7,rrr,V,S,V},     /* mul.w */
+  {3,8,rrr,V,S,V},     /* mul.l */
+  {4,5,rrr,V,V,V},     /* div.b */
+  {4,6,rrr,V,V,V},     /* div.h */
+  {4,7,rrr,V,V,V},     /* div.w */
+  {4,8,rrr,V,V,V},     /* div.l */
+  {4,5,rrr,V,S,V},     /* div.b */
+  {4,6,rrr,V,S,V},     /* div.h */
+  {4,7,rrr,V,S,V},     /* div.w */
+  {4,8,rrr,V,S,V},     /* div.l */
+};
+struct formstr format1[] = {
+  {11,0,xxx,0,0,0},    /* exit */
+  {12,0,a3,0,0,0},     /* jmp */
+  {13,2,a3,0,0,0},     /* jmpi.f */
+  {13,1,a3,0,0,0},     /* jmpi.t */
+  {14,2,a3,0,0,0},     /* jmpa.f */
+  {14,1,a3,0,0,0},     /* jmpa.t */
+  {15,2,a3,0,0,0},     /* jmps.f */
+  {15,1,a3,0,0,0},     /* jmps.t */
+  {16,0,a3,0,0,0},     /* tac */
+  {17,0,a1r,A,0,0},    /* ldea */
+  {18,8,a1l,VLS,0,0},  /* ld.l */
+  {18,9,a1l,VM,0,0},   /* ld.x */
+  {19,0,a3,0,0,0},     /* tas */
+  {20,0,a3,0,0,0},     /* pshea */
+  {21,8,a2l,VLS,0,0},  /* st.l */
+  {21,9,a2l,VM,0,0},   /* st.x */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {22,0,a3,0,0,0},     /* call */
+  {23,0,a3,0,0,0},     /* calls */
+  {24,0,a3,0,0,0},     /* callq */
+  {25,0,a1r,A,0,0},    /* pfork */
+  {26,5,a2r,S,0,0},    /* ste.b */
+  {26,6,a2r,S,0,0},    /* ste.h */
+  {26,7,a2r,S,0,0},    /* ste.w */
+  {26,8,a2r,S,0,0},    /* ste.l */
+  {18,5,a1r,A,0,0},    /* ld.b */
+  {18,6,a1r,A,0,0},    /* ld.h */
+  {18,7,a1r,A,0,0},    /* ld.w */
+  {27,7,a1r,A,0,0},    /* incr.w */
+  {21,5,a2r,A,0,0},    /* st.b */
+  {21,6,a2r,A,0,0},    /* st.h */
+  {21,7,a2r,A,0,0},    /* st.w */
+  {27,8,a1r,S,0,0},    /* incr.l */
+  {18,5,a1r,S,0,0},    /* ld.b */
+  {18,6,a1r,S,0,0},    /* ld.h */
+  {18,7,a1r,S,0,0},    /* ld.w */
+  {18,8,a1r,S,0,0},    /* ld.l */
+  {21,5,a2r,S,0,0},    /* st.b */
+  {21,6,a2r,S,0,0},    /* st.h */
+  {21,7,a2r,S,0,0},    /* st.w */
+  {21,8,a2r,S,0,0},    /* st.l */
+  {18,5,a1r,V,0,0},    /* ld.b */
+  {18,6,a1r,V,0,0},    /* ld.h */
+  {18,7,a1r,V,0,0},    /* ld.w */
+  {18,8,a1r,V,0,0},    /* ld.l */
+  {21,5,a2r,V,0,0},    /* st.b */
+  {21,6,a2r,V,0,0},    /* st.h */
+  {21,7,a2r,V,0,0},    /* st.w */
+  {21,8,a2r,V,0,0},    /* st.l */
+};
+struct formstr format2[] = {
+  {28,5,rr,A,A,0},     /* cvtw.b */
+  {28,6,rr,A,A,0},     /* cvtw.h */
+  {29,7,rr,A,A,0},     /* cvtb.w */
+  {30,7,rr,A,A,0},     /* cvth.w */
+  {28,5,rr,S,S,0},     /* cvtw.b */
+  {28,6,rr,S,S,0},     /* cvtw.h */
+  {29,7,rr,S,S,0},     /* cvtb.w */
+  {30,7,rr,S,S,0},     /* cvth.w */
+  {28,3,rr,S,S,0},     /* cvtw.s */
+  {31,7,rr,S,S,0},     /* cvts.w */
+  {32,3,rr,S,S,0},     /* cvtd.s */
+  {31,4,rr,S,S,0},     /* cvts.d */
+  {31,8,rr,S,S,0},     /* cvts.l */
+  {32,8,rr,S,S,0},     /* cvtd.l */
+  {33,3,rr,S,S,0},     /* cvtl.s */
+  {33,4,rr,S,S,0},     /* cvtl.d */
+  {34,0,rr,A,A,0},     /* ldpa */
+  {8,0,nr,A,0,0},      /* shf */
+  {18,6,nr,A,0,0},     /* ld.h */
+  {18,7,nr,A,0,0},     /* ld.w */
+  {33,7,rr,S,S,0},     /* cvtl.w */
+  {28,8,rr,S,S,0},     /* cvtw.l */
+  {35,1,rr,S,S,0},     /* plc.t */
+  {36,0,rr,S,S,0},     /* tzc */
+  {37,6,rr,A,A,0},     /* eq.h */
+  {37,7,rr,A,A,0},     /* eq.w */
+  {37,6,nr,A,0,0},     /* eq.h */
+  {37,7,nr,A,0,0},     /* eq.w */
+  {37,5,rr,S,S,0},     /* eq.b */
+  {37,6,rr,S,S,0},     /* eq.h */
+  {37,7,rr,S,S,0},     /* eq.w */
+  {37,8,rr,S,S,0},     /* eq.l */
+  {38,6,rr,A,A,0},     /* leu.h */
+  {38,7,rr,A,A,0},     /* leu.w */
+  {38,6,nr,A,0,0},     /* leu.h */
+  {38,7,nr,A,0,0},     /* leu.w */
+  {38,5,rr,S,S,0},     /* leu.b */
+  {38,6,rr,S,S,0},     /* leu.h */
+  {38,7,rr,S,S,0},     /* leu.w */
+  {38,8,rr,S,S,0},     /* leu.l */
+  {39,6,rr,A,A,0},     /* ltu.h */
+  {39,7,rr,A,A,0},     /* ltu.w */
+  {39,6,nr,A,0,0},     /* ltu.h */
+  {39,7,nr,A,0,0},     /* ltu.w */
+  {39,5,rr,S,S,0},     /* ltu.b */
+  {39,6,rr,S,S,0},     /* ltu.h */
+  {39,7,rr,S,S,0},     /* ltu.w */
+  {39,8,rr,S,S,0},     /* ltu.l */
+  {40,6,rr,A,A,0},     /* le.h */
+  {40,7,rr,A,A,0},     /* le.w */
+  {40,6,nr,A,0,0},     /* le.h */
+  {40,7,nr,A,0,0},     /* le.w */
+  {40,5,rr,S,S,0},     /* le.b */
+  {40,6,rr,S,S,0},     /* le.h */
+  {40,7,rr,S,S,0},     /* le.w */
+  {40,8,rr,S,S,0},     /* le.l */
+  {41,6,rr,A,A,0},     /* lt.h */
+  {41,7,rr,A,A,0},     /* lt.w */
+  {41,6,nr,A,0,0},     /* lt.h */
+  {41,7,nr,A,0,0},     /* lt.w */
+  {41,5,rr,S,S,0},     /* lt.b */
+  {41,6,rr,S,S,0},     /* lt.h */
+  {41,7,rr,S,S,0},     /* lt.w */
+  {41,8,rr,S,S,0},     /* lt.l */
+  {9,7,rr,S,A,0},      /* add.w */
+  {8,0,rr,A,A,0},      /* shf */
+  {0,0,rr,A,A,0},      /* mov */
+  {0,0,rr,S,A,0},      /* mov */
+  {0,7,rr,S,S,0},      /* mov.w */
+  {8,0,rr,S,S,0},      /* shf */
+  {0,0,rr,S,S,0},      /* mov */
+  {0,0,rr,A,S,0},      /* mov */
+  {5,0,rr,A,A,0},      /* and */
+  {6,0,rr,A,A,0},      /* or */
+  {7,0,rr,A,A,0},      /* xor */
+  {42,0,rr,A,A,0},     /* not */
+  {5,0,rr,S,S,0},      /* and */
+  {6,0,rr,S,S,0},      /* or */
+  {7,0,rr,S,S,0},      /* xor */
+  {42,0,rr,S,S,0},     /* not */
+  {40,3,rr,S,S,0},     /* le.s */
+  {40,4,rr,S,S,0},     /* le.d */
+  {41,3,rr,S,S,0},     /* lt.s */
+  {41,4,rr,S,S,0},     /* lt.d */
+  {9,3,rr,S,S,0},      /* add.s */
+  {9,4,rr,S,S,0},      /* add.d */
+  {10,3,rr,S,S,0},     /* sub.s */
+  {10,4,rr,S,S,0},     /* sub.d */
+  {37,3,rr,S,S,0},     /* eq.s */
+  {37,4,rr,S,S,0},     /* eq.d */
+  {43,6,rr,A,A,0},     /* neg.h */
+  {43,7,rr,A,A,0},     /* neg.w */
+  {3,3,rr,S,S,0},      /* mul.s */
+  {3,4,rr,S,S,0},      /* mul.d */
+  {4,3,rr,S,S,0},      /* div.s */
+  {4,4,rr,S,S,0},      /* div.d */
+  {9,6,rr,A,A,0},      /* add.h */
+  {9,7,rr,A,A,0},      /* add.w */
+  {9,6,nr,A,0,0},      /* add.h */
+  {9,7,nr,A,0,0},      /* add.w */
+  {9,5,rr,S,S,0},      /* add.b */
+  {9,6,rr,S,S,0},      /* add.h */
+  {9,7,rr,S,S,0},      /* add.w */
+  {9,8,rr,S,S,0},      /* add.l */
+  {10,6,rr,A,A,0},     /* sub.h */
+  {10,7,rr,A,A,0},     /* sub.w */
+  {10,6,nr,A,0,0},     /* sub.h */
+  {10,7,nr,A,0,0},     /* sub.w */
+  {10,5,rr,S,S,0},     /* sub.b */
+  {10,6,rr,S,S,0},     /* sub.h */
+  {10,7,rr,S,S,0},     /* sub.w */
+  {10,8,rr,S,S,0},     /* sub.l */
+  {3,6,rr,A,A,0},      /* mul.h */
+  {3,7,rr,A,A,0},      /* mul.w */
+  {3,6,nr,A,0,0},      /* mul.h */
+  {3,7,nr,A,0,0},      /* mul.w */
+  {3,5,rr,S,S,0},      /* mul.b */
+  {3,6,rr,S,S,0},      /* mul.h */
+  {3,7,rr,S,S,0},      /* mul.w */
+  {3,8,rr,S,S,0},      /* mul.l */
+  {4,6,rr,A,A,0},      /* div.h */
+  {4,7,rr,A,A,0},      /* div.w */
+  {4,6,nr,A,0,0},      /* div.h */
+  {4,7,nr,A,0,0},      /* div.w */
+  {4,5,rr,S,S,0},      /* div.b */
+  {4,6,rr,S,S,0},      /* div.h */
+  {4,7,rr,S,S,0},      /* div.w */
+  {4,8,rr,S,S,0},      /* div.l */
+};
+struct formstr format3[] = {
+  {32,3,rr,V,V,0},     /* cvtd.s */
+  {31,4,rr,V,V,0},     /* cvts.d */
+  {33,4,rr,V,V,0},     /* cvtl.d */
+  {32,8,rr,V,V,0},     /* cvtd.l */
+  {0,0,rrl,S,S,VM},    /* mov */
+  {0,0,rlr,S,VM,S},    /* mov */
+  {0,0,0,0,0,0},
+  {44,0,rr,S,S,0},     /* lop */
+  {36,0,rr,V,V,0},     /* tzc */
+  {44,0,rr,V,V,0},     /* lop */
+  {0,0,0,0,0,0},
+  {42,0,rr,V,V,0},     /* not */
+  {8,0,rr,S,V,0},      /* shf */
+  {35,1,rr,V,V,0},     /* plc.t */
+  {45,2,rr,V,V,0},     /* cprs.f */
+  {45,1,rr,V,V,0},     /* cprs.t */
+  {37,3,rr,V,V,0},     /* eq.s */
+  {37,4,rr,V,V,0},     /* eq.d */
+  {43,3,rr,V,V,0},     /* neg.s */
+  {43,4,rr,V,V,0},     /* neg.d */
+  {37,3,rr,S,V,0},     /* eq.s */
+  {37,4,rr,S,V,0},     /* eq.d */
+  {43,3,rr,S,S,0},     /* neg.s */
+  {43,4,rr,S,S,0},     /* neg.d */
+  {40,3,rr,V,V,0},     /* le.s */
+  {40,4,rr,V,V,0},     /* le.d */
+  {41,3,rr,V,V,0},     /* lt.s */
+  {41,4,rr,V,V,0},     /* lt.d */
+  {40,3,rr,S,V,0},     /* le.s */
+  {40,4,rr,S,V,0},     /* le.d */
+  {41,3,rr,S,V,0},     /* lt.s */
+  {41,4,rr,S,V,0},     /* lt.d */
+  {37,5,rr,V,V,0},     /* eq.b */
+  {37,6,rr,V,V,0},     /* eq.h */
+  {37,7,rr,V,V,0},     /* eq.w */
+  {37,8,rr,V,V,0},     /* eq.l */
+  {37,5,rr,S,V,0},     /* eq.b */
+  {37,6,rr,S,V,0},     /* eq.h */
+  {37,7,rr,S,V,0},     /* eq.w */
+  {37,8,rr,S,V,0},     /* eq.l */
+  {40,5,rr,V,V,0},     /* le.b */
+  {40,6,rr,V,V,0},     /* le.h */
+  {40,7,rr,V,V,0},     /* le.w */
+  {40,8,rr,V,V,0},     /* le.l */
+  {40,5,rr,S,V,0},     /* le.b */
+  {40,6,rr,S,V,0},     /* le.h */
+  {40,7,rr,S,V,0},     /* le.w */
+  {40,8,rr,S,V,0},     /* le.l */
+  {41,5,rr,V,V,0},     /* lt.b */
+  {41,6,rr,V,V,0},     /* lt.h */
+  {41,7,rr,V,V,0},     /* lt.w */
+  {41,8,rr,V,V,0},     /* lt.l */
+  {41,5,rr,S,V,0},     /* lt.b */
+  {41,6,rr,S,V,0},     /* lt.h */
+  {41,7,rr,S,V,0},     /* lt.w */
+  {41,8,rr,S,V,0},     /* lt.l */
+  {43,5,rr,V,V,0},     /* neg.b */
+  {43,6,rr,V,V,0},     /* neg.h */
+  {43,7,rr,V,V,0},     /* neg.w */
+  {43,8,rr,V,V,0},     /* neg.l */
+  {43,5,rr,S,S,0},     /* neg.b */
+  {43,6,rr,S,S,0},     /* neg.h */
+  {43,7,rr,S,S,0},     /* neg.w */
+  {43,8,rr,S,S,0},     /* neg.l */
+};
+struct formstr format4[] = {
+  {46,0,nops,0,0,0},   /* nop */
+  {47,0,pcrel,0,0,0},  /* br */
+  {48,2,pcrel,0,0,0},  /* bri.f */
+  {48,1,pcrel,0,0,0},  /* bri.t */
+  {49,2,pcrel,0,0,0},  /* bra.f */
+  {49,1,pcrel,0,0,0},  /* bra.t */
+  {50,2,pcrel,0,0,0},  /* brs.f */
+  {50,1,pcrel,0,0,0},  /* brs.t */
+};
+struct formstr format5[] = {
+  {51,5,rr,V,V,0},     /* ldvi.b */
+  {51,6,rr,V,V,0},     /* ldvi.h */
+  {51,7,rr,V,V,0},     /* ldvi.w */
+  {51,8,rr,V,V,0},     /* ldvi.l */
+  {28,3,rr,V,V,0},     /* cvtw.s */
+  {31,7,rr,V,V,0},     /* cvts.w */
+  {28,8,rr,V,V,0},     /* cvtw.l */
+  {33,7,rr,V,V,0},     /* cvtl.w */
+  {52,5,rxr,V,V,0},    /* stvi.b */
+  {52,6,rxr,V,V,0},    /* stvi.h */
+  {52,7,rxr,V,V,0},    /* stvi.w */
+  {52,8,rxr,V,V,0},    /* stvi.l */
+  {52,5,rxr,S,V,0},    /* stvi.b */
+  {52,6,rxr,S,V,0},    /* stvi.h */
+  {52,7,rxr,S,V,0},    /* stvi.w */
+  {52,8,rxr,S,V,0},    /* stvi.l */
+};
+struct formstr format6[] = {
+  {53,0,r,A,0,0},      /* ldsdr */
+  {54,0,r,A,0,0},      /* ldkdr */
+  {55,3,r,S,0,0},      /* ln.s */
+  {55,4,r,S,0,0},      /* ln.d */
+  {56,0,nops,0,0,0},   /* patu */
+  {57,0,r,A,0,0},      /* pate */
+  {58,0,nops,0,0,0},   /* pich */
+  {59,0,nops,0,0,0},   /* plch */
+  {0,0,lr,PSW,A,0},    /* mov */
+  {0,0,rxl,A,PSW,0},   /* mov */
+  {0,0,lr,PC,A,0},     /* mov */
+  {60,0,r,S,0,0},      /* idle */
+  {0,0,lr,ITR,S,0},    /* mov */
+  {0,0,rxl,S,ITR,0},   /* mov */
+  {0,0,0,0,0,0},
+  {0,0,rxl,S,ITSR,0},  /* mov */
+  {61,0,nops,0,0,0},   /* rtnq */
+  {62,0,nops,0,0,0},   /* cfork */
+  {63,0,nops,0,0,0},   /* rtn */
+  {64,0,nops,0,0,0},   /* wfork */
+  {65,0,nops,0,0,0},   /* join */
+  {66,0,nops,0,0,0},   /* rtnc */
+  {67,3,r,S,0,0},      /* exp.s */
+  {67,4,r,S,0,0},      /* exp.d */
+  {68,3,r,S,0,0},      /* sin.s */
+  {68,4,r,S,0,0},      /* sin.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {69,3,r,S,0,0},      /* cos.s */
+  {69,4,r,S,0,0},      /* cos.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {70,7,r,A,0,0},      /* psh.w */
+  {0,0,0,0,0,0},
+  {71,7,r,A,0,0},      /* pop.w */
+  {0,0,0,0,0,0},
+  {70,7,r,S,0,0},      /* psh.w */
+  {70,8,r,S,0,0},      /* psh.l */
+  {71,7,r,S,0,0},      /* pop.w */
+  {71,8,r,S,0,0},      /* pop.l */
+  {72,0,nops,0,0,0},   /* eni */
+  {73,0,nops,0,0,0},   /* dsi */
+  {74,0,nops,0,0,0},   /* bkpt */
+  {75,0,nops,0,0,0},   /* msync */
+  {76,0,r,S,0,0},      /* mski */
+  {77,0,r,S,0,0},      /* xmti */
+  {0,0,rxl,S,VV,0},    /* mov */
+  {78,0,nops,0,0,0},   /* tstvv */
+  {0,0,lr,VS,A,0},     /* mov */
+  {0,0,rxl,A,VS,0},    /* mov */
+  {0,0,lr,VL,A,0},     /* mov */
+  {0,0,rxl,A,VL,0},    /* mov */
+  {0,7,lr,VS,S,0},     /* mov.w */
+  {0,7,rxl,S,VS,0},    /* mov.w */
+  {0,7,lr,VL,S,0},     /* mov.w */
+  {0,7,rxl,S,VL,0},    /* mov.w */
+  {79,0,r,A,0,0},      /* diag */
+  {80,0,nops,0,0,0},   /* pbkpt */
+  {81,3,r,S,0,0},      /* sqrt.s */
+  {81,4,r,S,0,0},      /* sqrt.d */
+  {82,0,nops,0,0,0},   /* casr */
+  {0,0,0,0,0,0},
+  {83,3,r,S,0,0},      /* atan.s */
+  {83,4,r,S,0,0},      /* atan.d */
+};
+struct formstr format7[] = {
+  {84,5,r,V,0,0},      /* sum.b */
+  {84,6,r,V,0,0},      /* sum.h */
+  {84,7,r,V,0,0},      /* sum.w */
+  {84,8,r,V,0,0},      /* sum.l */
+  {85,0,r,V,0,0},      /* all */
+  {86,0,r,V,0,0},      /* any */
+  {87,0,r,V,0,0},      /* parity */
+  {0,0,0,0,0,0},
+  {88,5,r,V,0,0},      /* max.b */
+  {88,6,r,V,0,0},      /* max.h */
+  {88,7,r,V,0,0},      /* max.w */
+  {88,8,r,V,0,0},      /* max.l */
+  {89,5,r,V,0,0},      /* min.b */
+  {89,6,r,V,0,0},      /* min.h */
+  {89,7,r,V,0,0},      /* min.w */
+  {89,8,r,V,0,0},      /* min.l */
+  {84,3,r,V,0,0},      /* sum.s */
+  {84,4,r,V,0,0},      /* sum.d */
+  {90,3,r,V,0,0},      /* prod.s */
+  {90,4,r,V,0,0},      /* prod.d */
+  {88,3,r,V,0,0},      /* max.s */
+  {88,4,r,V,0,0},      /* max.d */
+  {89,3,r,V,0,0},      /* min.s */
+  {89,4,r,V,0,0},      /* min.d */
+  {90,5,r,V,0,0},      /* prod.b */
+  {90,6,r,V,0,0},      /* prod.h */
+  {90,7,r,V,0,0},      /* prod.w */
+  {90,8,r,V,0,0},      /* prod.l */
+  {35,2,lr,VM,S,0},    /* plc.f */
+  {35,1,lr,VM,S,0},    /* plc.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr formatx[] = {
+  {0,0,0,0,0,0},
+};
+struct formstr format1a[] = {
+  {91,0,imr,A,0,0},    /* halt */
+  {92,0,a4,0,0,0},     /* sysc */
+  {18,6,imr,A,0,0},    /* ld.h */
+  {18,7,imr,A,0,0},    /* ld.w */
+  {5,0,imr,A,0,0},     /* and */
+  {6,0,imr,A,0,0},     /* or */
+  {7,0,imr,A,0,0},     /* xor */
+  {8,0,imr,A,0,0},     /* shf */
+  {9,6,imr,A,0,0},     /* add.h */
+  {9,7,imr,A,0,0},     /* add.w */
+  {10,6,imr,A,0,0},    /* sub.h */
+  {10,7,imr,A,0,0},    /* sub.w */
+  {3,6,imr,A,0,0},     /* mul.h */
+  {3,7,imr,A,0,0},     /* mul.w */
+  {4,6,imr,A,0,0},     /* div.h */
+  {4,7,imr,A,0,0},     /* div.w */
+  {18,7,iml,VL,0,0},   /* ld.w */
+  {18,7,iml,VS,0,0},   /* ld.w */
+  {0,0,0,0,0,0},
+  {8,7,imr,S,0,0},     /* shf.w */
+  {93,0,a5,0,0,0},     /* trap */
+  {0,0,0,0,0,0},
+  {37,6,imr,A,0,0},    /* eq.h */
+  {37,7,imr,A,0,0},    /* eq.w */
+  {38,6,imr,A,0,0},    /* leu.h */
+  {38,7,imr,A,0,0},    /* leu.w */
+  {39,6,imr,A,0,0},    /* ltu.h */
+  {39,7,imr,A,0,0},    /* ltu.w */
+  {40,6,imr,A,0,0},    /* le.h */
+  {40,7,imr,A,0,0},    /* le.w */
+  {41,6,imr,A,0,0},    /* lt.h */
+  {41,7,imr,A,0,0},    /* lt.w */
+};
+struct formstr format1b[] = {
+  {18,4,imr,S,0,0},    /* ld.d */
+  {18,10,imr,S,0,0},   /* ld.u */
+  {18,8,imr,S,0,0},    /* ld.l */
+  {18,7,imr,S,0,0},    /* ld.w */
+  {5,0,imr,S,0,0},     /* and */
+  {6,0,imr,S,0,0},     /* or */
+  {7,0,imr,S,0,0},     /* xor */
+  {8,0,imr,S,0,0},     /* shf */
+  {9,6,imr,S,0,0},     /* add.h */
+  {9,7,imr,S,0,0},     /* add.w */
+  {10,6,imr,S,0,0},    /* sub.h */
+  {10,7,imr,S,0,0},    /* sub.w */
+  {3,6,imr,S,0,0},     /* mul.h */
+  {3,7,imr,S,0,0},     /* mul.w */
+  {4,6,imr,S,0,0},     /* div.h */
+  {4,7,imr,S,0,0},     /* div.w */
+  {9,3,imr,S,0,0},     /* add.s */
+  {10,3,imr,S,0,0},    /* sub.s */
+  {3,3,imr,S,0,0},     /* mul.s */
+  {4,3,imr,S,0,0},     /* div.s */
+  {40,3,imr,S,0,0},    /* le.s */
+  {41,3,imr,S,0,0},    /* lt.s */
+  {37,6,imr,S,0,0},    /* eq.h */
+  {37,7,imr,S,0,0},    /* eq.w */
+  {38,6,imr,S,0,0},    /* leu.h */
+  {38,7,imr,S,0,0},    /* leu.w */
+  {39,6,imr,S,0,0},    /* ltu.h */
+  {39,7,imr,S,0,0},    /* ltu.w */
+  {40,6,imr,S,0,0},    /* le.h */
+  {40,7,imr,S,0,0},    /* le.w */
+  {41,6,imr,S,0,0},    /* lt.h */
+  {41,7,imr,S,0,0},    /* lt.w */
+};
+struct formstr e0_format0[] = {
+  {10,3,rrr,S,V,V},    /* sub.s */
+  {10,4,rrr,S,V,V},    /* sub.d */
+  {4,3,rrr,S,V,V},     /* div.s */
+  {4,4,rrr,S,V,V},     /* div.d */
+  {10,11,rrr,S,V,V},   /* sub.s.f */
+  {10,12,rrr,S,V,V},   /* sub.d.f */
+  {4,11,rrr,S,V,V},    /* div.s.f */
+  {4,12,rrr,S,V,V},    /* div.d.f */
+  {3,11,rrr,V,V,V},    /* mul.s.f */
+  {3,12,rrr,V,V,V},    /* mul.d.f */
+  {4,11,rrr,V,V,V},    /* div.s.f */
+  {4,12,rrr,V,V,V},    /* div.d.f */
+  {3,11,rrr,V,S,V},    /* mul.s.f */
+  {3,12,rrr,V,S,V},    /* mul.d.f */
+  {4,11,rrr,V,S,V},    /* div.s.f */
+  {4,12,rrr,V,S,V},    /* div.d.f */
+  {5,2,rrr,V,V,V},     /* and.f */
+  {6,2,rrr,V,V,V},     /* or.f */
+  {7,2,rrr,V,V,V},     /* xor.f */
+  {8,2,rrr,V,V,V},     /* shf.f */
+  {5,2,rrr,V,S,V},     /* and.f */
+  {6,2,rrr,V,S,V},     /* or.f */
+  {7,2,rrr,V,S,V},     /* xor.f */
+  {8,2,rrr,V,S,V},     /* shf.f */
+  {9,11,rrr,V,V,V},    /* add.s.f */
+  {9,12,rrr,V,V,V},    /* add.d.f */
+  {10,11,rrr,V,V,V},   /* sub.s.f */
+  {10,12,rrr,V,V,V},   /* sub.d.f */
+  {9,11,rrr,V,S,V},    /* add.s.f */
+  {9,12,rrr,V,S,V},    /* add.d.f */
+  {10,11,rrr,V,S,V},   /* sub.s.f */
+  {10,12,rrr,V,S,V},   /* sub.d.f */
+  {9,13,rrr,V,V,V},    /* add.b.f */
+  {9,14,rrr,V,V,V},    /* add.h.f */
+  {9,15,rrr,V,V,V},    /* add.w.f */
+  {9,16,rrr,V,V,V},    /* add.l.f */
+  {9,13,rrr,V,S,V},    /* add.b.f */
+  {9,14,rrr,V,S,V},    /* add.h.f */
+  {9,15,rrr,V,S,V},    /* add.w.f */
+  {9,16,rrr,V,S,V},    /* add.l.f */
+  {10,13,rrr,V,V,V},   /* sub.b.f */
+  {10,14,rrr,V,V,V},   /* sub.h.f */
+  {10,15,rrr,V,V,V},   /* sub.w.f */
+  {10,16,rrr,V,V,V},   /* sub.l.f */
+  {10,13,rrr,V,S,V},   /* sub.b.f */
+  {10,14,rrr,V,S,V},   /* sub.h.f */
+  {10,15,rrr,V,S,V},   /* sub.w.f */
+  {10,16,rrr,V,S,V},   /* sub.l.f */
+  {3,13,rrr,V,V,V},    /* mul.b.f */
+  {3,14,rrr,V,V,V},    /* mul.h.f */
+  {3,15,rrr,V,V,V},    /* mul.w.f */
+  {3,16,rrr,V,V,V},    /* mul.l.f */
+  {3,13,rrr,V,S,V},    /* mul.b.f */
+  {3,14,rrr,V,S,V},    /* mul.h.f */
+  {3,15,rrr,V,S,V},    /* mul.w.f */
+  {3,16,rrr,V,S,V},    /* mul.l.f */
+  {4,13,rrr,V,V,V},    /* div.b.f */
+  {4,14,rrr,V,V,V},    /* div.h.f */
+  {4,15,rrr,V,V,V},    /* div.w.f */
+  {4,16,rrr,V,V,V},    /* div.l.f */
+  {4,13,rrr,V,S,V},    /* div.b.f */
+  {4,14,rrr,V,S,V},    /* div.h.f */
+  {4,15,rrr,V,S,V},    /* div.w.f */
+  {4,16,rrr,V,S,V},    /* div.l.f */
+};
+struct formstr e0_format1[] = {
+  {0,0,0,0,0,0},
+  {94,0,a3,0,0,0},     /* tst */
+  {95,0,a3,0,0,0},     /* lck */
+  {96,0,a3,0,0,0},     /* ulk */
+  {17,0,a1r,S,0,0},    /* ldea */
+  {97,0,a1r,A,0,0},    /* spawn */
+  {98,0,a1r,A,0,0},    /* ldcmr */
+  {99,0,a2r,A,0,0},    /* stcmr */
+  {100,0,a1r,A,0,0},   /* popr */
+  {101,0,a2r,A,0,0},   /* pshr */
+  {102,7,a1r,A,0,0},   /* rcvr.w */
+  {103,7,a2r,A,0,0},   /* matm.w */
+  {104,7,a2r,A,0,0},   /* sndr.w */
+  {104,8,a2r,S,0,0},   /* sndr.l */
+  {102,8,a1r,S,0,0},   /* rcvr.l */
+  {103,8,a2r,S,0,0},   /* matm.l */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {105,7,a2r,A,0,0},   /* putr.w */
+  {105,8,a2r,S,0,0},   /* putr.l */
+  {106,7,a1r,A,0,0},   /* getr.w */
+  {106,8,a1r,S,0,0},   /* getr.l */
+  {26,13,a2r,S,0,0},   /* ste.b.f */
+  {26,14,a2r,S,0,0},   /* ste.h.f */
+  {26,15,a2r,S,0,0},   /* ste.w.f */
+  {26,16,a2r,S,0,0},   /* ste.l.f */
+  {107,7,a2r,A,0,0},   /* matr.w */
+  {108,7,a2r,A,0,0},   /* mat.w */
+  {109,7,a1r,A,0,0},   /* get.w */
+  {110,7,a1r,A,0,0},   /* rcv.w */
+  {0,0,0,0,0,0},
+  {111,7,a1r,A,0,0},   /* inc.w */
+  {112,7,a2r,A,0,0},   /* put.w */
+  {113,7,a2r,A,0,0},   /* snd.w */
+  {107,8,a2r,S,0,0},   /* matr.l */
+  {108,8,a2r,S,0,0},   /* mat.l */
+  {109,8,a1r,S,0,0},   /* get.l */
+  {110,8,a1r,S,0,0},   /* rcv.l */
+  {0,0,0,0,0,0},
+  {111,8,a1r,S,0,0},   /* inc.l */
+  {112,8,a2r,S,0,0},   /* put.l */
+  {113,8,a2r,S,0,0},   /* snd.l */
+  {18,13,a1r,V,0,0},   /* ld.b.f */
+  {18,14,a1r,V,0,0},   /* ld.h.f */
+  {18,15,a1r,V,0,0},   /* ld.w.f */
+  {18,16,a1r,V,0,0},   /* ld.l.f */
+  {21,13,a2r,V,0,0},   /* st.b.f */
+  {21,14,a2r,V,0,0},   /* st.h.f */
+  {21,15,a2r,V,0,0},   /* st.w.f */
+  {21,16,a2r,V,0,0},   /* st.l.f */
+};
+struct formstr e0_format2[] = {
+  {28,5,rr,V,V,0},     /* cvtw.b */
+  {28,6,rr,V,V,0},     /* cvtw.h */
+  {29,7,rr,V,V,0},     /* cvtb.w */
+  {30,7,rr,V,V,0},     /* cvth.w */
+  {28,13,rr,V,V,0},    /* cvtw.b.f */
+  {28,14,rr,V,V,0},    /* cvtw.h.f */
+  {29,15,rr,V,V,0},    /* cvtb.w.f */
+  {30,15,rr,V,V,0},    /* cvth.w.f */
+  {31,8,rr,V,V,0},     /* cvts.l */
+  {32,7,rr,V,V,0},     /* cvtd.w */
+  {33,3,rr,V,V,0},     /* cvtl.s */
+  {28,4,rr,V,V,0},     /* cvtw.d */
+  {31,16,rr,V,V,0},    /* cvts.l.f */
+  {32,15,rr,V,V,0},    /* cvtd.w.f */
+  {33,11,rr,V,V,0},    /* cvtl.s.f */
+  {28,12,rr,V,V,0},    /* cvtw.d.f */
+  {114,0,rr,S,S,0},    /* enal */
+  {8,7,rr,S,S,0},      /* shf.w */
+  {115,0,rr,S,S,0},    /* enag */
+  {0,0,0,0,0,0},
+  {28,4,rr,S,S,0},     /* cvtw.d */
+  {32,7,rr,S,S,0},     /* cvtd.w */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,3,rr,S,S,0},    /* frint.s */
+  {116,4,rr,S,S,0},    /* frint.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,3,rr,V,V,0},    /* frint.s */
+  {116,4,rr,V,V,0},    /* frint.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,11,rr,V,V,0},   /* frint.s.f */
+  {116,12,rr,V,V,0},   /* frint.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,3,rr,V,V,0},     /* sqrt.s */
+  {81,4,rr,V,V,0},     /* sqrt.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,11,rr,V,V,0},    /* sqrt.s.f */
+  {81,12,rr,V,V,0},    /* sqrt.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format3[] = {
+  {32,11,rr,V,V,0},    /* cvtd.s.f */
+  {31,12,rr,V,V,0},    /* cvts.d.f */
+  {33,12,rr,V,V,0},    /* cvtl.d.f */
+  {32,16,rr,V,V,0},    /* cvtd.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {36,2,rr,V,V,0},     /* tzc.f */
+  {44,2,rr,V,V,0},     /* lop.f */
+  {117,2,rr,V,V,0},    /* xpnd.f */
+  {42,2,rr,V,V,0},     /* not.f */
+  {8,2,rr,S,V,0},      /* shf.f */
+  {35,17,rr,V,V,0},    /* plc.t.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {37,11,rr,V,V,0},    /* eq.s.f */
+  {37,12,rr,V,V,0},    /* eq.d.f */
+  {43,11,rr,V,V,0},    /* neg.s.f */
+  {43,12,rr,V,V,0},    /* neg.d.f */
+  {37,11,rr,S,V,0},    /* eq.s.f */
+  {37,12,rr,S,V,0},    /* eq.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {40,11,rr,V,V,0},    /* le.s.f */
+  {40,12,rr,V,V,0},    /* le.d.f */
+  {41,11,rr,V,V,0},    /* lt.s.f */
+  {41,12,rr,V,V,0},    /* lt.d.f */
+  {40,11,rr,S,V,0},    /* le.s.f */
+  {40,12,rr,S,V,0},    /* le.d.f */
+  {41,11,rr,S,V,0},    /* lt.s.f */
+  {41,12,rr,S,V,0},    /* lt.d.f */
+  {37,13,rr,V,V,0},    /* eq.b.f */
+  {37,14,rr,V,V,0},    /* eq.h.f */
+  {37,15,rr,V,V,0},    /* eq.w.f */
+  {37,16,rr,V,V,0},    /* eq.l.f */
+  {37,13,rr,S,V,0},    /* eq.b.f */
+  {37,14,rr,S,V,0},    /* eq.h.f */
+  {37,15,rr,S,V,0},    /* eq.w.f */
+  {37,16,rr,S,V,0},    /* eq.l.f */
+  {40,13,rr,V,V,0},    /* le.b.f */
+  {40,14,rr,V,V,0},    /* le.h.f */
+  {40,15,rr,V,V,0},    /* le.w.f */
+  {40,16,rr,V,V,0},    /* le.l.f */
+  {40,13,rr,S,V,0},    /* le.b.f */
+  {40,14,rr,S,V,0},    /* le.h.f */
+  {40,15,rr,S,V,0},    /* le.w.f */
+  {40,16,rr,S,V,0},    /* le.l.f */
+  {41,13,rr,V,V,0},    /* lt.b.f */
+  {41,14,rr,V,V,0},    /* lt.h.f */
+  {41,15,rr,V,V,0},    /* lt.w.f */
+  {41,16,rr,V,V,0},    /* lt.l.f */
+  {41,13,rr,S,V,0},    /* lt.b.f */
+  {41,14,rr,S,V,0},    /* lt.h.f */
+  {41,15,rr,S,V,0},    /* lt.w.f */
+  {41,16,rr,S,V,0},    /* lt.l.f */
+  {43,13,rr,V,V,0},    /* neg.b.f */
+  {43,14,rr,V,V,0},    /* neg.h.f */
+  {43,15,rr,V,V,0},    /* neg.w.f */
+  {43,16,rr,V,V,0},    /* neg.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format4[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format5[] = {
+  {51,13,rr,V,V,0},    /* ldvi.b.f */
+  {51,14,rr,V,V,0},    /* ldvi.h.f */
+  {51,15,rr,V,V,0},    /* ldvi.w.f */
+  {51,16,rr,V,V,0},    /* ldvi.l.f */
+  {28,11,rr,V,V,0},    /* cvtw.s.f */
+  {31,15,rr,V,V,0},    /* cvts.w.f */
+  {28,16,rr,V,V,0},    /* cvtw.l.f */
+  {33,15,rr,V,V,0},    /* cvtl.w.f */
+  {52,13,rxr,V,V,0},   /* stvi.b.f */
+  {52,14,rxr,V,V,0},   /* stvi.h.f */
+  {52,15,rxr,V,V,0},   /* stvi.w.f */
+  {52,16,rxr,V,V,0},   /* stvi.l.f */
+  {52,13,rxr,S,V,0},   /* stvi.b.f */
+  {52,14,rxr,S,V,0},   /* stvi.h.f */
+  {52,15,rxr,S,V,0},   /* stvi.w.f */
+  {52,16,rxr,S,V,0},   /* stvi.l.f */
+};
+struct formstr e0_format6[] = {
+  {0,0,rxl,S,CIR,0},   /* mov */
+  {0,0,lr,CIR,S,0},    /* mov */
+  {0,0,lr,TOC,S,0},    /* mov */
+  {0,0,lr,CPUID,S,0},  /* mov */
+  {0,0,rxl,S,TTR,0},   /* mov */
+  {0,0,lr,TTR,S,0},    /* mov */
+  {118,0,nops,0,0,0},  /* ctrsl */
+  {119,0,nops,0,0,0},  /* ctrsg */
+  {0,0,rxl,S,VMU,0},   /* mov */
+  {0,0,lr,VMU,S,0},    /* mov */
+  {0,0,rxl,S,VML,0},   /* mov */
+  {0,0,lr,VML,S,0},    /* mov */
+  {0,0,rxl,S,ICR,0},   /* mov */
+  {0,0,lr,ICR,S,0},    /* mov */
+  {0,0,rxl,S,TCPU,0},  /* mov */
+  {0,0,lr,TCPU,S,0},   /* mov */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {120,0,nops,0,0,0},  /* stop */
+  {0,0,0,0,0,0},
+  {0,0,rxl,S,TID,0},   /* mov */
+  {0,0,lr,TID,S,0},    /* mov */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format7[] = {
+  {84,13,r,V,0,0},     /* sum.b.f */
+  {84,14,r,V,0,0},     /* sum.h.f */
+  {84,15,r,V,0,0},     /* sum.w.f */
+  {84,16,r,V,0,0},     /* sum.l.f */
+  {85,2,r,V,0,0},      /* all.f */
+  {86,2,r,V,0,0},      /* any.f */
+  {87,2,r,V,0,0},      /* parity.f */
+  {0,0,0,0,0,0},
+  {88,13,r,V,0,0},     /* max.b.f */
+  {88,14,r,V,0,0},     /* max.h.f */
+  {88,15,r,V,0,0},     /* max.w.f */
+  {88,16,r,V,0,0},     /* max.l.f */
+  {89,13,r,V,0,0},     /* min.b.f */
+  {89,14,r,V,0,0},     /* min.h.f */
+  {89,15,r,V,0,0},     /* min.w.f */
+  {89,16,r,V,0,0},     /* min.l.f */
+  {84,11,r,V,0,0},     /* sum.s.f */
+  {84,12,r,V,0,0},     /* sum.d.f */
+  {90,11,r,V,0,0},     /* prod.s.f */
+  {90,12,r,V,0,0},     /* prod.d.f */
+  {88,11,r,V,0,0},     /* max.s.f */
+  {88,12,r,V,0,0},     /* max.d.f */
+  {89,11,r,V,0,0},     /* min.s.f */
+  {89,12,r,V,0,0},     /* min.d.f */
+  {90,13,r,V,0,0},     /* prod.b.f */
+  {90,14,r,V,0,0},     /* prod.h.f */
+  {90,15,r,V,0,0},     /* prod.w.f */
+  {90,16,r,V,0,0},     /* prod.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format0[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {10,18,rrr,S,V,V},   /* sub.s.t */
+  {10,19,rrr,S,V,V},   /* sub.d.t */
+  {4,18,rrr,S,V,V},    /* div.s.t */
+  {4,19,rrr,S,V,V},    /* div.d.t */
+  {3,18,rrr,V,V,V},    /* mul.s.t */
+  {3,19,rrr,V,V,V},    /* mul.d.t */
+  {4,18,rrr,V,V,V},    /* div.s.t */
+  {4,19,rrr,V,V,V},    /* div.d.t */
+  {3,18,rrr,V,S,V},    /* mul.s.t */
+  {3,19,rrr,V,S,V},    /* mul.d.t */
+  {4,18,rrr,V,S,V},    /* div.s.t */
+  {4,19,rrr,V,S,V},    /* div.d.t */
+  {5,1,rrr,V,V,V},     /* and.t */
+  {6,1,rrr,V,V,V},     /* or.t */
+  {7,1,rrr,V,V,V},     /* xor.t */
+  {8,1,rrr,V,V,V},     /* shf.t */
+  {5,1,rrr,V,S,V},     /* and.t */
+  {6,1,rrr,V,S,V},     /* or.t */
+  {7,1,rrr,V,S,V},     /* xor.t */
+  {8,1,rrr,V,S,V},     /* shf.t */
+  {9,18,rrr,V,V,V},    /* add.s.t */
+  {9,19,rrr,V,V,V},    /* add.d.t */
+  {10,18,rrr,V,V,V},   /* sub.s.t */
+  {10,19,rrr,V,V,V},   /* sub.d.t */
+  {9,18,rrr,V,S,V},    /* add.s.t */
+  {9,19,rrr,V,S,V},    /* add.d.t */
+  {10,18,rrr,V,S,V},   /* sub.s.t */
+  {10,19,rrr,V,S,V},   /* sub.d.t */
+  {9,20,rrr,V,V,V},    /* add.b.t */
+  {9,21,rrr,V,V,V},    /* add.h.t */
+  {9,22,rrr,V,V,V},    /* add.w.t */
+  {9,23,rrr,V,V,V},    /* add.l.t */
+  {9,20,rrr,V,S,V},    /* add.b.t */
+  {9,21,rrr,V,S,V},    /* add.h.t */
+  {9,22,rrr,V,S,V},    /* add.w.t */
+  {9,23,rrr,V,S,V},    /* add.l.t */
+  {10,20,rrr,V,V,V},   /* sub.b.t */
+  {10,21,rrr,V,V,V},   /* sub.h.t */
+  {10,22,rrr,V,V,V},   /* sub.w.t */
+  {10,23,rrr,V,V,V},   /* sub.l.t */
+  {10,20,rrr,V,S,V},   /* sub.b.t */
+  {10,21,rrr,V,S,V},   /* sub.h.t */
+  {10,22,rrr,V,S,V},   /* sub.w.t */
+  {10,23,rrr,V,S,V},   /* sub.l.t */
+  {3,20,rrr,V,V,V},    /* mul.b.t */
+  {3,21,rrr,V,V,V},    /* mul.h.t */
+  {3,22,rrr,V,V,V},    /* mul.w.t */
+  {3,23,rrr,V,V,V},    /* mul.l.t */
+  {3,20,rrr,V,S,V},    /* mul.b.t */
+  {3,21,rrr,V,S,V},    /* mul.h.t */
+  {3,22,rrr,V,S,V},    /* mul.w.t */
+  {3,23,rrr,V,S,V},    /* mul.l.t */
+  {4,20,rrr,V,V,V},    /* div.b.t */
+  {4,21,rrr,V,V,V},    /* div.h.t */
+  {4,22,rrr,V,V,V},    /* div.w.t */
+  {4,23,rrr,V,V,V},    /* div.l.t */
+  {4,20,rrr,V,S,V},    /* div.b.t */
+  {4,21,rrr,V,S,V},    /* div.h.t */
+  {4,22,rrr,V,S,V},    /* div.w.t */
+  {4,23,rrr,V,S,V},    /* div.l.t */
+};
+struct formstr e1_format1[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {26,20,a2r,S,0,0},   /* ste.b.t */
+  {26,21,a2r,S,0,0},   /* ste.h.t */
+  {26,22,a2r,S,0,0},   /* ste.w.t */
+  {26,23,a2r,S,0,0},   /* ste.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {18,20,a1r,V,0,0},   /* ld.b.t */
+  {18,21,a1r,V,0,0},   /* ld.h.t */
+  {18,22,a1r,V,0,0},   /* ld.w.t */
+  {18,23,a1r,V,0,0},   /* ld.l.t */
+  {21,20,a2r,V,0,0},   /* st.b.t */
+  {21,21,a2r,V,0,0},   /* st.h.t */
+  {21,22,a2r,V,0,0},   /* st.w.t */
+  {21,23,a2r,V,0,0},   /* st.l.t */
+};
+struct formstr e1_format2[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {28,20,rr,V,V,0},    /* cvtw.b.t */
+  {28,21,rr,V,V,0},    /* cvtw.h.t */
+  {29,22,rr,V,V,0},    /* cvtb.w.t */
+  {30,22,rr,V,V,0},    /* cvth.w.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {31,23,rr,V,V,0},    /* cvts.l.t */
+  {32,22,rr,V,V,0},    /* cvtd.w.t */
+  {33,18,rr,V,V,0},    /* cvtl.s.t */
+  {28,19,rr,V,V,0},    /* cvtw.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,18,rr,V,V,0},   /* frint.s.t */
+  {116,19,rr,V,V,0},   /* frint.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,18,rr,V,V,0},    /* sqrt.s.t */
+  {81,19,rr,V,V,0},    /* sqrt.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format3[] = {
+  {32,18,rr,V,V,0},    /* cvtd.s.t */
+  {31,19,rr,V,V,0},    /* cvts.d.t */
+  {33,19,rr,V,V,0},    /* cvtl.d.t */
+  {32,23,rr,V,V,0},    /* cvtd.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {36,1,rr,V,V,0},     /* tzc.t */
+  {44,1,rr,V,V,0},     /* lop.t */
+  {117,1,rr,V,V,0},    /* xpnd.t */
+  {42,1,rr,V,V,0},     /* not.t */
+  {8,1,rr,S,V,0},      /* shf.t */
+  {35,24,rr,V,V,0},    /* plc.t.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {37,18,rr,V,V,0},    /* eq.s.t */
+  {37,19,rr,V,V,0},    /* eq.d.t */
+  {43,18,rr,V,V,0},    /* neg.s.t */
+  {43,19,rr,V,V,0},    /* neg.d.t */
+  {37,18,rr,S,V,0},    /* eq.s.t */
+  {37,19,rr,S,V,0},    /* eq.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {40,18,rr,V,V,0},    /* le.s.t */
+  {40,19,rr,V,V,0},    /* le.d.t */
+  {41,18,rr,V,V,0},    /* lt.s.t */
+  {41,19,rr,V,V,0},    /* lt.d.t */
+  {40,18,rr,S,V,0},    /* le.s.t */
+  {40,19,rr,S,V,0},    /* le.d.t */
+  {41,18,rr,S,V,0},    /* lt.s.t */
+  {41,19,rr,S,V,0},    /* lt.d.t */
+  {37,20,rr,V,V,0},    /* eq.b.t */
+  {37,21,rr,V,V,0},    /* eq.h.t */
+  {37,22,rr,V,V,0},    /* eq.w.t */
+  {37,23,rr,V,V,0},    /* eq.l.t */
+  {37,20,rr,S,V,0},    /* eq.b.t */
+  {37,21,rr,S,V,0},    /* eq.h.t */
+  {37,22,rr,S,V,0},    /* eq.w.t */
+  {37,23,rr,S,V,0},    /* eq.l.t */
+  {40,20,rr,V,V,0},    /* le.b.t */
+  {40,21,rr,V,V,0},    /* le.h.t */
+  {40,22,rr,V,V,0},    /* le.w.t */
+  {40,23,rr,V,V,0},    /* le.l.t */
+  {40,20,rr,S,V,0},    /* le.b.t */
+  {40,21,rr,S,V,0},    /* le.h.t */
+  {40,22,rr,S,V,0},    /* le.w.t */
+  {40,23,rr,S,V,0},    /* le.l.t */
+  {41,20,rr,V,V,0},    /* lt.b.t */
+  {41,21,rr,V,V,0},    /* lt.h.t */
+  {41,22,rr,V,V,0},    /* lt.w.t */
+  {41,23,rr,V,V,0},    /* lt.l.t */
+  {41,20,rr,S,V,0},    /* lt.b.t */
+  {41,21,rr,S,V,0},    /* lt.h.t */
+  {41,22,rr,S,V,0},    /* lt.w.t */
+  {41,23,rr,S,V,0},    /* lt.l.t */
+  {43,20,rr,V,V,0},    /* neg.b.t */
+  {43,21,rr,V,V,0},    /* neg.h.t */
+  {43,22,rr,V,V,0},    /* neg.w.t */
+  {43,23,rr,V,V,0},    /* neg.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format4[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format5[] = {
+  {51,20,rr,V,V,0},    /* ldvi.b.t */
+  {51,21,rr,V,V,0},    /* ldvi.h.t */
+  {51,22,rr,V,V,0},    /* ldvi.w.t */
+  {51,23,rr,V,V,0},    /* ldvi.l.t */
+  {28,18,rr,V,V,0},    /* cvtw.s.t */
+  {31,22,rr,V,V,0},    /* cvts.w.t */
+  {28,23,rr,V,V,0},    /* cvtw.l.t */
+  {33,22,rr,V,V,0},    /* cvtl.w.t */
+  {52,20,rxr,V,V,0},   /* stvi.b.t */
+  {52,21,rxr,V,V,0},   /* stvi.h.t */
+  {52,22,rxr,V,V,0},   /* stvi.w.t */
+  {52,23,rxr,V,V,0},   /* stvi.l.t */
+  {52,20,rxr,S,V,0},   /* stvi.b.t */
+  {52,21,rxr,S,V,0},   /* stvi.h.t */
+  {52,22,rxr,S,V,0},   /* stvi.w.t */
+  {52,23,rxr,S,V,0},   /* stvi.l.t */
+};
+struct formstr e1_format6[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format7[] = {
+  {84,20,r,V,0,0},     /* sum.b.t */
+  {84,21,r,V,0,0},     /* sum.h.t */
+  {84,22,r,V,0,0},     /* sum.w.t */
+  {84,23,r,V,0,0},     /* sum.l.t */
+  {85,1,r,V,0,0},      /* all.t */
+  {86,1,r,V,0,0},      /* any.t */
+  {87,1,r,V,0,0},      /* parity.t */
+  {0,0,0,0,0,0},
+  {88,20,r,V,0,0},     /* max.b.t */
+  {88,21,r,V,0,0},     /* max.h.t */
+  {88,22,r,V,0,0},     /* max.w.t */
+  {88,23,r,V,0,0},     /* max.l.t */
+  {89,20,r,V,0,0},     /* min.b.t */
+  {89,21,r,V,0,0},     /* min.h.t */
+  {89,22,r,V,0,0},     /* min.w.t */
+  {89,23,r,V,0,0},     /* min.l.t */
+  {84,18,r,V,0,0},     /* sum.s.t */
+  {84,19,r,V,0,0},     /* sum.d.t */
+  {90,18,r,V,0,0},     /* prod.s.t */
+  {90,19,r,V,0,0},     /* prod.d.t */
+  {88,18,r,V,0,0},     /* max.s.t */
+  {88,19,r,V,0,0},     /* max.d.t */
+  {89,18,r,V,0,0},     /* min.s.t */
+  {89,19,r,V,0,0},     /* min.d.t */
+  {90,20,r,V,0,0},     /* prod.b.t */
+  {90,21,r,V,0,0},     /* prod.h.t */
+  {90,22,r,V,0,0},     /* prod.w.t */
+  {90,23,r,V,0,0},     /* prod.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+char *lop[] = {
+  "mov",       /* 0 */
+  "merg",      /* 1 */
+  "mask",      /* 2 */
+  "mul",       /* 3 */
+  "div",       /* 4 */
+  "and",       /* 5 */
+  "or",        /* 6 */
+  "xor",       /* 7 */
+  "shf",       /* 8 */
+  "add",       /* 9 */
+  "sub",       /* 10 */
+  "exit",      /* 11 */
+  "jmp",       /* 12 */
+  "jmpi",      /* 13 */
+  "jmpa",      /* 14 */
+  "jmps",      /* 15 */
+  "tac",       /* 16 */
+  "ldea",      /* 17 */
+  "ld",        /* 18 */
+  "tas",       /* 19 */
+  "pshea",     /* 20 */
+  "st",        /* 21 */
+  "call",      /* 22 */
+  "calls",     /* 23 */
+  "callq",     /* 24 */
+  "pfork",     /* 25 */
+  "ste",       /* 26 */
+  "incr",      /* 27 */
+  "cvtw",      /* 28 */
+  "cvtb",      /* 29 */
+  "cvth",      /* 30 */
+  "cvts",      /* 31 */
+  "cvtd",      /* 32 */
+  "cvtl",      /* 33 */
+  "ldpa",      /* 34 */
+  "plc",       /* 35 */
+  "tzc",       /* 36 */
+  "eq",        /* 37 */
+  "leu",       /* 38 */
+  "ltu",       /* 39 */
+  "le",        /* 40 */
+  "lt",        /* 41 */
+  "not",       /* 42 */
+  "neg",       /* 43 */
+  "lop",       /* 44 */
+  "cprs",      /* 45 */
+  "nop",       /* 46 */
+  "br",        /* 47 */
+  "bri",       /* 48 */
+  "bra",       /* 49 */
+  "brs",       /* 50 */
+  "ldvi",      /* 51 */
+  "stvi",      /* 52 */
+  "ldsdr",     /* 53 */
+  "ldkdr",     /* 54 */
+  "ln",        /* 55 */
+  "patu",      /* 56 */
+  "pate",      /* 57 */
+  "pich",      /* 58 */
+  "plch",      /* 59 */
+  "idle",      /* 60 */
+  "rtnq",      /* 61 */
+  "cfork",     /* 62 */
+  "rtn",       /* 63 */
+  "wfork",     /* 64 */
+  "join",      /* 65 */
+  "rtnc",      /* 66 */
+  "exp",       /* 67 */
+  "sin",       /* 68 */
+  "cos",       /* 69 */
+  "psh",       /* 70 */
+  "pop",       /* 71 */
+  "eni",       /* 72 */
+  "dsi",       /* 73 */
+  "bkpt",      /* 74 */
+  "msync",     /* 75 */
+  "mski",      /* 76 */
+  "xmti",      /* 77 */
+  "tstvv",     /* 78 */
+  "diag",      /* 79 */
+  "pbkpt",     /* 80 */
+  "sqrt",      /* 81 */
+  "casr",      /* 82 */
+  "atan",      /* 83 */
+  "sum",       /* 84 */
+  "all",       /* 85 */
+  "any",       /* 86 */
+  "parity",    /* 87 */
+  "max",       /* 88 */
+  "min",       /* 89 */
+  "prod",      /* 90 */
+  "halt",      /* 91 */
+  "sysc",      /* 92 */
+  "trap",      /* 93 */
+  "tst",       /* 94 */
+  "lck",       /* 95 */
+  "ulk",       /* 96 */
+  "spawn",     /* 97 */
+  "ldcmr",     /* 98 */
+  "stcmr",     /* 99 */
+  "popr",      /* 100 */
+  "pshr",      /* 101 */
+  "rcvr",      /* 102 */
+  "matm",      /* 103 */
+  "sndr",      /* 104 */
+  "putr",      /* 105 */
+  "getr",      /* 106 */
+  "matr",      /* 107 */
+  "mat",       /* 108 */
+  "get",       /* 109 */
+  "rcv",       /* 110 */
+  "inc",       /* 111 */
+  "put",       /* 112 */
+  "snd",       /* 113 */
+  "enal",      /* 114 */
+  "enag",      /* 115 */
+  "frint",     /* 116 */
+  "xpnd",      /* 117 */
+  "ctrsl",     /* 118 */
+  "ctrsg",     /* 119 */
+  "stop",      /* 120 */
+};
+char *rop[] = {
+  "",  /* 0 */
+  ".t",        /* 1 */
+  ".f",        /* 2 */
+  ".s",        /* 3 */
+  ".d",        /* 4 */
+  ".b",        /* 5 */
+  ".h",        /* 6 */
+  ".w",        /* 7 */
+  ".l",        /* 8 */
+  ".x",        /* 9 */
+  ".u",        /* 10 */
+  ".s.f",      /* 11 */
+  ".d.f",      /* 12 */
+  ".b.f",      /* 13 */
+  ".h.f",      /* 14 */
+  ".w.f",      /* 15 */
+  ".l.f",      /* 16 */
+  ".t.f",      /* 17 */
+  ".s.t",      /* 18 */
+  ".d.t",      /* 19 */
+  ".b.t",      /* 20 */
+  ".h.t",      /* 21 */
+  ".w.t",      /* 22 */
+  ".l.t",      /* 23 */
+  ".t.t",      /* 24 */
+};
diff --git a/gdb/doc/all.m4 b/gdb/doc/all.m4
new file mode 100644 (file)
index 0000000..4d97fbe
--- /dev/null
@@ -0,0 +1,18 @@
+_divert__(-1)
+_define__(<_ALL_ARCH__>,<1>)
+_define__(<_GENERIC__>,<1>)    In case none.m4 changes its mind abt default
+
+_define__(<_AOUT__>,<1>)
+_define__(<_BOUT__>,<1>)
+_define__(<_COFF__>,<1>)
+_define__(<_ELF__>,<1>)
+
+_define__(<_AMD29K__>,<1>)
+_define__(<_I80386__>,<1>)
+_define__(<_I960__>,<1>)
+_define__(<_M680X0__>,<1>)
+_define__(<_SPARC__>,<1>)
+_define__(<_VAX__>,<1>)
+_define__(<_VXWORKS__>,<1>)
+
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/amd29k.m4 b/gdb/doc/amd29k.m4
new file mode 100644 (file)
index 0000000..cf3ba38
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_AMD29K__>,<1>)
+_define__(<_HOST__>,<AMD 29K>)
+_define__(<_MACH_DEP__>,<AMD29K Dependent>
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/gen.m4 b/gdb/doc/gen.m4
new file mode 100644 (file)
index 0000000..be995bf
--- /dev/null
@@ -0,0 +1,13 @@
+_divert__(-1)
+_define__(<_GENERIC__>,<1>)    In case none.m4 changes its mind abt default
+
+_define__(<_AOUT__>,<1>)
+_define__(<_COFF__>,<1>)
+_define__(<_ELF__>,<1>)
+
+_define__(<_I80386__>,<1>)
+_define__(<_M680X0__>,<1>)
+_define__(<_SPARC__>,<1>)
+_define__(<_VAX__>,<1>)
+
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/i80386.m4 b/gdb/doc/i80386.m4
new file mode 100644 (file)
index 0000000..d8293d1
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_I80386__>,<1>)
+_define__(<_HOST__>,<Intel 80386>)
+_define__(<_MACH_DEP__>,<80386 Dependent>
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/i960.m4 b/gdb/doc/i960.m4
new file mode 100644 (file)
index 0000000..e98155d
--- /dev/null
@@ -0,0 +1,12 @@
+_divert__(-1)
+_define__(<_I960__>,<1>)
+_define__(<_AOUT__>,<0>)
+_define__(<_BOUT__>,<1>)
+_define__(<_COFF__>,<1>)
+_define__(<_AS__>,<gas960>)
+_define__(<_GCC__>,<gcc960>)
+_define__(<_LD__>,<gld960>)
+_define__(<_GDB__>,<gdb960>)
+_define__(<_HOST__>,<Intel 960>)
+_define__(<_MACH_DEP__>,<i960 Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/m680x0.m4 b/gdb/doc/m680x0.m4
new file mode 100644 (file)
index 0000000..e5f83b6
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_M680X0__>,<1>)
+_define__(<_HOST__>,<Motorola 680x0>)
+_define__(<_MACH_DEP__>,<M680x0 Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/none.m4 b/gdb/doc/none.m4
new file mode 100644 (file)
index 0000000..940245c
--- /dev/null
@@ -0,0 +1,49 @@
+_divert__(-1)
+
+Switches:
+
+_define__(<_ALL_ARCH__>,<0>)           (Meant as most inclusive; file turning 
+                                       it on is expected to also turn on
+                                       all arch-related switches including
+                                       "_GENERIC__")
+_define__(<_GENERIC__>,<1>)            (may not be quite all configs; 
+                                       meant for "most vanilla" manual)
+_define__(<_INTERNALS__>,<0>)
+
+_define__(<_AOUT__>,<1>)               Object formats.  Note we turn on one.
+_define__(<_BOUT__>,<0>)
+_define__(<_COFF__>,<0>)
+_define__(<_ELF__>,<0>)
+
+_define__(<_AMD29K__>,<0>)             Specific architectures.  Note none
+_define__(<_I80386__>,<0>)             starts out on.
+_define__(<_I960__>,<0>)
+_define__(<_M680X0__>,<0>)
+_define__(<_SPARC__>,<0>)
+_define__(<_VAX__>,<0>)
+_define__(<_VXWORKS__>,<0>)
+
+Text:
+
+Default names; individual configs may override
+Assembler:
+_define__(<_AS__>,<as>)
+C Compiler:
+_define__(<_GCC__>,<gcc>)
+Linker:
+_define__(<_LD__>,<ld>)
+Debugger name:
+_define__(<_GDBN__>,<GDB>)
+Debugger program:
+_define__(<_GDBP__>,<gdb>)
+Debugger init file:
+_define__(<_GDBINIT__>,<.gdbinit>)
+
+Text for host; individual configs *should* override, but this may
+catch some flubs
+_define__(<_HOST__>,<machine specific>)
+
+"Machine Dependent" nodename
+_define__(<_MACH_DEP__>,<Machine Dependent>)
+
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/pretex.m4 b/gdb/doc/pretex.m4
new file mode 100644 (file)
index 0000000..3fe9e05
--- /dev/null
@@ -0,0 +1,252 @@
+divert(-1)                             -*-Text-*-
+
+I. INTRODUCTION
+
+This collection of M4 macros is meant to help in pre-processing texinfo
+files to allow configuring them by hosts; for example, the reader of an
+as manual who only has access to a 386 may not really want to see crud about 
+VAXen. 
+
+A preprocessor is used, rather than extending texinfo, because this
+way we can hack the conditionals in only one place; otherwise we would
+have to write TeX macros, update makeinfo, and update the Emacs
+info-formatting functions.
+
+II. COMPATIBILITY
+
+These macros should work with GNU m4 and System V m4; they do not work
+with Sun or Berkeley M4.
+
+III. USAGE
+
+A. M4 INVOCATION
+Assume this file is called "pretex.m4".  Then, to preprocess a
+document "mybook.texinfo" you might do something like the following:
+
+       m4 pretex.m4 none.m4 PARTIC.m4 mybook.texinfo >mybook-PARTIC.texinfo
+
+---where your path is set to find GNU or SysV "m4", and the other m4
+files mentioned are as follows:
+
+       none.m4: A file that defines, as 0, all the options you might
+               want to turn on using the conditionals defined below.
+               Unlike the C preprocessor, m4 does not default
+               undefined macros to 0.  For example, here is a "none.m4"
+               I have been using:
+           _divert__(-1)
+
+           _define__(<_ALL_ARCH__>,<0>)
+           _define__(<_INTERNALS__>,<0>)
+
+           _define__(<_AMD29K__>,<0>)
+           _define__(<_I80386__>,<0>)
+           _define__(<_I960__>,<0>)
+           _define__(<_M680X0__>,<0>)
+           _define__(<_SPARC__>,<0>)
+           _define__(<_VAX__>,<0>)
+
+           _divert__<>
+
+       PARTIC.m4: A file that turns on whichever options you actually
+               want the manual configured for, in this particular
+               instance.  Its contents are similar to one or more of
+               the lines in "none.m4", but of course the second
+               argument to _define__ is <1> rather than <0>.
+
+               This is also a convenient place to define any macros
+               that you want to expand to different text for
+               different configurations---for example, the name of
+               the program being described.
+
+Naturally, these are just suggested conventions; you could put your macro
+definitions in any files or combinations of files you like.
+
+These macros use the characters < and > as m4 quotes; if you need
+these characters in your text, you will also want to use the macros
+_0__ and _1__ from this package---see the description of "Quote
+Handling" in the "Implementation" section below.
+
+B. WHAT GOES IN THE PRE-TEXINFO SOURCE
+
+For the most part, the text of your book.  In addition, you can
+include text that is included only conditionally, using the macros
+_if__ and _fi__ defined below.  They BOTH take an argument!  This is
+primarily meant for readability (so a human can more easily see what
+conditional end matches what conditional beginning), but the argument
+is actually used in the _fi__ as well as the _if__ implementation.
+You should always give a _fi__ the same argument as its matching
+_if__.  Other arguments may appear to work for a while, but are almost
+certain to produce the wrong output for some configurations.
+
+For example, here is an excerpt from the very beginning of the
+documentation for GNU as, to name the info file appropriately for
+different configurations:
+    _if__(_ALL_ARCH__)
+    @setfilename as.info
+    _fi__(_ALL_ARCH__)
+    _if__(_M680X0__ && !_ALL_ARCH__)
+    @setfilename as-m680x0.info
+    _fi__(_M680X0__ && !_ALL_ARCH__)
+    _if__(_AMD29K__ && !_ALL_ARCH__)
+    @setfilename as-29k.info
+    _fi__(_AMD29K__ && !_ALL_ARCH__) 
+
+Note that you can use Boolean expressions in the arguments; the
+expression language is that of the builtin m4 macro "eval", described
+in the m4 manual.
+
+IV. IMPLEMENTATION
+
+A.PRIMITIVE RENAMING
+First, we redefine m4's built-ins to avoid conflict with plain text.
+The naming convention used is that our macros all begin with a single
+underbar and end with two underbars.  The asymmetry is meant to avoid
+conflict with some other conventions (which we may want to document) that
+are intended to avoid conflict, like ANSI C predefined macros.
+
+define(`_undefine__',defn(`undefine'))
+define(`_define__',defn(`define'))
+define(`_defn__',defn(`defn'))
+define(`_ppf__',`_define__(`_$1__',_defn__(`$1'))_undefine__(`$1')')
+_ppf__(`builtin')
+_ppf__(`changecom')
+_ppf__(`changequote')
+_ppf__(`decr')
+_ppf__(`define')
+_ppf__(`defn')
+_ppf__(`divert')
+_ppf__(`dnl')
+_ppf__(`dumpdef')
+_ppf__(`errprint')
+_ppf__(`eval')
+_ppf__(`ifdef')
+_ppf__(`ifelse')
+_ppf__(`include')
+_ppf__(`incr')
+_ppf__(`index')
+_ppf__(`len')
+_ppf__(`m4exit')
+_ppf__(`m4wrap')
+_ppf__(`maketemp')
+_ppf__(`popdef')
+_ppf__(`pushdef')
+_ppf__(`shift')
+_ppf__(`sinclude')
+_ppf__(`substr')
+_ppf__(`syscmd')
+_ppf__(`sysval')
+_ppf__(`traceoff')
+_ppf__(`traceon')
+_ppf__(`translit')
+_ppf__(`undefine')
+_ppf__(`undivert')
+
+B. QUOTE HANDLING.
+
+The characters used as quotes by M4, by default, are unfortunately
+quite likely to occur in ordinary text.  To avoid surprises, we will
+use the characters <> ---which are just as suggestive (more so to
+Francophones, perhaps) but a little less common in text (save for
+those poor Francophones.  You win some, you lose some).  Still, we
+expect also to have to set < and > occasionally in text; to do that,
+we define a macro to turn off quote handling (_0__) and a macro to
+turn it back on (_1__), according to our convention.  
+
+       BEWARE: This seems to make < and > unusable as relational operations
+               in calls to the builtin "eval".  So far I've gotten
+               along without; but a better choice may be possible.
+
+Note that we postponed this for a while, for convenience in discussing
+the issue and in the primitive renaming---not to mention in defining
+_0__ and _1__ themselves!  However, the quote redefinitions MUST
+precede the _if__ / _fi__ definitions, because M4 will expand the text
+as given---if we use the wrong quotes here, we will get the wrong
+quotes when we use the conditionals.
+
+_define__(_0__,`_changequote__(\ 1,\ 2)')_define__(_1__,`_changequote__(<,>)')
+_1__
+
+C. CONDITIONALS
+
+We define two macros, _if__ and _fi__.  BOTH take arguments!  This is
+meant both to help the human reader match up a _fi__ with its
+corresponding _if__ and to aid in the implementation.  You may use the
+full expression syntax supported by M4 (see docn of `eval' builtin in
+the m4 manual).
+
+The conditional macros are carefully defined to avoid introducing
+extra whitespace (i.e., blank lines or blank characters).  One side
+effect exists---
+
+       BEWARE: text following an `_if__' on the same line is
+               DISCARDED even if the condition is true; text
+               following a `_fi__' on the same line is also 
+               always discarded.
+
+The recommended convention is to always place _if__ and _fi__ on a
+line by themselves.  This will also aid the human reader.  TeX won't
+care about the line breaks; as for info, you may want to insert calls
+to `@refill' at the end of paragraphs containing conditionalized text,
+where you don't want line breaks separating unconditional from
+conditional text.  info formatting will then give you nice looking
+paragraphs in the info file.
+
+Nesting: conditionals are designed to nest, in the following way:
+*nothing* is output between an outer pair of false conditionals, even
+if there are true conditionals inside.  A false conditional "defeats"
+all conditionals within it.  The counter _IF_FS__ is used to
+implement this; kindly avoid redefining it directly.
+
+_define__(<_IF_FS__>,<0>)
+_define__(
+       <_pushf__>,
+       <_define__(<_IF_FS__>,
+               _incr__(_IF_FS__))>)
+_define__(
+       <_popf__>,
+       <_ifelse__(0,_IF_FS__,
+                       <<>_dnl__<>>,
+                       <_define__(<_IF_FS__>,_decr__(_IF_FS__))>)>)
+
+_define__(
+       <_if__>,
+       <_ifelse__(1,_eval__( ($1) ),
+                       <<>_dnl__<>>,
+                       <_pushf__<>_divert__(-1)>)>)
+_define__(
+       <_fi__>,
+       <_ifelse__(1,_eval__( ($1) ),
+               <<>_dnl__<>>,
+               <_popf__<>_ifelse__(0,_IF_FS__,
+                       <_divert__<>_dnl__<>>,<>)>)>)
+
+D. CHAPTER/SECTION MACRO
+In a parametrized manual, the heading level may need to be calculated;
+for example, a manual that has a chapter on machine dependencies
+should be conditionally structured as follows:
+       - IF the manual is configured for a SINGLE machine type,  use
+the chapter heading for that machine type, and run headings down
+from there (top level for a particular machine is chapter, then within
+that we have section, subsection etc);
+       - ELSE, if MANY machine types are described in the chapter,
+use a generic chapter heading such as "@chapter Machine Dependencies",
+use "section" for the top level description of EACH machine, and run
+headings down from there (top level for a particular machine is
+section, then within that we have subsection, subsubsection etc).
+
+The macro <_CHAPSEC__> is for this purpose: its argument is evaluated (so
+you can construct expressions to express choices such as above), then
+expands as follows:
+   0: @chapter
+   1: @section
+   2: @subsection
+   3: @subsubsection
+ ...and so on.
+
+_define__(<_CHAPSEC__>,<@_cs__(_eval__($1))>)
+_define__(<_cs__>,<_ifelse__(
+                       0, $1, <chapter>,
+                       1, $1, <section>,
+                               <sub<>_cs__(_eval__($1 - 1))>)>)
+
+_divert__<>_dnl__<>
diff --git a/gdb/doc/sparc.m4 b/gdb/doc/sparc.m4
new file mode 100644 (file)
index 0000000..8cc6a3e
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_SPARC__>,<1>)
+_define__(<_HOST__>,<SPARC>)
+_define__(<_MACH_DEP__>,<SPARC Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gdb/doc/vax.m4 b/gdb/doc/vax.m4
new file mode 100644 (file)
index 0000000..59cb2ab
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_VAX__>,<1>)
+_define__(<_HOST__>,<VAX>)
+_define__(<_MACH_DEP__>,<VAX Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gdb/hp300ux-xdep.c b/gdb/hp300ux-xdep.c
new file mode 100644 (file)
index 0000000..f7f1cf0
--- /dev/null
@@ -0,0 +1,230 @@
+/* HP/UX interface for HP 300's, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* Defining this means some system include files define some extra stuff.  */
+#define WOPR
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <sys/trap.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#define INFERIOR_AR0(u)                                                        \
+  ((ptrace                                                             \
+    (PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0))   \
+   - KERNEL_U_ADDR)
+
+static void
+fetch_inferior_register (regno, regaddr)
+     register int regno;
+     register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+  if (regno == PS_REGNUM)
+    {
+      union { int i; short s[2]; } ps_val;
+      int regval;
+      
+      ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+      regval = ps_val.s[0];
+      supply_register (regno, &regval);
+    }
+  else
+#endif /* not HPUX_VERSION_5 */
+    {
+      char buf[MAX_REGISTER_RAW_SIZE];
+      register int i;
+      
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
+         regaddr += sizeof (int);
+       }
+      supply_register (regno, buf);
+    }
+  return;
+}
+
+static void
+store_inferior_register_1 (regno, regaddr, value)
+     int regno;
+     unsigned int regaddr;
+     int value;
+{
+  errno = 0;
+  ptrace (PT_WUAREA, inferior_pid, regaddr, value);
+#if 0
+  /* HP-UX randomly sets errno to non-zero for regno == 25.
+     However, the value is correctly written, so ignore errno. */
+  if (errno != 0)
+    {
+      char string_buf[64];
+      
+      sprintf (string_buf, "writing register number %d", regno);
+      perror_with_name (string_buf);
+    }
+#endif
+  return;
+}
+
+static void
+store_inferior_register (regno, regaddr)
+     register int regno;
+     register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+  if (regno == PS_REGNUM)
+    {
+      union { int i; short s[2]; } ps_val;
+      
+      ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+      ps_val.s[0] = (read_register (regno));
+      store_inferior_register_1 (regno, regaddr, ps_val.i);
+    }
+  else
+#endif /* not HPUX_VERSION_5 */
+    {
+      char buf[MAX_REGISTER_RAW_SIZE];
+      register int i;
+      extern char registers[];
+      
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         store_inferior_register_1
+           (regno, regaddr,
+            (*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
+         regaddr += sizeof (int);
+       }
+    }
+  return;
+}
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  struct user u;
+  register int regno;
+  register unsigned int ar0_offset;
+  
+  ar0_offset = (INFERIOR_AR0 (u));
+  if (regno == -1)
+    {
+      for (regno = 0; (regno < FP0_REGNUM); regno++)
+       fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+      for (; (regno < NUM_REGS); regno++)
+       fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+    }
+  else
+    fetch_inferior_register (regno,
+                            (regno < FP0_REGNUM
+                             ? REGISTER_ADDR (ar0_offset, regno)
+                             : FP_REGISTER_ADDR (u, regno)));
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     register int regno;
+{
+  struct user u;
+  register unsigned int ar0_offset;
+  extern char registers[];
+
+  if (regno >= FP0_REGNUM)
+    {
+      store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+      return;
+    }
+  
+  ar0_offset = (INFERIOR_AR0 (u));
+  if (regno >= 0)
+    {
+      store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+      return;
+    }
+
+  for (regno = 0; (regno < FP0_REGNUM); regno++)
+    store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+  for (; (regno < NUM_REGS); regno++)
+    store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+  return;
+}
+
+\f
+/* Take the register values out of a core file and store
+   them where `read_register' will find them.  */
+
+#ifdef HPUX_VERSION_5
+#define e_PS e_regs[PS]
+#define e_PC e_regs[PC]
+#endif /* HPUX_VERSION_5 */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+     char *core_reg_sect;
+     int core_reg_size;
+     int which;
+{
+  int val, regno;
+  struct user u;
+  struct exception_stack *pes = (struct exception_stack *) core_reg_sect;
+#define es (*pes)
+  char *buf;
+
+  if (which == 0) {
+    if (core_reg_size < 
+                 ((char *) &es.e_offset - (char *) &es.e_regs[R0]))
+         error ("Not enough registers in core file");
+    for (regno = 0; (regno < PS_REGNUM); regno++)
+      supply_register (regno, &es.e_regs[regno + R0]);
+    val = es.e_PS;
+    supply_register (regno++, &val);
+    supply_register (regno++, &es.e_PC);
+
+  } else if (which == 2) {
+
+    /* FIXME: This may not work if the float regs and control regs are
+       discontinuous.  */
+    for (regno = FP0_REGNUM, buf = core_reg_sect;
+        (regno < NUM_REGS);
+        buf += REGISTER_RAW_SIZE (regno), regno++)
+      {
+       supply_register (regno, buf);
+      }
+  }
+}
diff --git a/gdb/infrun.hacked.c b/gdb/infrun.hacked.c
new file mode 100644 (file)
index 0000000..a1b5926
--- /dev/null
@@ -0,0 +1,1707 @@
+/* Start and stop the inferior process, for GDB.
+   Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Notes on the algorithm used in wait_for_inferior to determine if we
+   just did a subroutine call when stepping.  We have the following
+   information at that point:
+
+                  Current and previous (just before this step) pc.
+                 Current and previous sp.
+                 Current and previous start of current function.
+
+   If the start's of the functions don't match, then
+
+       a) We did a subroutine call.
+
+   In this case, the pc will be at the beginning of a function.
+
+       b) We did a subroutine return.
+
+   Otherwise.
+
+       c) We did a longjmp.
+
+   If we did a longjump, we were doing "nexti", since a next would
+   have attempted to skip over the assembly language routine in which
+   the longjmp is coded and would have simply been the equivalent of a
+   continue.  I consider this ok behaivior.  We'd like one of two
+   things to happen if we are doing a nexti through the longjmp()
+   routine: 1) It behaves as a stepi, or 2) It acts like a continue as
+   above.  Given that this is a special case, and that anybody who
+   thinks that the concept of sub calls is meaningful in the context
+   of a longjmp, I'll take either one.  Let's see what happens.  
+
+   Acts like a subroutine return.  I can handle that with no problem
+   at all.
+
+   -->So: If the current and previous beginnings of the current
+   function don't match, *and* the pc is at the start of a function,
+   we've done a subroutine call.  If the pc is not at the start of a
+   function, we *didn't* do a subroutine call.  
+
+   -->If the beginnings of the current and previous function do match,
+   either: 
+
+       a) We just did a recursive call.
+
+          In this case, we would be at the very beginning of a
+          function and 1) it will have a prologue (don't jump to
+          before prologue, or 2) (we assume here that it doesn't have
+          a prologue) there will have been a change in the stack
+          pointer over the last instruction.  (Ie. it's got to put
+          the saved pc somewhere.  The stack is the usual place.  In
+          a recursive call a register is only an option if there's a
+          prologue to do something with it.  This is even true on
+          register window machines; the prologue sets up the new
+          window.  It might not be true on a register window machine
+          where the call instruction moved the register window
+          itself.  Hmmm.  One would hope that the stack pointer would
+          also change.  If it doesn't, somebody send me a note, and
+          I'll work out a more general theory.
+          bug-gdb@prep.ai.mit.edu).  This is true (albeit slipperly
+          so) on all machines I'm aware of:
+
+             m68k:     Call changes stack pointer.  Regular jumps don't.
+
+             sparc:    Recursive calls must have frames and therefor,
+                       prologues.
+
+             vax:      All calls have frames and hence change the
+                       stack pointer.
+
+       b) We did a return from a recursive call.  I don't see that we
+          have either the ability or the need to distinguish this
+          from an ordinary jump.  The stack frame will be printed
+          when and if the frame pointer changes; if we are in a
+          function without a frame pointer, it's the users own
+          lookout.
+
+       c) We did a jump within a function.  We assume that this is
+          true if we didn't do a recursive call.
+
+       d) We are in no-man's land ("I see no symbols here").  We
+          don't worry about this; it will make calls look like simple
+          jumps (and the stack frames will be printed when the frame
+          pointer moves), which is a reasonably non-violent response.
+
+#if 0
+    We skip this; it causes more problems than it's worth.
+#ifdef SUN4_COMPILER_FEATURE
+    We do a special ifdef for the sun 4, forcing it to single step
+  into calls which don't have prologues.  This means that we can't
+  nexti over leaf nodes, we can probably next over them (since they
+  won't have debugging symbols, usually), and we can next out of
+  functions returning structures (with a "call .stret4" at the end).
+#endif
+#endif
+*/
+   
+
+   
+   
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "breakpoint.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "signame.h"
+#include "command.h"
+#include "terminal.h"          /* For #ifdef TIOCGPGRP and new_tty */
+#include "target.h"
+
+#include <signal.h>
+
+/* unistd.h is needed to #define X_OK */
+#ifdef USG
+#include <unistd.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifdef SET_STACK_LIMIT_HUGE
+extern int original_stack_limit;
+#endif /* SET_STACK_LIMIT_HUGE */
+
+/* Required by <sys/user.h>.  */
+#include <sys/types.h>
+/* Required by <sys/user.h>, at least on system V.  */
+#include <sys/dir.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax).  */
+#include <sys/param.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax).  */
+#include <sys/user.h>
+
+extern int errno;
+extern char *getenv ();
+
+extern struct target_ops child_ops;    /* In inftarg.c */
+
+/* Copy of inferior_io_terminal when inferior was last started.  */
+
+extern char *inferior_thisrun_terminal;
+
+
+/* Sigtramp is a routine that the kernel calls (which then calls the
+   signal handler).  On most machines it is a library routine that
+   is linked into the executable.
+
+   This macro, given a program counter value and the name of the
+   function in which that PC resides (which can be null if the
+   name is not known), returns nonzero if the PC and name show
+   that we are in sigtramp.
+
+   On most machines just see if the name is sigtramp (and if we have
+   no name, assume we are not in sigtramp).  */
+#if !defined (IN_SIGTRAMP)
+#define IN_SIGTRAMP(pc, name) \
+  name && !strcmp ("_sigtramp", name)
+#endif
+
+/* Tables of how to react to signals; the user sets them.  */
+
+static char signal_stop[NSIG];
+static char signal_print[NSIG];
+static char signal_program[NSIG];
+
+/* Nonzero if breakpoints are now inserted in the inferior.  */
+/* Nonstatic for initialization during xxx_create_inferior. FIXME. */
+
+/*static*/ int breakpoints_inserted;
+
+/* Function inferior was in as of last step command.  */
+
+static struct symbol *step_start_function;
+
+/* Nonzero => address for special breakpoint for resuming stepping.  */
+
+static CORE_ADDR step_resume_break_address;
+
+/* Pointer to orig contents of the byte where the special breakpoint is.  */
+
+static char step_resume_break_shadow[BREAKPOINT_MAX];
+
+/* Nonzero means the special breakpoint is a duplicate
+   so it has not itself been inserted.  */
+
+static int step_resume_break_duplicate;
+
+/* Nonzero if we are expecting a trace trap and should proceed from it.  */
+
+static int trap_expected;
+
+/* Nonzero if the next time we try to continue the inferior, it will
+   step one instruction and generate a spurious trace trap.
+   This is used to compensate for a bug in HP-UX.  */
+
+static int trap_expected_after_continue;
+
+/* Nonzero means expecting a trace trap
+   and should stop the inferior and return silently when it happens.  */
+
+int stop_after_trap;
+
+/* Nonzero means expecting a trap and caller will handle it themselves.
+   It is used after attach, due to attaching to a process;
+   when running in the shell before the child program has been exec'd;
+   and when running some kinds of remote stuff (FIXME?).  */
+
+int stop_soon_quietly;
+
+/* Nonzero if pc has been changed by the debugger
+   since the inferior stopped.  */
+
+int pc_changed;
+
+/* Nonzero if proceed is being used for a "finish" command or a similar
+   situation when stop_registers should be saved.  */
+
+int proceed_to_finish;
+
+/* Save register contents here when about to pop a stack dummy frame,
+   if-and-only-if proceed_to_finish is set.
+   Thus this contains the return value from the called function (assuming
+   values are returned in a register).  */
+
+char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if program stopped due to error trying to insert breakpoints.  */
+
+static int breakpoints_failed;
+
+/* Nonzero after stop if current stack frame should be printed.  */
+
+static int stop_print_frame;
+
+#ifdef NO_SINGLE_STEP
+extern int one_stepped;                /* From machine dependent code */
+extern void single_step ();    /* Same. */
+#endif /* NO_SINGLE_STEP */
+
+static void insert_step_breakpoint ();
+static void remove_step_breakpoint ();
+/*static*/ void wait_for_inferior ();
+void init_wait_for_inferior ();
+static void normal_stop ();
+
+\f
+/* Clear out all variables saying what to do when inferior is continued.
+   First do this, then set the ones you want, then call `proceed'.  */
+
+void
+clear_proceed_status ()
+{
+  trap_expected = 0;
+  step_range_start = 0;
+  step_range_end = 0;
+  step_frame_address = 0;
+  step_over_calls = -1;
+  step_resume_break_address = 0;
+  stop_after_trap = 0;
+  stop_soon_quietly = 0;
+  proceed_to_finish = 0;
+  breakpoint_proceeded = 1;    /* We're about to proceed... */
+
+  /* Discard any remaining commands or status from previous stop.  */
+  bpstat_clear (&stop_bpstat);
+}
+
+/* Basic routine for continuing the program in various fashions.
+
+   ADDR is the address to resume at, or -1 for resume where stopped.
+   SIGGNAL is the signal to give it, or 0 for none,
+     or -1 for act according to how it stopped.
+   STEP is nonzero if should trap after one instruction.
+     -1 means return after that and print nothing.
+     You should probably set various step_... variables
+     before calling here, if you are stepping.
+
+   You should call clear_proceed_status before calling proceed.  */
+
+void
+proceed (addr, siggnal, step)
+     CORE_ADDR addr;
+     int siggnal;
+     int step;
+{
+  int oneproc = 0;
+
+  if (step > 0)
+    step_start_function = find_pc_function (read_pc ());
+  if (step < 0)
+    stop_after_trap = 1;
+
+  if (addr == -1)
+    {
+      /* If there is a breakpoint at the address we will resume at,
+        step one instruction before inserting breakpoints
+        so that we do not stop right away.  */
+
+      if (!pc_changed && breakpoint_here_p (read_pc ()))
+       oneproc = 1;
+    }
+  else
+    {
+      write_register (PC_REGNUM, addr);
+#ifdef NPC_REGNUM
+      write_register (NPC_REGNUM, addr + 4);
+#ifdef NNPC_REGNUM
+      write_register (NNPC_REGNUM, addr + 8);
+#endif
+#endif
+    }
+
+  if (trap_expected_after_continue)
+    {
+      /* If (step == 0), a trap will be automatically generated after
+        the first instruction is executed.  Force step one
+        instruction to clear this condition.  This should not occur
+        if step is nonzero, but it is harmless in that case.  */
+      oneproc = 1;
+      trap_expected_after_continue = 0;
+    }
+
+  if (oneproc)
+    /* We will get a trace trap after one instruction.
+       Continue it automatically and insert breakpoints then.  */
+    trap_expected = 1;
+  else
+    {
+      int temp = insert_breakpoints ();
+      if (temp)
+       {
+         print_sys_errmsg ("ptrace", temp);
+         error ("Cannot insert breakpoints.\n\
+The same program may be running in another process.");
+       }
+      breakpoints_inserted = 1;
+    }
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  if (siggnal >= 0)
+    stop_signal = siggnal;
+  /* If this signal should not be seen by program,
+     give it zero.  Used for debugging signals.  */
+  else if (stop_signal < NSIG && !signal_program[stop_signal])
+    stop_signal= 0;
+
+  /* Handle any optimized stores to the inferior NOW...  */
+#ifdef DO_DEFERRED_STORES
+  DO_DEFERRED_STORES;
+#endif
+
+  /* Resume inferior.  */
+  target_resume (oneproc || step || bpstat_should_step (), stop_signal);
+
+  /* Wait for it to stop (if not standalone)
+     and in any case decode why it stopped, and act accordingly.  */
+
+  wait_for_inferior ();
+  normal_stop ();
+}
+
+#if 0
+/* This might be useful (not sure), but isn't currently used.  See also
+   write_pc().  */
+/* Writing the inferior pc as a register calls this function
+   to inform infrun that the pc has been set in the debugger.  */
+
+void
+writing_pc (val)
+     CORE_ADDR val;
+{
+  stop_pc = val;
+  pc_changed = 1;
+}
+#endif
+
+/* Record the pc and sp of the program the last time it stopped.
+   These are just used internally by wait_for_inferior, but need
+   to be preserved over calls to it and cleared when the inferior
+   is started.  */
+static CORE_ADDR prev_pc;
+static CORE_ADDR prev_sp;
+static CORE_ADDR prev_func_start;
+static char *prev_func_name;
+
+/* Start an inferior Unix child process and sets inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.  Errors reported with error().  */
+
+#ifndef SHELL_FILE
+#define SHELL_FILE "/bin/sh"
+#endif
+
+void
+child_create_inferior (exec_file, allargs, env)
+     char *exec_file;
+     char *allargs;
+     char **env;
+{
+  int pid;
+  char *shell_command;
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+  char *shell_file;
+  static char default_shell_file[] = SHELL_FILE;
+  int len;
+  int pending_execs;
+  /* Set debug_fork then attach to the child while it sleeps, to debug. */
+  static int debug_fork = 0;
+  /* This is set to the result of setpgrp, which if vforked, will be visible
+     to you in the parent process.  It's only used by humans for debugging.  */
+  static int debug_setpgrp = 657473;
+
+  /* The user might want tilde-expansion, and in general probably wants
+     the program to behave the same way as if run from
+     his/her favorite shell.  So we let the shell run it for us.
+     FIXME, this should probably search the local environment (as
+     modified by the setenv command), not the env gdb inherited.  */
+  shell_file = getenv ("SHELL");
+  if (shell_file == NULL)
+    shell_file = default_shell_file;
+  
+  len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
+  /* If desired, concat something onto the front of ALLARGS.
+     SHELL_COMMAND is the result.  */
+#ifdef SHELL_COMMAND_CONCAT
+  shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
+  strcpy (shell_command, SHELL_COMMAND_CONCAT);
+#else
+  shell_command = (char *) alloca (len);
+  shell_command[0] = '\0';
+#endif
+  strcat (shell_command, "exec ");
+  strcat (shell_command, exec_file);
+  strcat (shell_command, " ");
+  strcat (shell_command, allargs);
+
+  /* exec is said to fail if the executable is open.  */
+  close_exec_file ();
+
+#if defined(USG) && !defined(HAVE_VFORK)
+  pid = fork ();
+#else
+  if (debug_fork)
+    pid = fork ();
+  else
+    pid = vfork ();
+#endif
+
+  if (pid < 0)
+    perror_with_name ("vfork");
+
+  if (pid == 0)
+    {
+      if (debug_fork) 
+       sleep (debug_fork);
+
+#ifdef TIOCGPGRP
+      /* Run inferior in a separate process group.  */
+      debug_setpgrp = setpgrp (getpid (), getpid ());
+      if (0 != debug_setpgrp)
+        perror("setpgrp failed in child");
+#endif /* TIOCGPGRP */
+
+#ifdef SET_STACK_LIMIT_HUGE
+      /* Reset the stack limit back to what it was.  */
+      {
+       struct rlimit rlim;
+
+       getrlimit (RLIMIT_STACK, &rlim);
+       rlim.rlim_cur = original_stack_limit;
+       setrlimit (RLIMIT_STACK, &rlim);
+      }
+#endif /* SET_STACK_LIMIT_HUGE */
+
+      /* Tell the terminal handling subsystem what tty we plan to run on;
+        it will now switch to that one if non-null.  */
+
+      new_tty (inferior_io_terminal);
+
+      /* Changing the signal handlers for the inferior after
+        a vfork can also change them for the superior, so we don't mess
+        with signals here.  See comments in
+        initialize_signals for how we get the right signal handlers
+        for the inferior.  */
+
+      call_ptrace (0, 0, 0, 0);                /* "Trace me, Dr. Memory!" */
+      execle (shell_file, shell_file, "-c", shell_command, (char *)0, env);
+
+      fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
+              errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+      fflush (stderr);
+      _exit (0177);
+    }
+
+  /* Now that we have a child process, make it our target.  */
+  push_target (&child_ops);
+
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
+
+/* The process was started by the fork that created it,
+   but it will have stopped one instruction after execing the shell.
+   Here we must get it up to actual execution of the real program.  */
+
+  inferior_pid = pid;          /* Needed for wait_for_inferior stuff below */
+
+  clear_proceed_status ();
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  /* We will get a trace trap after one instruction.
+     Continue it automatically.  Eventually (after shell does an exec)
+     it will get another trace trap.  Then insert breakpoints and continue.  */
+
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+  pending_execs = START_INFERIOR_TRAPS_EXPECTED;
+#else
+  pending_execs = 2;
+#endif
+
+  init_wait_for_inferior ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  while (1)
+    {
+      stop_soon_quietly = 1;   /* Make wait_for_inferior be quiet */
+      wait_for_inferior ();
+      if (stop_signal != SIGTRAP)
+       {
+         /* Let shell child handle its own signals in its own way */
+         /* FIXME, what if child has exit()ed?  Must exit loop somehow */
+         target_resume (0, stop_signal);
+       }
+      else
+       {
+         /* We handle SIGTRAP, however; it means child did an exec.  */
+         if (0 == --pending_execs)
+           break;
+         target_resume (0, 0);         /* Just make it go on */
+       }
+    }
+  stop_soon_quietly = 0;
+
+  /* Should this perhaps just be a "proceed" call?  FIXME */
+  insert_step_breakpoint ();
+  breakpoints_failed = insert_breakpoints ();
+  if (!breakpoints_failed)
+    {
+      breakpoints_inserted = 1;
+      target_terminal_inferior();
+      /* Start the child program going on its first instruction, single-
+        stepping if we need to.  */
+      target_resume (bpstat_should_step (), 0);
+      wait_for_inferior ();
+      normal_stop ();
+    }
+}
+
+/* Start remote-debugging of a machine over a serial link.  */
+
+void
+start_remote ()
+{
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  trap_expected = 0;
+}
+
+/* Initialize static vars when a new inferior begins.  */
+
+void
+init_wait_for_inferior ()
+{
+  /* These are meaningless until the first time through wait_for_inferior.  */
+  prev_pc = 0;
+  prev_sp = 0;
+  prev_func_start = 0;
+  prev_func_name = NULL;
+
+  trap_expected_after_continue = 0;
+  breakpoints_inserted = 0;
+  mark_breakpoints_out ();
+}
+
+
+/* Attach to process PID, then initialize for debugging it
+   and wait for the trace-trap that results from attaching.  */
+
+void
+child_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
+
+  dont_repeat();
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+
+#ifndef ATTACH_DETACH
+  error ("Can't attach to a process on this machine.");
+#else
+  pid = atoi (args);
+
+  if (target_has_execution)
+    {
+      if (query ("A program is being debugged already.  Kill it? "))
+       target_kill ((char *)0, from_tty);
+      else
+       error ("Inferior not killed.");
+    }
+
+  exec_file = (char *) get_exec_file (1);
+
+  if (from_tty)
+    {
+      printf ("Attaching program: %s pid %d\n",
+             exec_file, pid);
+      fflush (stdout);
+    }
+
+  attach (pid);
+  inferior_pid = pid;
+  push_target (&child_ops);
+
+  mark_breakpoints_out ();
+  target_terminal_init ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  /*proceed (-1, 0, -2);*/
+  target_terminal_inferior ();
+  wait_for_inferior ();
+  normal_stop ();
+#endif  /* ATTACH_DETACH */
+}
+\f
+/* Wait for control to return from inferior to debugger.
+   If inferior gets a signal, we may decide to start it up again
+   instead of returning.  That is why there is a loop in this function.
+   When this function actually returns it means the inferior
+   should be left stopped and GDB should read more commands.  */
+
+void
+wait_for_inferior ()
+{
+  WAITTYPE w;
+  int another_trap;
+  int random_signal;
+  CORE_ADDR stop_sp;
+  CORE_ADDR stop_func_start;
+  char *stop_func_name;
+  CORE_ADDR prologue_pc;
+  int stop_step_resume_break;
+  struct symtab_and_line sal;
+  int remove_breakpoints_on_following_step = 0;
+
+#if 0
+  /* This no longer works now that read_register is lazy;
+     it might try to ptrace when the process is not stopped.  */
+  prev_pc = read_pc ();
+  (void) find_pc_partial_function (prev_pc, &prev_func_name,
+                                  &prev_func_start);
+  prev_func_start += FUNCTION_START_OFFSET;
+  prev_sp = read_register (SP_REGNUM);
+#endif /* 0 */
+
+  while (1)
+    {
+      /* Clean up saved state that will become invalid.  */
+      pc_changed = 0;
+      flush_cached_frames ();
+      registers_changed ();
+
+      target_wait (&w);
+
+      /* See if the process still exists; clean up if it doesn't.  */
+      if (WIFEXITED (w))
+       {
+         target_terminal_ours_for_output ();
+         if (WEXITSTATUS (w))
+           printf ("\nProgram exited with code 0%o.\n", 
+                    (unsigned int)WEXITSTATUS (w));
+         else
+           if (!batch_mode())
+             printf ("\nProgram exited normally.\n");
+         fflush (stdout);
+         target_mourn_inferior ();
+#ifdef NO_SINGLE_STEP
+         one_stepped = 0;
+#endif
+         stop_print_frame = 0;
+         break;
+       }
+      else if (!WIFSTOPPED (w))
+       {
+         target_kill ((char *)0, 0);
+         stop_print_frame = 0;
+         stop_signal = WTERMSIG (w);
+         target_terminal_ours_for_output ();
+         printf ("\nProgram terminated with signal %d, %s\n",
+                 stop_signal,
+                 stop_signal < NSIG
+                 ? sys_siglist[stop_signal]
+                 : "(undocumented)");
+         printf ("The inferior process no longer exists.\n");
+         fflush (stdout);
+#ifdef NO_SINGLE_STEP
+         one_stepped = 0;
+#endif
+         break;
+       }
+      
+#ifdef NO_SINGLE_STEP
+      if (one_stepped)
+       single_step (0);        /* This actually cleans up the ss */
+#endif /* NO_SINGLE_STEP */
+      
+      stop_pc = read_pc ();
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      
+      stop_frame_address = FRAME_FP (get_current_frame ());
+      stop_sp = read_register (SP_REGNUM);
+      stop_func_start = 0;
+      stop_func_name = 0;
+      /* Don't care about return value; stop_func_start and stop_func_name
+        will both be 0 if it doesn't work.  */
+      (void) find_pc_partial_function (stop_pc, &stop_func_name,
+                                      &stop_func_start);
+      stop_func_start += FUNCTION_START_OFFSET;
+      another_trap = 0;
+      bpstat_clear (&stop_bpstat);
+      stop_step = 0;
+      stop_stack_dummy = 0;
+      stop_print_frame = 1;
+      stop_step_resume_break = 0;
+      random_signal = 0;
+      stopped_by_random_signal = 0;
+      breakpoints_failed = 0;
+      
+      /* Look at the cause of the stop, and decide what to do.
+        The alternatives are:
+        1) break; to really stop and return to the debugger,
+        2) drop through to start up again
+        (set another_trap to 1 to single step once)
+        3) set random_signal to 1, and the decision between 1 and 2
+        will be made according to the signal handling tables.  */
+      
+      stop_signal = WSTOPSIG (w);
+      
+      /* First, distinguish signals caused by the debugger from signals
+        that have to do with the program's own actions.
+        Note that breakpoint insns may cause SIGTRAP or SIGILL
+        or SIGEMT, depending on the operating system version.
+        Here we detect when a SIGILL or SIGEMT is really a breakpoint
+        and change it to SIGTRAP.  */
+      
+      if (stop_signal == SIGTRAP
+         || (breakpoints_inserted &&
+             (stop_signal == SIGILL
+              || stop_signal == SIGEMT))
+         || stop_soon_quietly)
+       {
+         if (stop_signal == SIGTRAP && stop_after_trap)
+           {
+             stop_print_frame = 0;
+             break;
+           }
+         if (stop_soon_quietly)
+           break;
+
+         /* Don't even think about breakpoints
+            if just proceeded over a breakpoint.
+
+            However, if we are trying to proceed over a breakpoint
+            and end up in sigtramp, then step_resume_break_address
+            will be set and we should check whether we've hit the
+            step breakpoint.  */
+         if (stop_signal == SIGTRAP && trap_expected
+             && step_resume_break_address == NULL)
+           bpstat_clear (&stop_bpstat);
+         else
+           {
+             /* See if there is a breakpoint at the current PC.  */
+#if DECR_PC_AFTER_BREAK
+             /* Notice the case of stepping through a jump
+                that leads just after a breakpoint.
+                Don't confuse that with hitting the breakpoint.
+                What we check for is that 1) stepping is going on
+                and 2) the pc before the last insn does not match
+                the address of the breakpoint before the current pc.  */
+             if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+                   && step_range_end && !step_resume_break_address))
+#endif /* DECR_PC_AFTER_BREAK not zero */
+               {
+                 /* See if we stopped at the special breakpoint for
+                    stepping over a subroutine call.  */
+                 if (stop_pc - DECR_PC_AFTER_BREAK
+                     == step_resume_break_address)
+                   {
+                     stop_step_resume_break = 1;
+                     if (DECR_PC_AFTER_BREAK)
+                       {
+                         stop_pc -= DECR_PC_AFTER_BREAK;
+                         write_register (PC_REGNUM, stop_pc);
+                         pc_changed = 0;
+                       }
+                   }
+                 else
+                   {
+                     stop_bpstat =
+                       bpstat_stop_status (&stop_pc, stop_frame_address);
+                     /* Following in case break condition called a
+                        function.  */
+                     stop_print_frame = 1;
+                   }
+               }
+           }
+         
+         if (stop_signal == SIGTRAP)
+           random_signal
+             = !(bpstat_explains_signal (stop_bpstat)
+                 || trap_expected
+                 || stop_step_resume_break
+                 || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                 || (step_range_end && !step_resume_break_address));
+         else
+           {
+             random_signal
+               = !(bpstat_explains_signal (stop_bpstat)
+                   || stop_step_resume_break
+                   /* End of a stack dummy.  Some systems (e.g. Sony
+                      news) give another signal besides SIGTRAP,
+                      so check here as well as above.  */
+                   || (stop_sp INNER_THAN stop_pc
+                       && stop_pc INNER_THAN stop_frame_address)
+                   );
+             if (!random_signal)
+               stop_signal = SIGTRAP;
+           }
+       }
+      else
+       random_signal = 1;
+      
+      /* For the program's own signals, act according to
+        the signal handling tables.  */
+      
+      if (random_signal)
+       {
+         /* Signal not for debugging purposes.  */
+         int printed = 0;
+         
+         stopped_by_random_signal = 1;
+         
+         if (stop_signal >= NSIG
+             || signal_print[stop_signal])
+           {
+             printed = 1;
+             target_terminal_ours_for_output ();
+#ifdef PRINT_RANDOM_SIGNAL
+             PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+             printf ("\nProgram received signal %d, %s\n",
+                     stop_signal,
+                     stop_signal < NSIG
+                     ? sys_siglist[stop_signal]
+                     : "(undocumented)");
+#endif /* PRINT_RANDOM_SIGNAL */
+             fflush (stdout);
+           }
+         if (stop_signal >= NSIG
+             || signal_stop[stop_signal])
+           break;
+         /* If not going to stop, give terminal back
+            if we took it away.  */
+         else if (printed)
+           target_terminal_inferior ();
+       }
+      
+      /* Handle cases caused by hitting a user breakpoint.  */
+      
+      if (!random_signal && bpstat_explains_signal (stop_bpstat))
+      {
+         /* Does a breakpoint want us to stop?  */
+         if (bpstat_stop (stop_bpstat))
+           {
+             stop_print_frame = bpstat_should_print (stop_bpstat);
+             break;
+           }
+
+         /* Otherwise we continue.  Must remove breakpoints and single-step
+            to get us past the one we hit.  Possibly we also were stepping
+            and should stop for that.  So fall through and
+            test for stepping.  But, if not stepping,
+            do not stop.  */
+         else
+           {
+             remove_breakpoints ();
+             remove_step_breakpoint (); /* FIXME someday, do we need this? */
+             breakpoints_inserted = 0;
+             another_trap = 1;
+           }
+       }
+
+      /* Handle cases caused by hitting a step-resumption breakpoint.  */
+      
+      else if (!random_signal && stop_step_resume_break)
+       {
+         /* We have hit the step-resumption breakpoint.
+            If we aren't in a recursive call that hit it again
+            before returning from the original call, remove it;
+            it has done its job getting us here.  We then resume
+            the stepping we were doing before the function call.
+
+            If we are in a recursive call, just proceed from this
+            breakpoint as usual, keeping it around to catch the final
+            return of interest.
+
+            There used to be an sp test to make sure that we don't get hung
+            up in recursive calls in functions without frame
+            pointers.  If the stack pointer isn't outside of
+            where the breakpoint was set (within a routine to be
+            stepped over), we're in the middle of a recursive
+            call. Not true for reg window machines (sparc)
+            because they must change frames to call things and
+            the stack pointer doesn't have to change if
+            the bp was set in a routine without a frame (pc can
+            be stored in some other window).
+
+            The removal of the sp test is to allow calls to
+            alloca.  Nasty things were happening.  Oh, well,
+            gdb can only handle one level deep of lack of
+            frame pointer. */
+         if (step_frame_address == 0
+             || (stop_frame_address == step_frame_address))
+           {
+             /* We really hit it:  not a recursive call.  */
+             remove_step_breakpoint ();
+             step_resume_break_address = 0;
+
+             /* If we're waiting for a trap, hitting the step_resume_break
+                doesn't count as getting it.  */
+             if (trap_expected)
+               another_trap = 1;
+             /* Fall through to resume stepping... */
+           }
+         else
+           {
+             /* Otherwise, it's the recursive call case.  */
+             remove_breakpoints ();
+             remove_step_breakpoint ();
+             breakpoints_inserted = 0;
+             another_trap = 1;
+             /* Fall through to continue executing at full speed 
+                (with a possible single-step lurch over the step-resumption
+                 breakpoint as we start.)  */
+           }
+       }
+      
+      /* If this is the breakpoint at the end of a stack dummy,
+        just stop silently.  */
+      if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address))
+         {
+           stop_print_frame = 0;
+           stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+           trap_expected_after_continue = 1;
+#endif
+           break;
+         }
+      
+      if (step_resume_break_address)
+       /* Having a step-resume breakpoint overrides anything
+          else having to do with stepping commands until
+          that breakpoint is reached.  */
+       ;
+      /* If stepping through a line, keep going if still within it.  */
+      else if (!random_signal
+              && step_range_end
+              && stop_pc >= step_range_start
+              && stop_pc < step_range_end
+              /* The step range might include the start of the
+                 function, so if we are at the start of the
+                 step range and either the stack or frame pointers
+                 just changed, we've stepped outside */
+              && !(stop_pc == step_range_start
+                   && stop_frame_address
+                   && (stop_sp INNER_THAN prev_sp
+                       || stop_frame_address != step_frame_address)))
+       {
+#if 0
+         /* When "next"ing through a function,
+            This causes an extra stop at the end.
+            Is there any reason for this?
+            It's confusing to the user.  */
+         /* Don't step through the return from a function
+            unless that is the first instruction stepped through.  */
+         if (ABOUT_TO_RETURN (stop_pc))
+           {
+             stop_step = 1;
+             break;
+           }
+#endif
+       }
+      
+      /* We stepped out of the stepping range.  See if that was due
+        to a subroutine call that we should proceed to the end of.  */
+      else if (!random_signal && step_range_end)
+       {
+         if (stop_func_start)
+           {
+             prologue_pc = stop_func_start;
+             SKIP_PROLOGUE (prologue_pc);
+           }
+
+         /* Did we just take a signal?  */
+         if (IN_SIGTRAMP (stop_pc, stop_func_name)
+             && !IN_SIGTRAMP (prev_pc, prev_func_name))
+           {
+             /* This code is needed at least in the following case:
+                The user types "next" and then a signal arrives (before
+                the "next" is done).  */
+             /* We've just taken a signal; go until we are back to
+                the point where we took it and one more.  */
+             step_resume_break_address = prev_pc;
+             step_resume_break_duplicate =
+               breakpoint_here_p (step_resume_break_address);
+             if (breakpoints_inserted)
+               insert_step_breakpoint ();
+             /* Make sure that the stepping range gets us past
+                that instruction.  */
+             if (step_range_end == 1)
+               step_range_end = (step_range_start = prev_pc) + 1;
+             remove_breakpoints_on_following_step = 1;
+           }
+
+         /* ==> See comments at top of file on this algorithm.  <==*/
+         
+         else if (stop_pc == stop_func_start
+             && (stop_func_start != prev_func_start
+                 || prologue_pc != stop_func_start
+                 || stop_sp != prev_sp))
+           {
+             /* It's a subroutine call */
+             if (step_over_calls > 0 
+                 || (step_over_calls &&  find_pc_function (stop_pc) == 0))
+               {
+                 /* A subroutine call has happened.  */
+                 /* Set a special breakpoint after the return */
+                 step_resume_break_address =
+                   ADDR_BITS_REMOVE
+                     (SAVED_PC_AFTER_CALL (get_current_frame ()));
+                 step_resume_break_duplicate
+                   = breakpoint_here_p (step_resume_break_address);
+                 if (breakpoints_inserted)
+                   insert_step_breakpoint ();
+               }
+             /* Subroutine call with source code we should not step over.
+                Do step to the first line of code in it.  */
+             else if (step_over_calls)
+               {
+                 SKIP_PROLOGUE (stop_func_start);
+                 sal = find_pc_line (stop_func_start, 0);
+                 /* Use the step_resume_break to step until
+                    the end of the prologue, even if that involves jumps
+                    (as it seems to on the vax under 4.2).  */
+                 /* If the prologue ends in the middle of a source line,
+                    continue to the end of that source line.
+                    Otherwise, just go to end of prologue.  */
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+                 /* no, don't either.  It skips any code that's
+                    legitimately on the first line.  */
+#else
+                 if (sal.end && sal.pc != stop_func_start)
+                   stop_func_start = sal.end;
+#endif
+                 
+                 if (stop_func_start == stop_pc)
+                   {
+                     /* We are already there: stop now.  */
+                     stop_step = 1;
+                     break;
+                   }
+                 else
+                   /* Put the step-breakpoint there and go until there. */
+                   {
+                     step_resume_break_address = stop_func_start;
+                     
+                     step_resume_break_duplicate
+                       = breakpoint_here_p (step_resume_break_address);
+                     if (breakpoints_inserted)
+                       insert_step_breakpoint ();
+                     /* Do not specify what the fp should be when we stop
+                        since on some machines the prologue
+                        is where the new fp value is established.  */
+                     step_frame_address = 0;
+                     /* And make sure stepping stops right away then.  */
+                     step_range_end = step_range_start;
+                   }
+               }
+             else
+               {
+                 /* We get here only if step_over_calls is 0 and we
+                    just stepped into a subroutine.  I presume
+                    that step_over_calls is only 0 when we're
+                    supposed to be stepping at the assembly
+                    language level.*/
+                 stop_step = 1;
+                 break;
+               }
+           }
+         /* No subroutine call; stop now.  */
+         else
+           {
+             stop_step = 1;
+             break;
+           }
+       }
+
+      else if (trap_expected
+              && IN_SIGTRAMP (stop_pc, stop_func_name)
+              && !IN_SIGTRAMP (prev_pc, prev_func_name))
+       {
+         /* What has happened here is that we have just stepped the inferior
+            with a signal (because it is a signal which shouldn't make
+            us stop), thus stepping into sigtramp.
+
+            So we need to set a step_resume_break_address breakpoint
+            and continue until we hit it, and then step.  */
+         step_resume_break_address = prev_pc;
+         /* Always 1, I think, but it's probably easier to have
+            the step_resume_break as usual rather than trying to
+            re-use the breakpoint which is already there.  */
+         step_resume_break_duplicate =
+           breakpoint_here_p (step_resume_break_address);
+         if (breakpoints_inserted)
+           insert_step_breakpoint ();
+         remove_breakpoints_on_following_step = 1;
+         another_trap = 1;
+       }
+
+      /* Save the pc before execution, to compare with pc after stop.  */
+      prev_pc = read_pc ();    /* Might have been DECR_AFTER_BREAK */
+      prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
+                                         BREAK is defined, the
+                                         original pc would not have
+                                         been at the start of a
+                                         function. */
+      prev_func_name = stop_func_name;
+      prev_sp = stop_sp;
+
+      /* If we did not do break;, it means we should keep
+        running the inferior and not return to debugger.  */
+
+      if (trap_expected && stop_signal != SIGTRAP)
+       {
+         /* We took a signal (which we are supposed to pass through to
+            the inferior, else we'd have done a break above) and we
+            haven't yet gotten our trap.  Simply continue.  */
+         target_resume ((step_range_end && !step_resume_break_address)
+                 || (trap_expected && !step_resume_break_address)
+                 || bpstat_should_step (),
+                 stop_signal);
+       }
+      else
+       {
+         /* Either the trap was not expected, but we are continuing
+            anyway (the user asked that this signal be passed to the
+            child)
+              -- or --
+            The signal was SIGTRAP, e.g. it was our signal, but we
+            decided we should resume from it.
+
+            We're going to run this baby now!
+
+            Insert breakpoints now, unless we are trying
+            to one-proceed past a breakpoint.  */
+         /* If we've just finished a special step resume and we don't
+            want to hit a breakpoint, pull em out.  */
+         if (!step_resume_break_address &&
+             remove_breakpoints_on_following_step)
+           {
+             remove_breakpoints_on_following_step = 0;
+             remove_breakpoints ();
+             breakpoints_inserted = 0;
+           }
+         else if (!breakpoints_inserted &&
+                  (step_resume_break_address != NULL || !another_trap))
+           {
+             insert_step_breakpoint ();
+             breakpoints_failed = insert_breakpoints ();
+             if (breakpoints_failed)
+               break;
+             breakpoints_inserted = 1;
+           }
+
+         trap_expected = another_trap;
+
+         if (stop_signal == SIGTRAP)
+           stop_signal = 0;
+
+#ifdef SHIFT_INST_REGS
+         /* I'm not sure when this following segment applies.  I do know, now,
+            that we shouldn't rewrite the regs when we were stopped by a
+            random signal from the inferior process.  */
+
+          if (!stop_breakpoint && (stop_signal != SIGCLD) 
+              && !stopped_by_random_signal)
+            {
+            CORE_ADDR pc_contents = read_register (PC_REGNUM);
+            CORE_ADDR npc_contents = read_register (NPC_REGNUM);
+            if (pc_contents != npc_contents)
+              {
+              write_register (NNPC_REGNUM, npc_contents);
+              write_register (NPC_REGNUM, pc_contents);
+             }
+            }
+#endif /* SHIFT_INST_REGS */
+
+         target_resume ((step_range_end && !step_resume_break_address)
+                 || (trap_expected && !step_resume_break_address)
+                 || bpstat_should_step (),
+                 stop_signal);
+       }
+    }
+  if (target_has_execution)
+    {
+      /* Assuming the inferior still exists, set these up for next
+        time, just like we did above if we didn't break out of the
+        loop.  */
+      prev_pc = read_pc ();
+      prev_func_start = stop_func_start;
+      prev_func_name = stop_func_name;
+      prev_sp = stop_sp;
+    }
+}
+\f
+/* Here to return control to GDB when the inferior stops for real.
+   Print appropriate messages, remove breakpoints, give terminal our modes.
+
+   STOP_PRINT_FRAME nonzero means print the executing frame
+   (pc, function, args, file, line number and line text).
+   BREAKPOINTS_FAILED nonzero means stop was due to error
+   attempting to insert breakpoints.  */
+
+static void
+normal_stop ()
+{
+  /* Make sure that the current_frame's pc is correct.  This
+     is a correction for setting up the frame info before doing
+     DECR_PC_AFTER_BREAK */
+  if (target_has_execution)
+    (get_current_frame ())->pc = read_pc ();
+  
+  if (breakpoints_failed)
+    {
+      target_terminal_ours_for_output ();
+      print_sys_errmsg ("ptrace", breakpoints_failed);
+      printf ("Stopped; cannot insert breakpoints.\n\
+The same program may be running in another process.\n");
+    }
+
+  if (target_has_execution)
+    remove_step_breakpoint ();
+
+  if (target_has_execution && breakpoints_inserted)
+    if (remove_breakpoints ())
+      {
+       target_terminal_ours_for_output ();
+       printf ("Cannot remove breakpoints because program is no longer writable.\n\
+It must be running in another process.\n\
+Further execution is probably impossible.\n");
+      }
+
+  breakpoints_inserted = 0;
+
+  /* Delete the breakpoint we stopped at, if it wants to be deleted.
+     Delete any breakpoint that is to be deleted at the next stop.  */
+
+  breakpoint_auto_delete (stop_bpstat);
+
+  /* If an auto-display called a function and that got a signal,
+     delete that auto-display to avoid an infinite recursion.  */
+
+  if (stopped_by_random_signal)
+    disable_current_display ();
+
+  if (step_multi && stop_step)
+    return;
+
+  target_terminal_ours ();
+
+  if (!target_has_stack)
+    return;
+
+  /* Select innermost stack frame except on return from a stack dummy routine,
+     or if the program has exited.  */
+  if (!stop_stack_dummy)
+    {
+      select_frame (get_current_frame (), 0);
+
+      if (stop_print_frame)
+       {
+         int source_only = bpstat_print (stop_bpstat);
+         print_sel_frame
+           (source_only
+            || (stop_step
+                && step_frame_address == stop_frame_address
+                && step_start_function == find_pc_function (stop_pc)));
+
+         /* Display the auto-display expressions.  */
+         do_displays ();
+       }
+    }
+
+  /* Save the function value return registers, if we care.
+     We might be about to restore their previous contents.  */
+  if (proceed_to_finish)
+    read_register_bytes (0, stop_registers, REGISTER_BYTES);
+
+  if (stop_stack_dummy)
+    {
+      /* Pop the empty frame that contains the stack dummy.
+         POP_FRAME ends with a setting of the current frame, so we
+        can use that next. */
+      POP_FRAME;
+      select_frame (get_current_frame (), 0);
+    }
+}
+\f
+static void
+insert_step_breakpoint ()
+{
+  if (step_resume_break_address && !step_resume_break_duplicate)
+    target_insert_breakpoint (step_resume_break_address,
+                             step_resume_break_shadow);
+}
+
+static void
+remove_step_breakpoint ()
+{
+  if (step_resume_break_address && !step_resume_break_duplicate)
+    target_remove_breakpoint (step_resume_break_address,
+                             step_resume_break_shadow);
+}
+\f
+static void
+sig_print_header ()
+{
+  printf_filtered ("Signal\t\tStop\tPrint\tPass to program\tDescription\n");
+}
+
+static void
+sig_print_info (number)
+     int number;
+{
+  char *abbrev = sig_abbrev(number);
+  if (abbrev == NULL)
+    printf_filtered ("%d\t\t", number);
+  else
+    printf_filtered ("SIG%s (%d)\t", abbrev, number);
+  printf_filtered ("%s\t", signal_stop[number] ? "Yes" : "No");
+  printf_filtered ("%s\t", signal_print[number] ? "Yes" : "No");
+  printf_filtered ("%s\t\t", signal_program[number] ? "Yes" : "No");
+  printf_filtered ("%s\n", sys_siglist[number]);
+}
+
+/* Specify how various signals in the inferior should be handled.  */
+
+static void
+handle_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register char *p = args;
+  int signum = 0;
+  register int digits, wordlen;
+  char *nextarg;
+
+  if (!args)
+    error_no_arg ("signal to handle");
+
+  while (*p)
+    {
+      /* Find the end of the next word in the args.  */
+      for (wordlen = 0;
+          p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t';
+          wordlen++);
+      /* Set nextarg to the start of the word after the one we just
+        found, and null-terminate this one.  */
+      if (p[wordlen] == '\0')
+       nextarg = p + wordlen;
+      else
+       {
+         p[wordlen] = '\0';
+         nextarg = p + wordlen + 1;
+       }
+      
+
+      for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++);
+
+      if (signum == 0)
+       {
+         /* It is the first argument--must be the signal to operate on.  */
+         if (digits == wordlen)
+           {
+             /* Numeric.  */
+             signum = atoi (p);
+             if (signum <= 0 || signum >= NSIG)
+               {
+                 p[wordlen] = '\0';
+                 error ("Invalid signal %s given as argument to \"handle\".", p);
+               }
+           }
+         else
+           {
+             /* Symbolic.  */
+             signum = sig_number (p);
+             if (signum == -1)
+               error ("No such signal \"%s\"", p);
+           }
+
+         if (signum == SIGTRAP || signum == SIGINT)
+           {
+             if (!query ("SIG%s is used by the debugger.\nAre you sure you want to change it? ", sig_abbrev (signum)))
+               error ("Not confirmed.");
+           }
+       }
+      /* Else, if already got a signal number, look for flag words
+        saying what to do for it.  */
+      else if (!strncmp (p, "stop", wordlen))
+       {
+         signal_stop[signum] = 1;
+         signal_print[signum] = 1;
+       }
+      else if (wordlen >= 2 && !strncmp (p, "print", wordlen))
+       signal_print[signum] = 1;
+      else if (wordlen >= 2 && !strncmp (p, "pass", wordlen))
+       signal_program[signum] = 1;
+      else if (!strncmp (p, "ignore", wordlen))
+       signal_program[signum] = 0;
+      else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen))
+       signal_stop[signum] = 0;
+      else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen))
+       {
+         signal_print[signum] = 0;
+         signal_stop[signum] = 0;
+       }
+      else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen))
+       signal_program[signum] = 0;
+      else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen))
+       signal_program[signum] = 1;
+      /* Not a number and not a recognized flag word => complain.  */
+      else
+       {
+         error ("Unrecognized flag word: \"%s\".", p);
+       }
+
+      /* Find start of next word.  */
+      p = nextarg;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+
+  if (from_tty)
+    {
+      /* Show the results.  */
+      sig_print_header ();
+      sig_print_info (signum);
+    }
+}
+
+/* Print current contents of the tables set by the handle command.  */
+
+static void
+signals_info (signum_exp)
+     char *signum_exp;
+{
+  register int i;
+  sig_print_header ();
+
+  if (signum_exp)
+    {
+      /* First see if this is a symbol name.  */
+      i = sig_number (signum_exp);
+      if (i == -1)
+       {
+         /* Nope, maybe it's an address which evaluates to a signal
+            number.  */
+         i = parse_and_eval_address (signum_exp);
+         if (i >= NSIG || i < 0)
+           error ("Signal number out of bounds.");
+       }
+      sig_print_info (i);
+      return;
+    }
+
+  printf_filtered ("\n");
+  for (i = 0; i < NSIG; i++)
+    {
+      QUIT;
+
+      sig_print_info (i);
+    }
+
+  printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
+}
+\f
+/* Save all of the information associated with the inferior<==>gdb
+   connection.  INF_STATUS is a pointer to a "struct inferior_status"
+   (defined in inferior.h).  */
+
+void
+save_inferior_status (inf_status, restore_stack_info)
+     struct inferior_status *inf_status;
+     int restore_stack_info;
+{
+  inf_status->pc_changed = pc_changed;
+  inf_status->stop_signal = stop_signal;
+  inf_status->stop_pc = stop_pc;
+  inf_status->stop_frame_address = stop_frame_address;
+  inf_status->stop_step = stop_step;
+  inf_status->stop_stack_dummy = stop_stack_dummy;
+  inf_status->stopped_by_random_signal = stopped_by_random_signal;
+  inf_status->trap_expected = trap_expected;
+  inf_status->step_range_start = step_range_start;
+  inf_status->step_range_end = step_range_end;
+  inf_status->step_frame_address = step_frame_address;
+  inf_status->step_over_calls = step_over_calls;
+  inf_status->step_resume_break_address = step_resume_break_address;
+  inf_status->stop_after_trap = stop_after_trap;
+  inf_status->stop_soon_quietly = stop_soon_quietly;
+  /* Save original bpstat chain here; replace it with copy of chain. 
+     If caller's caller is walking the chain, they'll be happier if we
+     hand them back the original chain when restore_i_s is called.  */
+  inf_status->stop_bpstat = stop_bpstat;
+  stop_bpstat = bpstat_copy (stop_bpstat);
+  inf_status->breakpoint_proceeded = breakpoint_proceeded;
+  inf_status->restore_stack_info = restore_stack_info;
+  inf_status->proceed_to_finish = proceed_to_finish;
+  
+  bcopy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+  
+  record_selected_frame (&(inf_status->selected_frame_address),
+                        &(inf_status->selected_level));
+  return;
+}
+
+void
+restore_inferior_status (inf_status)
+     struct inferior_status *inf_status;
+{
+  FRAME fid;
+  int level = inf_status->selected_level;
+
+  pc_changed = inf_status->pc_changed;
+  stop_signal = inf_status->stop_signal;
+  stop_pc = inf_status->stop_pc;
+  stop_frame_address = inf_status->stop_frame_address;
+  stop_step = inf_status->stop_step;
+  stop_stack_dummy = inf_status->stop_stack_dummy;
+  stopped_by_random_signal = inf_status->stopped_by_random_signal;
+  trap_expected = inf_status->trap_expected;
+  step_range_start = inf_status->step_range_start;
+  step_range_end = inf_status->step_range_end;
+  step_frame_address = inf_status->step_frame_address;
+  step_over_calls = inf_status->step_over_calls;
+  step_resume_break_address = inf_status->step_resume_break_address;
+  stop_after_trap = inf_status->stop_after_trap;
+  stop_soon_quietly = inf_status->stop_soon_quietly;
+  bpstat_clear (&stop_bpstat);
+  stop_bpstat = inf_status->stop_bpstat;
+  breakpoint_proceeded = inf_status->breakpoint_proceeded;
+  proceed_to_finish = inf_status->proceed_to_finish;
+
+  bcopy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
+
+  /* The inferior can be gone if the user types "print exit(0)"
+     (and perhaps other times).  */
+  if (target_has_stack && inf_status->restore_stack_info)
+    {
+      fid = find_relative_frame (get_current_frame (),
+                                &level);
+
+      if (fid == 0 ||
+         FRAME_FP (fid) != inf_status->selected_frame_address ||
+         level != 0)
+       {
+#if 0
+         /* I'm not sure this error message is a good idea.  I have
+            only seen it occur after "Can't continue previously
+            requested operation" (we get called from do_cleanups), in
+            which case it just adds insult to injury (one confusing
+            error message after another.  Besides which, does the
+            user really care if we can't restore the previously
+            selected frame?  */
+         fprintf (stderr, "Unable to restore previously selected frame.\n");
+#endif
+         select_frame (get_current_frame (), 0);
+         return;
+       }
+      
+      select_frame (fid, inf_status->selected_level);
+    }
+}
+
+\f
+void
+_initialize_infrun ()
+{
+  register int i;
+
+  add_info ("signals", signals_info,
+           "What debugger does when program gets various signals.\n\
+Specify a signal number as argument to print info on that signal only.");
+
+  add_com ("handle", class_run, handle_command,
+          "Specify how to handle a signal.\n\
+Args are signal number followed by flags.\n\
+Flags allowed are \"stop\", \"print\", \"pass\",\n\
+ \"nostop\", \"noprint\" or \"nopass\".\n\
+Print means print a message if this signal happens.\n\
+Stop means reenter debugger if this signal happens (implies print).\n\
+Pass means let program see this signal; otherwise program doesn't know.\n\
+Pass and Stop may be combined.");
+
+  for (i = 0; i < NSIG; i++)
+    {
+      signal_stop[i] = 1;
+      signal_print[i] = 1;
+      signal_program[i] = 1;
+    }
+
+  /* Signals caused by debugger's own actions
+     should not be given to the program afterwards.  */
+  signal_program[SIGTRAP] = 0;
+  signal_program[SIGINT] = 0;
+
+  /* Signals that are not errors should not normally enter the debugger.  */
+#ifdef SIGALRM
+  signal_stop[SIGALRM] = 0;
+  signal_print[SIGALRM] = 0;
+#endif /* SIGALRM */
+#ifdef SIGVTALRM
+  signal_stop[SIGVTALRM] = 0;
+  signal_print[SIGVTALRM] = 0;
+#endif /* SIGVTALRM */
+#ifdef SIGPROF
+  signal_stop[SIGPROF] = 0;
+  signal_print[SIGPROF] = 0;
+#endif /* SIGPROF */
+#ifdef SIGCHLD
+  signal_stop[SIGCHLD] = 0;
+  signal_print[SIGCHLD] = 0;
+#endif /* SIGCHLD */
+#ifdef SIGCLD
+  signal_stop[SIGCLD] = 0;
+  signal_print[SIGCLD] = 0;
+#endif /* SIGCLD */
+#ifdef SIGIO
+  signal_stop[SIGIO] = 0;
+  signal_print[SIGIO] = 0;
+#endif /* SIGIO */
+#ifdef SIGURG
+  signal_stop[SIGURG] = 0;
+  signal_print[SIGURG] = 0;
+#endif /* SIGURG */
+}
+
diff --git a/gdb/mtrace.awk b/gdb/mtrace.awk
new file mode 100755 (executable)
index 0000000..d7689ce
--- /dev/null
@@ -0,0 +1,36 @@
+#
+#  Awk program to analyze mtrace.c output.
+#
+$1 == "+"      { if (allocated[$2] != "")
+                   print "+", $2, "Alloc", NR, "duplicate:", allocated[$2];
+                 else
+                   allocated[$2] = $3;
+               }
+$1 == "-"      { if (allocated[$2] != "") {
+                   allocated[$2] = "";
+                   if (allocated[$2] != "")
+                       print "DELETE FAILED", $2, allocated[$2];
+                 } else
+                   print "-", $2, "Free", NR, "was never alloc'd";
+               }
+$1 == "<"      { if (allocated[$2] != "")
+                   allocated[$2] = "";
+                 else
+                   print "-", $2, "Realloc", NR, "was never alloc'd";
+               }
+$1 == ">"      { if (allocated[$2] != "")
+                   print "+", $2, "Realloc", NR, "duplicate:", allocated[$2];
+                 else
+                   allocated[$2] = $3;
+               }
+
+# Ignore "= Start"
+$1 == "="      { }
+# Ignore failed realloc attempts for now
+$1 == "!"      { }
+
+
+END            { for (x in allocated) 
+                   if (allocated[x] != "")
+                     print "+", x, allocated[x];
+               }
diff --git a/gdb/mtrace.c b/gdb/mtrace.c
new file mode 100755 (executable)
index 0000000..2b8222f
--- /dev/null
@@ -0,0 +1,129 @@
+/* More debugging hooks for `malloc'.
+   Copyright 1991 Free Software Foundation
+                 Written April 2, 1991 by John Gilmore of Cygnus Support
+                 Based on mcheck.c by Mike Haertel.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#include <stdio.h>
+#include "ansidecl.h"
+#include <stdlib.h>
+#include "gmalloc.h"
+
+extern char *getenv();
+
+FILE *mallstream;
+char mallenv[] = "MALLOC_TRACE";
+static char mallbuf[BUFSIZ];           /* Buffer for the output */
+
+/* Address to breakpoint on accesses to... */
+PTR mallwatch;
+
+/* Old hook values.  */
+static void EXFUN((*old_free_hook), (PTR ptr));
+static PTR EXFUN((*old_malloc_hook), (size_t size));
+static PTR EXFUN((*old_realloc_hook), (PTR ptr, size_t size));
+
+/* This function is called when the block being alloc'd, realloc'd, or
+   freed has an address matching the variable "mallwatch".  In a debugger,
+   set "mallwatch" to the address of interest, then put a breakpoint on
+   tr_break.  */
+
+void
+tr_break()
+{
+  ;
+}
+
+static void
+DEFUN(tr_freehook, (ptr), PTR ptr)
+{
+  fprintf(mallstream, "- %08x\n", ptr);        /* Be sure to print it first */
+  if (ptr == mallwatch)
+    tr_break();
+  __free_hook = old_free_hook;
+  free(ptr);
+  __free_hook = tr_freehook;
+}
+
+static PTR
+DEFUN(tr_mallochook, (size), size_t size)
+{
+  PTR hdr;
+
+  __malloc_hook = old_malloc_hook;
+  hdr = malloc(size);
+  __malloc_hook = tr_mallochook;
+
+  /* We could be printing a NULL here; that's OK */
+  fprintf (mallstream, "+ %08x %x\n", hdr, size);
+
+  if (hdr == mallwatch)
+    tr_break();
+
+  return hdr;
+}
+
+static PTR
+DEFUN(tr_reallochook, (ptr, size), PTR ptr AND size_t size)
+{
+  PTR hdr;
+
+  if (ptr == mallwatch)
+    tr_break();
+
+  __free_hook = old_free_hook;
+  __malloc_hook = old_malloc_hook;
+  __realloc_hook = old_realloc_hook;
+  hdr = realloc(ptr, size);
+  __free_hook = tr_freehook;
+  __malloc_hook = tr_mallochook;
+  __realloc_hook = tr_reallochook;
+  if (hdr == NULL) {
+    fprintf (mallstream, "! %08x %x\n", ptr, size);    /* Failed realloc */
+  } else {
+    fprintf (mallstream, "< %08x\n> %08x %x\n", ptr, hdr, size);
+  }
+
+  if (hdr == mallwatch)
+    tr_break();
+
+  return hdr;
+}
+
+void
+mtrace()
+{
+  char *mallfile;
+
+  mallfile = getenv (mallenv);
+  if (mallfile) {
+    mallstream = fopen (mallfile, "w");
+    if (mallstream) {
+      /* Be sure it doesn't malloc its buffer! */
+      setbuf (mallstream, mallbuf);
+      fprintf (mallstream, "= Start\n");
+      old_free_hook = __free_hook;
+      __free_hook = tr_freehook;
+      old_malloc_hook = __malloc_hook;
+      __malloc_hook = tr_mallochook;
+      old_realloc_hook = __realloc_hook;
+      __realloc_hook = tr_reallochook;
+    }
+  }
+}
diff --git a/gdb/rem-m68k.shar b/gdb/rem-m68k.shar
new file mode 100755 (executable)
index 0000000..aeb76e5
--- /dev/null
@@ -0,0 +1,893 @@
+# This is a shell archive.  Remove anything before this line,
+# then unpack it by saving it in a file and typing "sh file".
+#
+# Wrapped by Glenn Engel <glenne@labgre> on Mon Jun 12 15:19:20 1989
+#
+# This archive contains:
+#      remcom.c        
+#
+
+LANG=""; export LANG
+PATH=/bin:/usr/bin:$PATH; export PATH
+
+echo x - remcom.c
+cat >remcom.c <<'@EOF'
+
+/****************************************************************************
+
+               THIS SOFTWARE IS NOT COPYRIGHTED  
+   
+   HP offers the following for use in the public domain.  HP makes no
+   warranty with regard to the software or it's performance and the 
+   user accepts the software "AS IS" with all faults.
+
+   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *  $Header$                   
+ *
+ *  $Module name: remcom.c $  
+ *  $Revision$
+ *  $Date$
+ *  $Contributor:     Lake Stevens Instrument Division$
+ *  
+ *  $Description:     low level support for gdb debugger. $
+ *
+ *  $Considerations:  only works on target hardware $
+ *
+ *  $Written by:      Glenn Engel $
+ *  $ModuleState:     Experimental $ 
+ *
+ *  $NOTES:           See Below $
+ * 
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a trap #1.
+ *  
+ *  Some explanation is probably necessary to explain how exceptions are
+ *  handled.  When an exception is encountered the 68000 pushes the current
+ *  program counter and status register onto the supervisor stack and then
+ *  transfers execution to a location specified in it's vector table.
+ *  The handlers for the exception vectors are hardwired to jmp to an address
+ *  given by the relation:  (exception - 256) * 6.  These are decending 
+ *  addresses starting from -6, -12, -18, ...  By allowing 6 bytes for
+ *  each entry, a jsr, jmp, bsr, ... can be used to enter the exception 
+ *  handler.  Using a jsr to handle an exception has an added benefit of
+ *  allowing a single handler to service several exceptions and use the
+ *  return address as the key differentiation.  The vector number can be
+ *  computed from the return address by [ exception = (addr + 1530) / 6 ].
+ *  The sole purpose of the routine _catchException is to compute the
+ *  exception number and push it on the stack in place of the return address.
+ *  The external function exceptionHandler() is
+ *  used to attach a specific handler to a specific 68k exception.
+ *  For 68020 machines, the ability to have a return address around just
+ *  so the vector can be determined is not necessary because the '020 pushes an
+ *  extra word onto the stack containing the vector offset
+ * 
+ *  Because gdb will sometimes write to the stack area to execute function
+ *  calls, this program cannot rely on using the supervisor stack so it
+ *  uses it's own stack area reserved in the int array remcomStack.  
+ * 
+ *************
+ *
+ *    The following gdb commands are supported:
+ * 
+ * command          function                               Return value
+ * 
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ * 
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ * 
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ * 
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ * 
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ * 
+ * All commands and responses are sent with a packet which includes a 
+ * checksum.  A packet consists of 
+ * 
+ * $<packet info>#<checksum>.
+ * 
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ * 
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ * 
+ * Example:
+ * 
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ * 
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/************************************************************************
+ *
+ * external low-level support routines 
+ */
+typedef void (*ExceptionHook)(int);   /* pointer to function with int parm */
+typedef void (*Function)();           /* pointer to a function */
+
+extern putDebugChar();   /* write a single character      */
+extern getDebugChar();   /* read and return a single char */
+
+extern Function exceptionHandler();  /* assign an exception handler */
+extern ExceptionHook exceptionHook;  /* hook variable for errors/exceptions */
+
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized;  /* boolean flag. != 0 means we've been initialized */
+
+int     remote_debug = 0;
+/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */ 
+
+char hexchars[]="0123456789abcdef";
+
+/* there are 180 bytes of registers on a 68020 w/68881      */
+/* many of the fpa registers are 12 byte (96 bit) registers */
+#define NUMREGBYTES 180
+enum regnames {D0,D1,D2,D3,D4,D5,D6,D7, 
+               A0,A1,A2,A3,A4,A5,A6,A7, 
+               PS,PC,
+               FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
+               FPCONTROL,FPSTATUS,FPIADDR
+              };
+
+typedef struct FrameStruct
+{
+    struct FrameStruct  *previous;
+    int       exceptionPC;      /* pc value when this frame created */
+    int       exceptionVector;  /* cpu vector causing exception     */
+    short     frameSize;        /* size of cpu frame in words       */
+    short     sr;               /* for 68000, this not always sr    */
+    int       pc;
+    short     format;
+    int       fsaveHeader;
+    int       morejunk[0];        /* exception frame, fp save... */
+} Frame;
+
+#define FRAMESIZE 500
+static Frame *lastFrame;
+static int   frameStack[FRAMESIZE];
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGBYTES/4];
+int superStack;
+
+static int remcomStack[400];
+static int* stackPtr = &remcomStack[399];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.  
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+/* the size of the exception stack on the 68020 varies with the type of
+ * exception.  The following table is the number of WORDS used
+ * for each exception format.
+ */
+static short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,4,4,4,4 };
+
+/************* jump buffer used for setjmp/longjmp **************************/
+jmp_buf env;
+
+/***************************  ASSEMBLY CODE MACROS *************************/
+/*                                                                        */
+
+#ifdef __HAVE_68881__
+/* do an fsave, then remember the address to begin a restore from */
+#define SAVE_FP_REGS()    asm(" fsave   a0@-");                \
+                         asm(" fmovemx fp0-fp7,_registers+72");        \
+                         asm(" fmoveml fpcr/fpsr/fpi,_registers+168"); 
+#define RESTORE_FP_REGS() asm(" fmoveml _registers+168,fpcr/fpsr/fpi"); \
+                         asm(" fmovemx _registers+72,fp0-fp7");        \
+                         asm(" frestore a0@+");
+#else
+#define SAVE_FP_REGS()
+#define RESTORE_FP_REGS()
+#endif /* __HAVE_68881__ */
+
+asm("
+.text
+.globl _return_to_super
+_return_to_super:
+        movel   _registers+60,sp /* get new stack pointer */        
+        movel   _lastFrame,a0   /* get last frame info  */              
+        bra     return_to_any
+
+.globl _return_to_user
+_return_to_user:
+        movel   _registers+60,a0 /* get usp */                          
+        movel   a0,usp           /* set usp */                         
+        movel   _superStack,sp  /* get original stack pointer */        
+
+return_to_any:
+        movel   _lastFrame,a0   /* get last frame info  */              
+        movel   a0@+,_lastFrame /* link in previous frame     */        
+        addql   #8,a0           /* skip over pc, vector#*/              
+        movew   a0@+,d0         /* get # of words in cpu frame */       
+        addw    d0,a0           /* point to end of data        */       
+        addw    d0,a0           /* point to end of data        */       
+        movel   a0,a1                                                   
+#                                                                       
+# copy the stack frame                                                  
+        subql   #1,d0                                                   
+copyUserLoop:                                                               
+        movew   a1@-,sp@-                                               
+        dbf     d0,copyUserLoop                                             
+");                                                                     
+        RESTORE_FP_REGS()                                              
+   asm("   moveml  _registers,d0-d7/a0-a6");                           
+   asm("   rte");  /* pop and go! */                                    
+
+#define DISABLE_INTERRUPTS()   asm("         oriw   #0x0700,sr");
+#define BREAKPOINT() asm("   trap #1");
+
+/* this function is called immediately when a level 7 interrupt occurs */
+/* if the previous interrupt level was 7 then we're already servicing  */
+/* this interrupt and an rte is in order to return to the debugger.    */
+/* For the 68000, the offset for sr is 6 due to the jsr return address */
+asm("
+.text
+.globl __debug_level7
+__debug_level7:
+       movew   d0,sp@-");
+#ifdef mc68020
+asm("  movew   sp@(2),d0");
+#else
+asm("  movew   sp@(6),d0");
+#endif
+asm("  andiw   #0x700,d0
+       cmpiw   #0x700,d0
+       beq     _already7
+        movew   sp@+,d0        
+        bra     __catchException
+_already7:
+       movew   sp@+,d0");
+#ifndef mc68020
+asm("  lea     sp@(4),sp");     /* pull off 68000 return address */
+#endif
+asm("  rte");
+
+extern void _catchException();
+
+#ifdef mc68020
+/* This function is called when a 68020 exception occurs.  It saves
+ * all the cpu and fpcp regs in the _registers array, creates a frame on a
+ * linked list of frames which has the cpu and fpcp stack frames needed
+ * to properly restore the context of these processors, and invokes
+ * an exception handler (remcom_handler).
+ *
+ * stack on entry:                       stack on exit:
+ *   N bytes of junk                     exception # MSWord
+ *   Exception Format Word               exception # MSWord
+ *   Program counter LSWord              
+ *   Program counter MSWord             
+ *   Status Register                    
+ *                                       
+ *                                       
+ */
+asm(" 
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+        moveml  d0-d7/a0-a6,_registers /* save registers        */
+       movel   _lastFrame,a0   /* last frame pointer */
+");
+SAVE_FP_REGS();        
+asm("
+       lea     _registers,a5   /* get address of registers     */
+        movew   sp@,d1          /* get status register          */
+        movew   d1,a5@(66)      /* save sr                     */      
+       movel   sp@(2),a4       /* save pc in a4 for later use  */
+        movel   a4,a5@(68)      /* save pc in _regisers[]              */
+
+#
+# figure out how many bytes in the stack frame
+       movew   sp@(6),d0       /* get '020 exception format    */
+        movew   d0,d2           /* make a copy of format word   */
+        andiw   #0xf000,d0      /* mask off format type         */
+        rolw    #5,d0           /* rotate into the low byte *2  */
+        lea     _exceptionSize,a1   
+        addw    d0,a1           /* index into the table         */
+       movew   a1@,d0          /* get number of words in frame */
+        movew   d0,d3           /* save it                      */
+        subw    d0,a0          /* adjust save pointer          */
+        subw    d0,a0          /* adjust save pointer(bytes)   */
+       movel   a0,a1           /* copy save pointer            */
+       subql   #1,d0           /* predecrement loop counter    */
+#
+# copy the frame
+saveFrameLoop:
+       movew   sp@+,a1@+
+       dbf     d0,saveFrameLoop
+#
+# now that the stack has been clenaed,
+# save the a7 in use at time of exception
+        movel   sp,_superStack  /* save supervisor sp           */
+        andiw   #0x2000,d1      /* were we in supervisor mode ? */
+        beq     userMode       
+        movel   a7,a5@(60)      /* save a7                  */
+        bra     a7saveDone
+userMode:  
+       movel   usp,a1          
+        movel   a1,a5@(60)      /* save user stack pointer     */
+a7saveDone:
+
+#
+# save size of frame
+        movew   d3,a0@-
+
+#
+# compute exception number
+       andl    #0xfff,d2       /* mask off vector offset       */
+       lsrw    #2,d2           /* divide by 4 to get vect num  */
+        movel   d2,a0@-         /* save it                      */
+#
+# save pc causing exception
+        movel   a4,a0@-
+#
+# save old frame link and set the new value
+       movel   _lastFrame,a1   /* last frame pointer */
+       movel   a1,a0@-         /* save pointer to prev frame   */
+        movel   a0,_lastFrame
+
+        movel   d2,sp@-                /* push exception num           */
+       movel   _exceptionHook,a0  /* get address of handler */
+        jbsr    a0@             /* and call it */
+        jmp     __returnFromException     /* now, return        */
+");
+#else /* mc68000 */
+/* This function is called when an exception occurs.  It translates the
+ * return address found on the stack into an exception vector # which
+ * is then handled by either handle_exception or a system handler.
+ * _catchException provides a front end for both.  
+ *
+ * stack on entry:                       stack on exit:
+ *   Program counter MSWord              exception # MSWord 
+ *   Program counter LSWord              exception # MSWord
+ *   Status Register                     
+ *   Return Address  MSWord              
+ *   Return Address  LSWord             
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+        moveml d0-d7/a0-a6,_registers  /* save registers               */
+       movel   _lastFrame,a0   /* last frame pointer */
+");
+SAVE_FP_REGS();        
+asm("
+        lea     _registers,a5   /* get address of registers     */
+        movel   sp@+,d2         /* pop return address           */
+       addl    #1530,d2        /* convert return addr to       */
+       divs    #6,d2           /*  exception number            */
+       extl    d2   
+
+        moveql  #3,d3           /* assume a three word frame     */
+
+        cmpiw   #3,d2           /* bus error or address error ? */
+        bgt     normal          /* if >3 then normal error      */
+        movel   sp@+,a0@-       /* copy error info to frame buff*/
+        movel   sp@+,a0@-       /* these are never used         */
+        moveql  #7,d3           /* this is a 7 word frame       */
+     
+normal:   
+       movew   sp@+,d1         /* pop status register          */
+        movel   sp@+,a4         /* pop program counter          */
+        movew   d1,a5@(66)      /* save sr                     */      
+        movel   a4,a5@(68)      /* save pc in _regisers[]              */
+        movel   a4,a0@-         /* copy pc to frame buffer      */
+       movew   d1,a0@-         /* copy sr to frame buffer      */
+
+        movel   sp,_superStack  /* save supervisor sp          */
+
+        andiw   #0x2000,d1      /* were we in supervisor mode ? */
+        beq     userMode       
+        movel   a7,a5@(60)      /* save a7                  */
+        bra     saveDone             
+userMode:
+        movel   usp,a1         /* save user stack pointer      */
+        movel   a1,a5@(60)      /* save user stack pointer     */
+saveDone:
+
+        movew   d3,a0@-         /* push frame size in words     */
+        movel   d2,a0@-         /* push vector number           */
+        movel   a4,a0@-         /* push exception pc            */
+
+#
+# save old frame link and set the new value
+       movel   _lastFrame,a1   /* last frame pointer */
+       movel   a1,a0@-         /* save pointer to prev frame   */
+        movel   a0,_lastFrame
+
+        movel   d2,sp@-                /* push exception num           */
+       movel   _exceptionHook,a0  /* get address of handler */
+        jbsr    a0@             /* and call it */
+        jmp     __returnFromException     /* now, return        */
+");
+#endif
+
+
+/*
+ * remcomHandler is a front end for handle_exception.  It moves the
+ * stack pointer into an area reserved for debugger use in case the
+ * breakpoint happened in supervisor mode.
+ */
+asm("_remcomHandler:");
+asm("           addl    #4,sp");        /* pop off return address     */
+asm("           movel   sp@+,d0");      /* get the exception number   */
+asm("          movel   _stackPtr,sp"); /* move to remcom stack area  */
+asm("          movel   d0,sp@-");      /* push exception onto stack  */
+asm("          jbsr    _handle_exception");    /* this never returns */
+asm("           rts");                  /* return */
+
+void _returnFromException( Frame *frame )
+{
+    /* if no existing frame, dummy one up */
+    if (! frame)
+    {
+        frame = lastFrame -1;
+        frame->frameSize = 4;
+        frame->format = 0;
+        frame->fsaveHeader = 0;
+        frame->previous = lastFrame;
+    }
+
+#ifndef mc68020
+    /* a 68000 cannot use the internal info pushed onto a bus error
+     * or address error frame when doing an RTE so don't put this info
+     * onto the stack or the stack will creep every time this happens.
+     */
+    frame->frameSize=3;
+#endif
+
+    /* throw away any frames in the list after this frame */
+    lastFrame = frame;
+
+    frame->sr = registers[(int) PS];
+    frame->pc = registers[(int) PC];
+
+    if (registers[(int) PS] & 0x2000)
+    { 
+        /* return to supervisor mode... */
+        return_to_super();
+    }
+    else
+    { /* return to user mode */
+        return_to_user();
+    }
+}
+
+int hex(ch)
+char ch;
+{
+  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+  return (0);
+}
+
+
+/* scan for the sequence $<data>#<checksum>     */
+void getpacket(buffer)
+char * buffer;
+{
+  unsigned char checksum;
+  unsigned char xmitcsum;
+  int  i;
+  int  count;
+  char ch;
+  
+  do {
+    /* wait around for the start character, ignore all other characters */
+    while ((ch = getDebugChar()) != '$'); 
+    checksum = 0;
+    count = 0;
+    
+    /* now, read until a # or end of buffer is found */
+    while (count < BUFMAX) {
+      ch = getDebugChar();
+      if (ch == '#') break;
+      checksum = checksum + ch;
+      buffer[count] = ch;
+      count = count + 1;
+      }
+    buffer[count] = 0;
+
+    if (ch == '#') {
+      xmitcsum = hex(getDebugChar()) << 4;
+      xmitcsum += hex(getDebugChar());
+      if ((remote_debug ) && (checksum != xmitcsum)) {
+        fprintf(stderr,"bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
+                                                    checksum,xmitcsum,buffer);
+      }
+      
+      if (checksum != xmitcsum) putDebugChar('-');  /* failed checksum */ 
+      else {
+        putDebugChar('+');  /* successful transfer */
+        /* if a sequence char is present, reply the sequence ID */
+        if (buffer[2] == ':') {
+           putDebugChar( buffer[0] );
+           putDebugChar( buffer[1] );
+           /* remove sequence chars from buffer */
+           count = strlen(buffer);
+           for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+        } 
+      } 
+    } 
+  } while (checksum != xmitcsum);
+  
+}
+
+/* send the packet in buffer.  The host get's one chance to read it.  
+   This routine does not wait for a positive acknowledge.  */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+  unsigned char checksum;
+  int  count;
+  char ch;
+  
+  /*  $<packet info>#<checksum>. */
+  do {
+  putDebugChar('$');
+  checksum = 0;
+  count    = 0;
+  
+  while (ch=buffer[count]) {
+    if (! putDebugChar(ch)) return;
+    checksum += ch;
+    count += 1;
+  }
+  
+  putDebugChar('#');
+  putDebugChar(hexchars[checksum >> 4]);
+  putDebugChar(hexchars[checksum % 16]);
+
+  } while (1 == 0);  /* (getDebugChar() != '+'); */
+  
+}
+
+static char  inbuffer[BUFMAX];
+static char  outbuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+  if (remote_debug) fprintf(stderr,format,parm);
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+char* mem2hex(mem, buf, count)
+char* mem;
+char* buf;
+int   count;
+{
+      int i;
+      unsigned char ch;
+      for (i=0;i<count;i++) {
+          ch = *mem++;
+          *buf++ = hexchars[ch >> 4];
+          *buf++ = hexchars[ch % 16];
+      }
+      *buf = 0; 
+      return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count)
+char* buf;
+char* mem;
+int   count;
+{
+      int i;
+      unsigned char ch;
+      for (i=0;i<count;i++) {
+          ch = hex(*buf++) << 4;
+          ch = ch + hex(*buf++);
+          *mem++ = ch;
+      }
+      return(mem);
+}
+
+/* a bus error has occurred, perform a longjmp
+   to return execution and allow handling of the error */
+
+void handle_buserror()
+{
+  longjmp(env,1);
+}
+
+/* this function takes the 68000 exception number and attempts to 
+   translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+  int sigval;
+  switch (exceptionVector) {
+    case 2 : sigval = 10; break; /* bus error           */
+    case 3 : sigval = 10; break; /* address error       */
+    case 4 : sigval = 4;  break; /* illegal instruction */
+    case 5 : sigval = 8;  break; /* zero divide         */
+    case 6 : sigval = 16; break; /* chk instruction     */
+    case 7 : sigval = 16; break; /* trapv instruction   */
+    case 8 : sigval = 11; break; /* privilege violation */
+    case 9 : sigval = 5;  break; /* trace trap          */
+    case 10: sigval = 4;  break; /* line 1010 emulator  */
+    case 11: sigval = 4;  break; /* line 1111 emulator  */
+    case 31: sigval = 2;  break; /* interrupt           */
+    case 33: sigval = 5;  break; /* breakpoint          */
+    case 40: sigval = 8;  break; /* floating point err  */
+    case 48: sigval = 8;  break; /* floating point err  */
+    case 49: sigval = 8;  break; /* floating point err  */
+    case 50: sigval = 8;  break; /* zero divide         */
+    case 51: sigval = 8;  break; /* underflow           */
+    case 52: sigval = 8;  break; /* operand error       */
+    case 53: sigval = 8;  break; /* overflow            */
+    case 54: sigval = 8;  break; /* NAN                 */
+    default: 
+      sigval = 7;         /* "software generated"*/
+  }
+  return (sigval);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+  int    sigval;
+  int    addr, length;
+  char * ptr;
+  int    newPC;
+  Frame  *frame;
+  
+  if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n", 
+                           exceptionVector,
+                           registers[ PS ], 
+                           registers[ PC ]);
+
+  /* reply to host that an exception has occurred */
+  sigval = computeSignal( exceptionVector );
+  sprintf(outbuffer,"S%02x",sigval);
+  putpacket(outbuffer); 
+
+  while (1==1) { 
+    error = 0;
+    outbuffer[0] = 0;
+    getpacket(inbuffer);
+    switch (inbuffer[0]) {
+      case '?' : sprintf(outbuffer,"S%02x",sigval);
+                 break; 
+      case 'd' : remote_debug = !(remote_debug);  /* toggle debug flag */
+                 break; 
+      case 'g' : /* return the value of the CPU registers */
+                mem2hex((char*) registers, outbuffer, NUMREGBYTES);
+                break;
+      case 'G' : /* set the value of the CPU registers - return OK */
+                hex2mem(&inbuffer[1], (char*) registers, NUMREGBYTES);
+                strcpy(outbuffer,"OK");
+                break;
+      
+      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+      case 'm' : 
+               if (setjmp(env) == 0) {
+                   exceptionHandler(2,handle_buserror); 
+
+                   if (2 == sscanf(&inbuffer[1],"%x,%x",&addr,&length)) {
+                     mem2hex((char*) addr, outbuffer, length);
+                   }
+                   else {
+                     strcpy(outbuffer,"E01");
+                     debug_error("malformed read memory command: %s",inbuffer);
+                     }     
+                } 
+               else {
+                 exceptionHandler(2,_catchException);   
+                 strcpy(outbuffer,"E03");
+                 debug_error("bus error");
+                 }     
+                
+               /* restore handler for bus error */
+               exceptionHandler(2,_catchException);   
+               break;
+      
+      /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+      case 'M' : 
+               if (setjmp(env) == 0) {
+                   exceptionHandler(2,handle_buserror); 
+
+                   if (2 == sscanf(&inbuffer[1],"%x,%x:",&addr,&length)) {
+                     ptr = strchr(inbuffer,':');
+                     ptr += 1; /* point 1 past the colon */
+                     hex2mem(ptr, (char*) addr, length);
+                     strcpy(outbuffer,"OK");
+                   }
+                   else {
+                     strcpy(outbuffer,"E02");
+                     debug_error("malformed write memory command: %s",inbuffer);
+                     }     
+                } 
+               else {
+                 exceptionHandler(2,_catchException);   
+                 strcpy(outbuffer,"E03");
+                 debug_error("bus error");
+                 }     
+                break;
+     
+     /* cAA..AA    Continue at address AA..AA(optional) */
+     /* sAA..AA   Step one instruction from AA..AA(optional) */
+     case 'c' : 
+     case 's' : 
+          /* try to read optional parameter, addr unchanged if no parm */
+          if (1 == sscanf(&inbuffer[1],"%x",&registers[ PC ])); 
+          newPC = registers[ PC];
+          
+          /* clear the trace bit */
+          registers[ PS ] &= 0x7fff;
+          
+          /* set the trace bit if we're stepping */
+          if (inbuffer[0] == 's') registers[ PS ] |= 0x8000;
+          
+          /*
+           * look for newPC in the linked list of exception frames.
+           * if it is found, use the old frame it.  otherwise,
+           * fake up a dummy frame in returnFromException().
+           */
+          if (remote_debug) printf("new pc = 0x%x\n",newPC);
+          frame = lastFrame;
+          while (frame)
+          {
+              if (remote_debug)
+                  printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+                         frame,frame->exceptionPC,
+                         frame->exceptionVector);
+              if (frame->exceptionPC == newPC) break;  /* bingo! a match */
+              /*
+               * for a breakpoint instruction, the saved pc may
+               * be off by two due to re-executing the instruction
+               * replaced by the trap instruction.  Check for this.
+               */
+              if ((frame->exceptionVector == 33) &&
+                  (frame->exceptionPC == (newPC+2))) break;
+              frame = frame->previous;
+          }
+          
+          /*
+           * If we found a match for the PC AND we are not returning
+           * as a result of a breakpoint (33),
+           * trace exception (9), nmi (31), jmp to
+           * the old exception handler as if this code never ran.
+           */
+          if (frame) 
+          {
+              if ((frame->exceptionVector != 9)  && 
+                  (frame->exceptionVector != 31) && 
+                  (frame->exceptionVector != 33))
+              { 
+                  /*
+                   * invoke the previous handler.
+                   */
+                  if (oldExceptionHook)
+                      (*oldExceptionHook) (frame->exceptionVector);
+                  newPC = registers[ PC ];    /* pc may have changed  */
+                  if (newPC != frame->exceptionPC)
+                  {
+                      if (remote_debug)
+                          printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+                                 frame,frame->exceptionPC,
+                                 frame->exceptionVector);
+                      /* dispose of this frame, we're skipping it (longjump?)*/
+                      lastFrame = frame->previous;
+                      frame = (Frame *) 0;
+                  }
+              }
+          }         
+
+          _returnFromException( frame );
+
+          break;
+          
+      /* kill the program */
+      case 'k' :  /* do nothing */
+                break;
+      } /* switch */ 
+    
+    /* reply to the request */
+    putpacket(outbuffer); 
+    }
+}
+
+
+/* this function is used to set up exception handlers for tracing and 
+   breakpoints */
+void set_debug_traps()
+{
+extern void _debug_level7();
+extern void remcomHandler();
+int exception;
+
+  for (exception = 2; exception <= 23; exception++)
+      exceptionHandler(exception,_catchException);   
+
+  /* level 7 interrupt              */
+  exceptionHandler(31,_debug_level7);    
+  
+  /* breakpoint exception (trap #1) */
+  exceptionHandler(33,_catchException);
+  
+  /* floating point error (trap #8) */
+  exceptionHandler(40,_catchException);
+  
+  /* 48 to 54 are floating point coprocessor errors */
+  for (exception = 48; exception <= 54; exception++)
+      exceptionHandler(exception,_catchException);   
+
+  if (oldExceptionHook != remcomHandler)
+  {
+      oldExceptionHook = exceptionHook;
+      exceptionHook    = remcomHandler;
+  }
+  
+  initialized = 1;
+
+  lastFrame = (Frame *) &frameStack[FRAMESIZE-1];
+  lastFrame->previous = (Frame *) 0;
+}
+
+/* This function will generate a breakpoint exception.  It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+   
+void breakpoint()
+{
+  if (initialized) BREAKPOINT();
+}
+
+@EOF
+
+chmod 444 remcom.c
+
+exit 0
+
diff --git a/gdb/rem-multi.shar b/gdb/rem-multi.shar
new file mode 100644 (file)
index 0000000..86c9cf0
--- /dev/null
@@ -0,0 +1,1313 @@
+#!/bin/sh
+#      This is a shell archive.
+#      Run the file through sh to extract its contents.
+# shar:        Shell Archiver
+#      Run the following text with /bin/sh to create:
+#      Remote_Makefile
+#      remote_gutils.c
+#      remote_inflow.c
+#      remote_server.c
+#      remote_utils.c
+# This archive created: Fri Jun 23 17:06:55 1989
+cat << \SHAR_EOF > Remote_Makefile
+#    Makefile for the remote server for GDB, the GNU debugger.
+#    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+# 
+# This file is part of GDB.
+# 
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+# 
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+CFLAGS = -g 
+CC = cc
+
+SERVER = remote_server.o\
+                remote_inflow.o\
+                remote_utils.o\
+                remote_gutils.o 
+
+prog : $(SERVER)
+       $(CC) -g -o serve $(SERVER) 
+SHAR_EOF
+cat << \SHAR_EOF > remote_gutils.c
+/* General utility routines for the remote server for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include "defs.h"
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+   to be executed if an error happens.  */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested.  */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+   rather than waiting until QUIT is executed.  */
+
+int immediate_quit;
+\f
+/* Add a new cleanup to the cleanup_chain,
+   and return the previous chain pointer
+   to be passed later to do_cleanups or discard_cleanups.
+   Args are FUNCTION to clean up with, and ARG to pass to it.  */
+
+struct cleanup *
+make_cleanup (function, arg)
+     void (*function) ();
+     int arg;
+{
+  register struct cleanup *new
+    = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+  register struct cleanup *old_chain = cleanup_chain;
+
+  new->next = cleanup_chain;
+  new->function = function;
+  new->arg = arg;
+  cleanup_chain = new;
+
+  return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+do_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      (*ptr->function) (ptr->arg);
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+discard_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* This function is useful for cleanups.
+   Do
+
+     foo = xmalloc (...);
+     old_chain = make_cleanup (free_current_contents, &foo);
+
+   to arrange to free the object thus allocated.  */
+
+void
+free_current_contents (location)
+     char **location;
+{
+  free (*location);
+}
+\f
+/* Generally useful subroutines used throughout the program.  */
+
+/* Like malloc but get error if no storage available.  */
+
+char *
+xmalloc (size)
+     long size;
+{
+  register char *val = (char *) malloc (size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Like realloc but get error if no storage available.  */
+
+char *
+xrealloc (ptr, size)
+     char *ptr;
+     long size;
+{
+  register char *val = (char *) realloc (ptr, size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+   as the file name for which the error was encountered.
+   Then return to command level.  */
+
+void
+perror_with_name (string)
+     char *string;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+  char *err;
+  char *combined;
+
+  if (errno < sys_nerr)
+    err = sys_errlist[errno];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+   as the file name for which the error was encountered.  */
+
+void
+print_sys_errmsg (string, errcode)
+     char *string;
+     int errcode;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  char *err;
+  char *combined;
+
+  if (errcode < sys_nerr)
+    err = sys_errlist[errcode];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  printf ("%s.\n", combined);
+}
+
+void
+quit ()
+{
+  fflush (stdout);
+  ioctl (fileno (stdout), TIOCFLUSH, 0);
+  error ("Quit");
+}
+
+/* Control C comes here */
+
+void
+request_quit ()
+{
+  quit_flag = 1;
+  if (immediate_quit)
+    quit ();
+}
+
+/* Print an error message and return to command level.
+   STRING is the error message, used as a fprintf string,
+   and ARG is passed as an argument to it.  */
+
+void
+error (string, arg1, arg2, arg3)
+     char *string;
+     int arg1, arg2, arg3;
+{
+  fflush (stdout);
+  fprintf (stderr, string, arg1, arg2, arg3);
+  fprintf (stderr, "\n");
+  /************return_to_top_level ();************/ 
+}
+
+/* Print an error message and exit reporting failure.
+   This is for a error that we cannot continue from.
+   STRING and ARG are passed to fprintf.  */
+
+void
+fatal (string, arg)
+     char *string;
+     int arg;
+{
+  fprintf (stderr, "gdb: ");
+  fprintf (stderr, string, arg);
+  fprintf (stderr, "\n");
+  exit (1);
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+   (and add a null character at the end in the copy).
+   Uses malloc to get the space.  Returns the address of the copy.  */
+
+char *
+savestring (ptr, size)
+     char *ptr;
+     int size;
+{
+  register char *p = (char *) xmalloc (size + 1);
+  bcopy (ptr, p, size);
+  p[size] = 0;
+  return p;
+}
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+  register char *val = (char *) xmalloc (len);
+  strcpy (val, s1);
+  strcat (val, s2);
+  strcat (val, s3);
+  return val;
+}
+
+void
+print_spaces (n, file)
+     register int n;
+     register FILE *file;
+{
+  while (n-- > 0)
+    fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+   Takes three args which are given to printf to print the question.
+   The first, a control string, should end in "? ".
+   It should not say how to answer, because we do that.  */
+
+int
+query (ctlstr, arg1, arg2)
+     char *ctlstr;
+{
+  register int answer;
+
+  /* Automatically answer "yes" if input is not from a terminal.  */
+  /***********if (!input_from_terminal_p ())
+    return 1; *************************/ 
+
+  while (1)
+    {
+      printf (ctlstr, arg1, arg2);
+      printf ("(y or n) ");
+      fflush (stdout);
+      answer = fgetc (stdin);
+      clearerr (stdin);                /* in case of C-d */
+      if (answer != '\n')
+       while (fgetc (stdin) != '\n') clearerr (stdin);
+      if (answer >= 'a')
+       answer -= 040;
+      if (answer == 'Y')
+       return 1;
+      if (answer == 'N')
+       return 0;
+      printf ("Please answer y or n.\n");
+    }
+}
+\f
+/* Parse a C escape sequence.  STRING_PTR points to a variable
+   containing a pointer to the string to parse.  That pointer
+   is updated past the characters we use.  The value of the
+   escape sequence is returned.
+
+   A negative value means the sequence \ newline was seen,
+   which is supposed to be equivalent to nothing at all.
+
+   If \ is followed by a null character, we return a negative
+   value and leave the string pointer pointing at the null character.
+
+   If \ is followed by 000, we return 0 and leave the string pointer
+   after the zeros.  A value of 0 does not mean end of string.  */
+
+int
+parse_escape (string_ptr)
+     char **string_ptr;
+{
+  register int c = *(*string_ptr)++;
+  switch (c)
+    {
+    case 'a':
+      return '\a';
+    case 'b':
+      return '\b';
+    case 'e':
+      return 033;
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'v':
+      return '\v';
+    case '\n':
+      return -2;
+    case 0:
+      (*string_ptr)--;
+      return 0;
+    case '^':
+      c = *(*string_ptr)++;
+      if (c == '\\')
+       c = parse_escape (string_ptr);
+      if (c == '?')
+       return 0177;
+      return (c & 0200) | (c & 037);
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+      {
+       register int i = c - '0';
+       register int count = 0;
+       while (++count < 3)
+         {
+           if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+             {
+               i *= 8;
+               i += c - '0';
+             }
+           else
+             {
+               (*string_ptr)--;
+               break;
+             }
+         }
+       return i;
+      }
+    default:
+      return c;
+    }
+}
+\f
+void
+printchar (ch, stream)
+     unsigned char ch;
+     FILE *stream;
+{
+  register int c = ch;
+  if (c < 040 || c >= 0177)
+    {
+      if (c == '\n')
+       fprintf (stream, "\\n");
+      else if (c == '\b')
+       fprintf (stream, "\\b");
+      else if (c == '\t')
+       fprintf (stream, "\\t");
+      else if (c == '\f')
+       fprintf (stream, "\\f");
+      else if (c == '\r')
+       fprintf (stream, "\\r");
+      else if (c == 033)
+       fprintf (stream, "\\e");
+      else if (c == '\a')
+       fprintf (stream, "\\a");
+      else
+       fprintf (stream, "\\%03o", c);
+    }
+  else
+    {
+      if (c == '\\' || c == '"' || c == '\'')
+       fputc ('\\', stream);
+      fputc (c, stream);
+    }
+}
+SHAR_EOF
+cat << \SHAR_EOF > remote_inflow.c
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+*/
+
+#include "defs.h"
+#include "param.h"
+#include "wait.h"
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/ 
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/ 
+int quit_flag = 0; 
+char registers[REGISTER_BYTES]; 
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/ 
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+extern char **environ; 
+extern int errno;
+extern int inferior_pid; 
+void error(), quit(), perror_with_name();
+int query(); 
+void supply_register(), write_register(); 
+CORE_ADDR read_register(); 
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+
+/* Start an inferior process and returns its pid.
+   ALLARGS is a vector of program-name and args.
+   ENV is the environment vector to pass.  */
+
+int
+create_inferior (allargs, env)
+     char **allargs;
+     char **env;
+{
+  int pid;
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+
+  /* exec is said to fail if the executable is open.  */
+  /****************close_exec_file ();*****************/ 
+
+  pid = vfork ();
+  if (pid < 0)
+    perror_with_name ("vfork");
+
+  if (pid == 0)
+    {
+      /* Run inferior in a separate process group.  */
+      setpgrp (getpid (), getpid ());
+
+/* Not needed on Sun, at least, and loses there
+   because it clobbers the superior.  */
+/*???      signal (SIGQUIT, SIG_DFL);
+      signal (SIGINT, SIG_DFL);  */
+
+         errno = 0; 
+      ptrace (0);
+
+      execle ("/bin/sh", "sh", "-c", allargs, 0, env);
+
+      fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+              errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+      fflush (stderr);
+      _exit (0177);
+    }
+  return pid;
+}
+
+/* Kill the inferior process.  Make us have no inferior.  */
+
+kill_inferior ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (8, inferior_pid, 0, 0);
+  wait (0);
+  /*************inferior_died ();****VK**************/ 
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+unsigned char
+resume (step, signal,status)
+     int step;
+     int signal;
+        char *status; 
+{
+       int pid ; 
+       WAITTYPE w; 
+
+       errno = 0;
+    ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+    if (errno)
+               perror_with_name ("ptrace");
+       pid = wait(&w); 
+       if(pid != inferior_pid) 
+               perror_with_name ("wait"); 
+
+       if(WIFEXITED(w))
+       {
+               printf("\nchild exited with retcode = %x \n",WRETCODE(w)); 
+               *status = 'E'; 
+               return((unsigned char) WRETCODE(w));
+       } 
+       else if(!WIFSTOPPED(w))
+       {
+               printf("\nchild did terminated with signal = %x \n",WTERMSIG(w)); 
+               *status = 'T'; 
+               return((unsigned char) WTERMSIG(w)); 
+       } 
+       else 
+       {
+               printf("\nchild stopped with signal = %x \n",WSTOPSIG(w)); 
+               *status = 'S'; 
+               return((unsigned char) WSTOPSIG(w)); 
+       } 
+                
+}
+
+
+#ifdef NEW_SUN_PTRACE
+
+void
+fetch_inferior_registers ()
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+      ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+         /**********debugging begin **********/ 
+         print_some_registers(&inferior_registers); 
+         /**********debugging end **********/ 
+      ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+
+      bcopy (&inferior_registers, registers, 16 * 4);
+      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+      *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+      bcopy (&inferior_fp_registers.fps_control,
+            &registers[REGISTER_BYTE (FPC_REGNUM)],
+            sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+      bcopy (registers, &inferior_registers, 16 * 4);
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+            sizeof inferior_fp_registers.fps_regs);
+      inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+      inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+      bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+            &inferior_fp_registers.fps_control,
+            sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+      ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+      ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+}
+
+#endif /* not NEW_SUN_PTRACE */
+
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+   in the NEW_SUN_PTRACE case.
+   It ought to be straightforward.  But it appears that writing did
+   not write the data that I specified.  I cannot understand where
+   it got the data that it actually did write.  */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.  */
+
+read_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  /* Read all the longwords */
+  for (i = 0; i < count; i++, addr += sizeof (int))
+    {
+       buffer[i] = ptrace (1, inferior_pid, addr, 0);
+    }
+
+  /* Copy appropriate bytes out of the buffer.  */
+  bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.
+   On failure (cannot write the inferior)
+   returns the value of errno.  */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+  extern int errno;
+
+  /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+    buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+  if (count > 1)
+    {
+       buffer[count - 1]
+         = ptrace (1, inferior_pid,
+                   addr + (count - 1) * sizeof (int), 0);
+    }
+
+  /* Copy data to be written over corresponding part of buffer */
+
+  bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+  /* Write the entire buffer.  */
+
+  for (i = 0; i < count; i++, addr += sizeof (int))
+    {
+      errno = 0;
+       ptrace (4, inferior_pid, addr, buffer[i]);
+      if (errno)
+       return errno;
+    }
+
+  return 0;
+}
+\f
+void
+try_writing_regs_command ()
+{
+  register int i;
+  register int value;
+  extern int errno;
+
+  if (inferior_pid == 0)
+    error ("There is no inferior process now.");
+
+  fetch_inferior_registers(); 
+  for (i = 0;i<18 ; i ++)
+    {
+      QUIT;
+      errno = 0;
+      value = read_register(i); 
+      write_register ( i, value);
+      if (errno == 0)
+       {
+               printf (" Succeeded with register %d; value 0x%x (%d).\n",
+                 i, value, value);
+       }
+      else 
+               printf (" Failed with register %d.\n", i);
+    }
+}
+
+void
+initialize ()
+{
+
+  inferior_pid = 0;
+
+
+}
+
+
+/* Return the contents of register REGNO,
+   regarding it as an integer.  */
+
+CORE_ADDR
+read_register (regno)
+     int regno;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  return *(int *) &registers[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer.  */
+
+void
+write_register (regno, val)
+     int regno, val;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+  if (have_inferior_p ())
+    store_inferior_registers (regno);
+}
+
+
+int
+have_inferior_p ()
+{
+  return inferior_pid != 0;
+}
+
+print_some_registers(regs)
+int regs[];
+{
+   register int i;
+   for (i = 0; i < 18; i++) {
+        printf("reg[%d] = %x\n", i, regs[i]);
+        }
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_server.c
+/* Main code for remote server for GDB, the GNU Debugger.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "param.h"
+#include <stdio.h>
+
+void read_inferior_memory(), fetch_inferior_registers(); 
+unsigned char resume(); 
+void kill_inferior(); 
+void initialize(), try_writing_regs_command();  
+int create_inferior(), read_register(); 
+
+extern char registers[]; 
+int inferior_pid; 
+extern char **environ; 
+
+/* Descriptor for I/O to remote machine.  */
+int remote_desc;
+int kiodebug = 0;
+int remote_debugging; 
+
+void remote_send ();
+void putpkt ();
+void getpkt ();
+void remote_open(); 
+void write_ok(); 
+void write_enn(); 
+void convert_ascii_to_int(); 
+void convert_int_to_ascii(); 
+void prepare_resume_reply(); 
+void decode_m_packet(); 
+void decode_M_packet(); 
+
+
+main(argc,argv)
+int argc; char *argv[]; 
+{
+    char ch,status, own_buf[2000], mem_buf[2000]; 
+       int i=0;  
+       unsigned char signal;  
+       unsigned int mem_addr, len; 
+
+       initialize(); 
+    printf("\nwill open serial link\n"); 
+    remote_open("/dev/ttya",0); 
+
+       if(argc < 2) 
+       { 
+               printf("Enter name of program to be run with command line args\n"); 
+               gets(own_buf); 
+               inferior_pid = create_inferior(own_buf,environ); 
+               printf("\nProcess %s created; pid = %d\n",own_buf,inferior_pid);
+       } 
+       else 
+       { 
+               inferior_pid = create_inferior(argv[1],environ); 
+               printf("\nProcess %s created; pid = %d\n",argv[1],inferior_pid);
+       } 
+
+    do {  
+        getpkt(own_buf); 
+        printf("\nPacket received is>:%s\n",own_buf); 
+               i = 0; 
+               ch = own_buf[i++]; 
+           switch (ch) { 
+                       case 'h':       /**********This is only for tweaking the gdb+ program *******/ 
+                                               signal = resume(1,0,&status);
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                                               /*************end tweak*************************************/ 
+
+                       case 'g':       fetch_inferior_registers();             
+                                               convert_int_to_ascii(registers,own_buf,REGISTER_BYTES); 
+                                               break; 
+                       case 'G':       convert_ascii_to_int(&own_buf[1],registers,REGISTER_BYTES);
+                                               if(store_inferior_registers(-1)==0)  
+                                                       write_ok(own_buf); 
+                                               else  
+                                                       write_enn(own_buf); 
+                                               break; 
+                       case 'm':       decode_m_packet(&own_buf[1],&mem_addr,&len); 
+                                               read_inferior_memory(mem_addr,mem_buf,len);
+                                               convert_int_to_ascii(mem_buf,own_buf,len); 
+                                               break; 
+                       case 'M':       decode_M_packet(&own_buf[1],&mem_addr,&len,mem_buf); 
+                                               if(write_inferior_memory(mem_addr,mem_buf,len)==0)  
+                                                       write_ok(own_buf); 
+                                               else 
+                                                       write_enn(own_buf); 
+                                               break; 
+                       case 'c':       signal = resume(0,0,&status);
+                                               printf("\nSignal received is >: %0x \n",signal); 
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                       case 's':       signal = resume(1,0,&status);
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                       case 'k':       kill_inferior();
+                                               sprintf(own_buf,"q"); 
+                                       putpkt(own_buf); 
+                                               printf("\nObtained kill request...terminating\n"); 
+                                       close(remote_desc); 
+                                               exit(0); 
+                       case 't':       try_writing_regs_command();
+                                               own_buf[0] = '\0'; 
+                                               break; 
+                       default :       printf("\nUnknown option chosen by master\n"); 
+                                               write_enn(own_buf); 
+                                               break; 
+                 } 
+
+        putpkt(own_buf); 
+     }  while(1) ; 
+
+    close(remote_desc); 
+    /** now get out of here**/ 
+    printf("\nFinished reading data from serial link - Bye!\n"); 
+    exit(0);
+
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_utils.c
+/* Remote utility routines for the remote server for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "param.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <a.out.h>
+#include <sys/file.h>
+#include <sgtty.h> 
+
+extern int remote_desc; 
+extern int remote_debugging; 
+extern int kiodebug; 
+
+void remote_open(); 
+void remote_send(); 
+void putpkt(); 
+void getpkt(); 
+
+void write_ok(); 
+void write_enn(); 
+void convert_ascii_to_int(); 
+void convert_int_to_ascii(); 
+void prepare_resume_reply(); 
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication.  */
+
+void
+remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  struct sgttyb sg;
+
+  remote_debugging = 0;
+
+  remote_desc = open (name, O_RDWR);
+  if (remote_desc < 0)
+    printf("\ncould not open remote device\n"); 
+
+  ioctl (remote_desc, TIOCGETP, &sg);
+  sg.sg_flags = RAW;
+  ioctl (remote_desc, TIOCSETP, &sg);
+
+  if (from_tty)
+    printf ("Remote debugging using %s\n", name);
+  remote_debugging = 1;
+}
+
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (a)
+     int a;
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else
+    perror ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (nib)
+     int nib;
+{
+  if (nib < 10)
+    return '0'+nib;
+  else
+    return 'a'+nib-10;
+}
+
+/* Send the command in BUF to the remote machine,
+   and read the reply into BUF.
+   Report an error if we get an error reply.  */
+
+void
+remote_send (buf)
+     char *buf;
+{
+  putpkt (buf);
+  getpkt (buf);
+
+  if (buf[0] == 'E')
+    perror ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+   The data of the packet is in BUF.  */
+
+void
+putpkt (buf)
+     char *buf;
+{
+  int i;
+  unsigned char csum = 0;
+  char buf2[500];
+  char buf3[1];
+  int cnt = strlen (buf);
+  char *p;
+
+  if (kiodebug)
+    fprintf (stderr, "Sending packet: %s\n", buf);
+
+  /* Copy the packet into buffer BUF2, encapsulating it
+     and giving it a checksum.  */
+
+  p = buf2;
+  *p++ = '$';
+
+  for (i = 0; i < cnt; i++)
+    {
+      csum += buf[i];
+      *p++ = buf[i];
+    }
+  *p++ = '#';
+  *p++ = tohex ((csum >> 4) & 0xf);
+  *p++ = tohex (csum & 0xf);
+
+  /* Send it over and over until we get a positive ack.  */
+
+  do {
+    write (remote_desc, buf2, p - buf2);
+    read (remote_desc, buf3, 1);
+  } while (buf3[0] != '+');
+}
+
+static int
+readchar ()
+{
+  char buf[1];
+  while (read (remote_desc, buf, 1) != 1) ;
+  return buf[0] & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+   and store it in BUF.  */
+
+void
+getpkt (buf)
+     char *buf;
+{
+  char *bp;
+  unsigned char csum, c, c1, c2;
+  extern kiodebug;
+
+  while (1)
+    {
+         csum = 0; 
+      while ((c = readchar()) != '$');
+
+      bp = buf;
+      while (1)
+       {
+         c = readchar ();
+         if (c == '#')
+           break;
+         *bp++ = c;
+         csum += c;
+       }
+      *bp = 0;
+
+      c1 = fromhex (readchar ());
+      c2 = fromhex (readchar ());
+      if (csum == (c1 << 4) + c2)
+           break;
+
+      printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+             (c1 << 4) + c2, csum, buf);
+      write (remote_desc, "-", 1);
+    }
+
+  write (remote_desc, "+", 1);
+
+  if (kiodebug)
+    fprintf (stderr,"Packet received :%s\n", buf);
+}
+
+
+void 
+write_ok(buf)
+       char *buf; 
+{
+       buf[0] = 'O';
+       buf[1] = 'k';
+       buf[2] = '\0';
+}
+
+void 
+write_enn(buf)
+       char *buf; 
+{
+       buf[0] = 'E';
+       buf[1] = 'N';
+       buf[2] = 'N';
+       buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii(from,to,n)
+char *from, *to; int n; 
+{
+       int nib ; 
+       char ch; 
+       while( n-- )
+       {
+               ch = *from++;           
+               nib = ((ch & 0xf0) >> 4)& 0x0f; 
+               *to++ = tohex(nib); 
+               nib = ch & 0x0f; 
+               *to++ = tohex(nib); 
+       } 
+       *to++ = 0; 
+}
+
+
+void
+convert_ascii_to_int(from,to,n)
+char *from, *to; int n;  
+{
+       int nib1,nib2 ; 
+       while( n-- )
+       {
+               nib1 = fromhex(*from++); 
+               nib2 = fromhex(*from++); 
+               *to++ = (((nib1 & 0x0f)<< 4)& 0xf0) | (nib2 & 0x0f); 
+       } 
+}
+
+void
+prepare_resume_reply(buf,status,signal)
+char *buf ,status; 
+unsigned char signal; 
+{
+       int nib; 
+       char ch; 
+
+       *buf++ = 'S';  
+       *buf++ = status;  
+       nib = ((signal & 0xf0) >> 4) ; 
+       *buf++ = tohex(nib); 
+       nib = signal & 0x0f; 
+       *buf++ = tohex(nib); 
+       *buf++ = 0; 
+}
+
+void 
+decode_m_packet(from,mem_addr_ptr,len_ptr)
+char *from;
+unsigned int *mem_addr_ptr, *len_ptr; 
+{
+       int i = 0, j = 0 ; 
+       char ch; 
+       *mem_addr_ptr = *len_ptr = 0; 
+       /************debugging begin************/ 
+       printf("\nIn decode_m_packet"); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ',') 
+       { 
+               *mem_addr_ptr = *mem_addr_ptr << 4; 
+               *mem_addr_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished mem_addr part"); 
+       /************debugging end************/ 
+
+       for(j=0; j < 4; j++) 
+       { 
+               if((ch = from[i++]) == 0)  
+                       break; 
+               *len_ptr = *len_ptr << 4; 
+               *len_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished len_ptr part"); 
+       /************debugging end************/ 
+}
+
+void 
+decode_M_packet(from,mem_addr_ptr,len_ptr,to)
+char *from, *to;
+unsigned int *mem_addr_ptr, *len_ptr; 
+{
+       int i = 0, j = 0 ; 
+       char ch; 
+       *mem_addr_ptr = *len_ptr = 0; 
+       /************debugging begin************/ 
+       printf("\nIn decode_M_packet"); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ',') 
+       { 
+               *mem_addr_ptr = *mem_addr_ptr << 4; 
+               *mem_addr_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished mem_addr part: memaddr = %x",*mem_addr_ptr); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ':') 
+       { 
+               *len_ptr = *len_ptr << 4; 
+               *len_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished len_ptr part: len = %d",*len_ptr); 
+       /************debugging end************/ 
+
+       convert_ascii_to_int(&from[i++],to,*len_ptr); 
+
+       /************debugging begin************/ 
+       printf("\nmembuf : %x",*(int *)to); 
+       /************debugging end************/ 
+}
+
+SHAR_EOF
+#      End of shell archive
+exit 0
diff --git a/gdb/remote-sa.sparc.c b/gdb/remote-sa.sparc.c
new file mode 100644 (file)
index 0000000..686699e
--- /dev/null
@@ -0,0 +1,1146 @@
+/* THIS FILE HAS NOT HAD ITS COPYRIGHT CHECKED...FSF SHOULD NOT
+   DISTRIBUTE IT UNTIL THIS HAPPENS.  */
+
+/* Memory-access and commands for inferior process, for GDB.
+*/
+
+#include <sys/errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "value.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#undef WSTOPSIG
+#undef WTERMSIG
+#include "wait.h"
+
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include <signal.h>
+#include <sys/file.h>
+
+#include <termios.h>
+#define TERMINAL struct termios
+
+#define LONGTIMEOUT 5
+#define SHORTTIMEOUT 1
+
+#define KD_MINUTAE 1
+#define KD_LINEDISCIPLINE 2
+#define KD_RETRY 4
+#define KD_BLOCKTRANSFER 8
+
+#ifndef STDIN
+#define STDIN 0
+#endif
+
+#define GL_READING 0 /* get line is reading data */
+#define GL_OK 1 /* Getline saw the "ok" string */
+#define GL_SUCCESS 2 /* Get line got data */
+#define GL_TIMEOUT 3 /* Get line timed out */
+#define GL_OVERRUN 4 /* Get line filled up the buffer */
+#define GL_EXCEPTION 5 /* Get line saw "Exception" */
+#define GL_PROMLINE 6 /* Get line saw prom specific info */
+#define GL_BLANKLINE 7 /* Get line saw a blank line */
+
+static int kiodebug /* = KD_RETRY | KD_BLOCKTRANSFER */;
+
+static CORE_ADDR remote_pc = 0;
+static CORE_ADDR remote_next_pc = 0;
+static CORE_ADDR remove_thisbp_next_pc = 0;
+static CORE_ADDR remove_thisbp_target = 0;
+
+enum showDrainage {DONTSHOW , SHOW} ;
+
+
+/* Descriptor for I/O to remote machine.  Initialize it to -1 so that
+   remote_open knows that we don't have a file open when the program
+   starts.  */
+int remote_desc = -1;
+
+int dontskipcrs = 0;
+
+#define        PBUFSIZ 400
+
+unsigned char ignorebuf[PBUFSIZ];
+#define IGNORE &ignorebuf[0]
+
+/* Maximum number of bytes to read/write at once.  The value here
+   is chosen to fill up a packet (the headers account for the 32).  */
+#define MAXBUFBYTES ((PBUFSIZ-32)/2)
+
+static void remote_send ();
+static void putpkt ();
+static int getpkt ();
+
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication.  */
+CORE_ADDR breakpoint_regs_addr;
+
+
+void
+remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  extern int frame_file_full_name;
+  unsigned char buf[PBUFSIZ];
+  TERMINAL sg;
+
+  remote_debugging = 0;
+
+  if (remote_desc >= 0)
+    close (remote_desc);
+
+  breakpoint_regs_addr = parse_and_eval_address("&breakpoint_regs");
+
+  dontskipcrs = !frame_file_full_name; /* if we are running inside of
+                                        emacs, this will be true. 
+                                        then skip carriage returns */
+
+  remote_desc = open (name, O_RDWR);
+  if (remote_desc < 0)
+    perror_with_name (name);
+
+  setup_remote();
+
+  if (from_tty)
+    printf ("Remote debugging using %s\n", name);
+  remote_debugging = 1;
+
+
+}
+static char *boot_cmd = 0;
+
+static print_boot_cmd()
+{
+    fprintf(stderr, "boot command set to be \"%s\"\n", boot_cmd);
+}
+
+remote_start()
+{
+  WAITTYPE ignoredWaitType;
+
+  if (boot_cmd)
+    {
+    sendbreak();
+    remote_wait (&ignoredWaitType);
+    putpkt ("reset");
+    sleep(10);
+    sendbreak();
+    remote_wait (&ignoredWaitType);
+    sleep(10);
+    print_boot_cmd();
+    putpkt(boot_cmd);
+    fprintf(stderr, "rgdb and nucleus synchronized, booting....\n");
+    }
+  else
+    {
+    error("The boot command is null. Cannot start the remote kernel/nucleus");
+    }
+}
+
+/* Close the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+void
+remote_close (from_tty)
+     int from_tty;
+{
+  if (!remote_debugging)
+    error ("Can't close remote connection: not debugging remotely.");
+  
+  close (remote_desc);         /* This should never be called if
+                                  there isn't something valid in
+                                  remote_desc.  */
+
+  /* Do not try to close remote_desc again, later in the program.  */
+  remote_desc = -1;
+
+  if (from_tty)
+    printf ("Ending remote debugging\n");
+
+  remote_debugging = 0;
+}
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (a)
+     int a;
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else
+    error ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (nib)
+     int nib;
+{
+  if (nib < 10)
+    return '0'+nib;
+  else
+    return 'a'+nib-10;
+}
+\f
+/* Tell the remote machine to resume.  */
+
+extern int one_stepped;                /* From machine dependent code */
+static int remote_set_one_stepped;
+
+int
+remote_resume (step, signal)
+     int step, signal;
+{
+  if (step)
+    {
+      remote_single_step();
+    }
+  remote_set_one_stepped = step;
+  putpkt("go");
+}
+
+/* Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+int
+remote_wait (status)
+     WAITTYPE *status;
+{
+  char last, this;
+  int pend, saveTheOh = 0;
+
+  user_terminal_raw();
+
+  WSETEXIT ((*status), 0177);
+  last = this = 0;
+
+  while (1)
+      {
+       char buf[PBUFSIZ];
+       int readUser, readProm, state;
+
+       doselect(&readUser, &readProm);
+       if (readProm)
+         {
+           switch (state = getline(buf, PBUFSIZ, SHORTTIMEOUT))
+             {
+             case GL_BLANKLINE:
+               if (remote_set_one_stepped)
+                 break;
+               
+               /* fall through */
+
+             default:
+             case GL_READING:
+             case GL_SUCCESS:
+             case GL_OVERRUN:
+             case GL_TIMEOUT:
+               if (kiodebug & KD_LINEDISCIPLINE)
+                 fprintf(stderr, "%d<%s>\n", state, buf);
+               else
+                 {
+                   fprintf(stderr, "%s", buf);
+                   fflush(stderr);
+                 }
+               break;
+             case GL_OK:
+               remote_cleanup_after_stop();
+               WSETSTOP ((*status), SIGTRAP);
+               return;
+             case GL_PROMLINE:
+               break;
+             }
+         }
+       if (readUser)
+         shuffleFromUserToProm();
+      }
+}
+static TERMINAL userterminal;
+       
+user_terminal_restore()
+{
+#if 0
+  int in_desc = fileno (stdin);
+  ioctl (in_desc, TCSETS, &userterminal);
+#endif
+}
+static void set_term_raw();
+
+user_terminal_raw()
+{
+#if 0
+  TERMINAL tempterminal;
+  int in_desc = fileno (stdin);
+  ioctl (in_desc, TCGETS, &userterminal);
+  tempterminal = userterminal;
+
+  tempterminal.c_lflag &= ~(ICANON|ISIG|IEXTEN);
+  tempterminal.c_cc[VMIN] = 1;
+  tempterminal.c_cc[VTIME] = 0;
+  tempterminal.c_iflag &= ~(INPCK|IXON|IXOFF);
+  tempterminal.c_oflag = 0;
+
+  ioctl (in_desc, TCSETS, &tempterminal);
+#endif
+}
+
+doselect(pReadUser, pReadProm)
+     int *pReadUser, *pReadProm;
+{
+  extern FILE *instream;
+  int in_desc = fileno (stdin);
+  int instreammask = 1 << in_desc;
+  int remotemask = 1 << remote_desc;
+  int rfds = instreammask | remotemask;
+
+  select (32, &rfds, 0, 0, (struct timeval *) 0); /* 0 = Block indefinitely */
+  *pReadUser = (rfds & instreammask) == instreammask;
+  *pReadProm = (rfds & remotemask) == remotemask;
+}
+
+
+
+/* Read the remote registers into the block pRegisters.
+implementation copied largely from fetch_inferior_registers () 
+in sparc-dep.c */
+
+void
+remote_fetch_registers(ignored)
+int *ignored;
+{
+  struct regs inferior_registers;
+  extern char registers[];
+  CORE_ADDR breakpoint_regs_target;
+
+  if (breakpoint_regs_addr == 0)
+    {
+      error("no address for breakpoint_regs\n");
+      return;
+    }
+  remote_read_inferior_memory(breakpoint_regs_addr, &breakpoint_regs_target,
+                             sizeof(breakpoint_regs_target));
+
+  bzero(registers, REGISTER_BYTES);
+  registers[REGISTER_BYTE (0)] = 0;
+
+  if (breakpoint_regs_target)
+    {
+      remote_read_inferior_memory(breakpoint_regs_target, &inferior_registers,
+                                 sizeof(inferior_registers));
+      registers[REGISTER_BYTE (0)] = 0;
+      bcopy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (1)], 15 * 4);
+      *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; 
+      *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+      *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+      *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+      remote_pc =  inferior_registers.r_pc; 
+      remote_next_pc =  inferior_registers.r_npc; 
+      remote_read_inferior_memory (inferior_registers.r_sp,
+                                  &registers[REGISTER_BYTE (16)],
+                                  16*4);
+    }
+  else
+    {
+      error("breakpoint_regs == 0\n");
+    }
+}
+
+
+
+\f
+/* Write memory data directly to the remote machine.
+   This does not inform the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   MYADDR is the address of the buffer in our space.
+   LEN is the number of bytes.  */
+
+int
+remote_write_bytes (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     unsigned char *myaddr;
+     int len;
+{
+  char buf[PBUFSIZ];
+  int i;
+
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  for (i = 0; i < len; i++)
+    {
+    sprintf(buf, "%x %x c!", myaddr[i], memaddr + i); 
+    remote_send (buf, buf);
+    if (strstr(buf, "Exception"))
+      {
+       return EFAULT;    
+      }
+    }
+  return 0;      
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.  Returns errno value.  */
+int
+remote_write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int xfersize;
+  int retval;
+
+  while (len > 0)
+    {
+      if (len > MAXBUFBYTES)
+       xfersize = MAXBUFBYTES;
+      else
+       xfersize = len;
+      
+      retval = remote_write_bytes(memaddr, myaddr, xfersize);
+      if (retval)
+       return retval; /* error */
+      
+      memaddr += xfersize;
+      myaddr  += xfersize;
+      len     -= xfersize;
+    }
+  return 0; /* no error */
+}
+\f
+
+/* read a single character */
+
+static int
+readCharFromProm ()
+{
+  char buf;
+
+  buf = '\0';
+  /* termio does the timeout for us.  */
+  read (remote_desc, &buf, 1);
+  return buf & 0x7f;
+}
+
+/* Send the command in BUF to the remote machine,
+   and read the reply into BUF.
+   Report an error if we get an error reply.  */
+
+static void
+remote_send (buf, buf2)
+     char *buf, *buf2;
+{
+  putpkt (buf);
+  getpkt (buf2);
+}
+
+/* Send a single character out over the wire */
+
+static void
+putcharacter (ch)
+     char ch;
+{
+
+  while (1)
+    {
+      int i;
+
+      write(remote_desc, &ch, 1);
+      for (i = 0; i < 100; i++)
+       {
+         char nch = 0;
+
+         if (read (remote_desc, &nch, 1) == 0)
+           i++;
+         if ((ch == nch)
+             || (ch == '\n' && nch == '\r')
+             || (ch == '\r' && nch == '\n'))
+           return;
+         if (kiodebug & KD_MINUTAE)
+           fprintf (stderr, "Sent %c(%d) Received %c(%d)\n", ch, ch, nch, nch);
+       }
+    }
+}
+
+/* Send a packet to the remote machine, with error checking.
+   The data of the packet is in BUF.  */
+
+static void
+putpkt (buf)
+     char *buf;
+{
+  int i;
+  int cnt = strlen (buf);
+  char ch;
+
+  if (kiodebug & KD_LINEDISCIPLINE)
+    fprintf(stderr, "putpkt(%s)\n", buf);
+
+  for (i = 0; i < cnt; i++)
+      putcharacter (buf[i]);
+  putcharacter ('\n');
+}
+
+jmp_buf getline_jmpbuf;
+
+/* Read a line from the remote machine, and store it in BUF.  */
+getline_timer()
+{
+  alarm(0);
+  
+  if (kiodebug & KD_RETRY)
+    fprintf(stderr, "getline timed out\n");
+  longjmp(getline_jmpbuf, 1);
+}
+
+static int
+getline (buf, size, timeout)
+     char *buf;
+     int size, timeout;
+{
+  int cnt = 0;
+  int state;
+  int isspace_state = 1;
+
+  if ((void (*)) signal (SIGALRM, getline_timer) == (void (*)) -1)
+    perror ("remote_open: error in signal");
+
+  --size; /* back it up one so that we can read */
+
+  state = GL_READING;
+
+  if (setjmp(getline_jmpbuf))
+    state = GL_TIMEOUT;
+  else
+    {
+      alarm (timeout);
+      do
+       {
+         char ch = readCharFromProm();
+         isspace_state = isspace_state && isspace(ch);
+         if (ch && (dontskipcrs || ch != '\r'))
+           {
+             buf[cnt++] = ch;
+             buf[cnt] = '\0';
+           }
+         if (kiodebug & KD_MINUTAE)
+           fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
+         if (cnt >= 2 && buf[cnt - 2] == 'o' && buf[cnt - 1] == 'k')
+             state = GL_OK;
+         else if (buf[cnt - 1] == '\n' )
+           state = isspace_state ?  GL_BLANKLINE : GL_SUCCESS;
+         else if (cnt == size)
+           state = GL_OVERRUN;
+         else if (strstr(buf, "Type  'go' to resume"))
+           state = GL_PROMLINE;
+         else if (strstr(buf, "Type  help  for more information"))
+           state = GL_PROMLINE;
+         else if (strstr(buf, "Exception"))
+           state = GL_EXCEPTION;
+       }
+      while (state == GL_READING);
+    }
+  alarm (0);
+  
+  if (kiodebug & KD_LINEDISCIPLINE)
+    fprintf (stderr,"Line received :%s\n", buf);
+  return state;
+}
+
+
+/* Read a packet from the remote machine, and store it in BUF.  */
+
+static int
+getpkt (buf)
+     char *buf;
+{
+  int cnt = 0;
+
+    do
+      {
+      char ch = readCharFromProm();
+      if (ch)
+       buf[cnt++] = ch;
+      if (kiodebug & KD_MINUTAE)
+       fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
+      }
+    while (cnt < 2 ||
+      buf[cnt - 2] != 'o' &&
+      buf[cnt - 1] != 'k');
+
+    buf[cnt] = '\0';
+    if (kiodebug& KD_LINEDISCIPLINE)
+      fprintf (stderr,"Packet received :%s\n", buf);
+    return cnt;
+}
+
+void remote_fetch_word (addr)
+     CORE_ADDR addr;
+{
+  error ("Internal error: remote_fetch_word is obsolete.\n");
+}
+void remote_store_word (addr)
+     CORE_ADDR addr;
+{
+  error ("Internal error: remote_store_word is obsolete.\n");
+}
+#include <termio.h>
+
+draininput(showit)
+enum showDrainage showit;
+{
+  unsigned char buf[PBUFSIZ];
+  int cnt;
+
+  while ((cnt = read(remote_desc, buf, PBUFSIZ)) > 0)
+    {
+      buf[cnt] = 0;
+      if (kiodebug& KD_LINEDISCIPLINE)
+       fprintf (stderr,"Draining :%s\n", buf);
+      else
+       if (showit == SHOW)
+         fprintf (stderr,"%s", buf);
+    }
+  if (kiodebug& KD_LINEDISCIPLINE)
+    fprintf (stderr,"Drained\n");
+}
+sendbreak()
+{
+  if (kiodebug & KD_RETRY)
+    fprintf (stderr,"rgdb sending break to target...\n");
+  else
+    {
+      fprintf (stderr,"=");
+      fflush(stderr);
+    }
+    
+  ioctl (remote_desc, TCSBRK, 0);
+  sleep(5);
+}
+
+
+/* shuffle a character from the user to remote debugger */
+
+int 
+shuffleFromUserToProm()
+{
+  char ch;
+  static int escape = 0;
+    
+  extern FILE *instream;
+  
+  ch = 0;
+  if (read(STDIN, &ch , 1) != 1 || ch == 0)
+    return;
+
+  if (escape) {
+    if (ch == '#')
+      sendbreak();
+    else if (ch == '.')
+       {
+         while (ch != '\n')    
+           read(STDIN, &ch , 1);
+         return 1;
+       }
+    else {
+      static char tilde = '~';
+
+      putcharacter(tilde);
+      putcharacter(ch);
+    }
+    escape = 0;
+  } else /* not escape */ {
+    if (ch == '~')
+      escape = 1;
+    else
+      putcharacter(ch);
+  }
+  return 0;
+}
+  
+  
+
+/* Tell  the Prom put a breakpoint at memaddr */
+remote_insert_breakpoint(memaddr)
+     CORE_ADDR memaddr;
+{
+  char buf[PBUFSIZ];
+
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  sprintf(buf, "%x +bp", memaddr);
+  remote_send(buf, buf);
+  if (strstr(buf, "Exception"))
+    {
+      return EFAULT;     
+    }
+  else
+    {
+      return 0;          
+    }
+}
+
+/* Tell  the Prom remove the the breakpoint at memaddr */
+remote_remove_breakpoint(memaddr)
+     CORE_ADDR memaddr;
+{
+  char buf[PBUFSIZ];
+
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  sprintf(buf, "%x -bp", memaddr);
+  remote_send(buf, buf);
+  if (strstr(buf, "Exception"))
+    {
+      return EFAULT;     
+    }
+  else
+    {
+      return 0;          
+    }
+}
+
+
+
+
+
+/* Read memory data directly from the remote machine.
+   This does not use the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   MYADDR is the address of the buffer in our space.
+   LEN is the number of words.  */
+
+long
+remote_read(memaddr, myaddr, len, increment, promcommand)
+     CORE_ADDR memaddr;
+     unsigned char *myaddr;
+     int len, increment;
+     char *promcommand;
+{
+  char buf[PBUFSIZ];
+  char buf2[PBUFSIZ];
+  int i;
+  unsigned long num;
+
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  for (i = 0; i < len; i += increment)
+    {
+      sprintf(buf, promcommand, memaddr + i) ;
+      remote_send(buf, buf2);
+      remote_send(".", buf);
+      if (strstr(buf2, "Exception"))
+       {
+         bzero(&myaddr[i], len - i);
+         return -i;      
+       }
+      else
+       {
+         char *pBuf;
+         for (pBuf = &buf[0]; *pBuf == '\r' || *pBuf == '\n'; pBuf++)
+           ;
+         sscanf(pBuf, "%x\n", &num);
+         switch (increment)
+           {
+           case 1: myaddr[i] = num;
+             if (num > 255)
+               fprintf(stderr, "number out of bounds %x truncating to %x\n",
+                       num, myaddr[i]);
+             break;
+           case 4: {unsigned long *p;
+                    p = (unsigned long *) &myaddr[i];
+                    *p = num;
+                    }
+             break;
+           default: fprintf(stderr, "unknown increment\n"); break;
+           }
+       }
+    }
+  return i;
+}
+\f
+
+
+/* Read LEN bytes from inferior memory at MEMADDR.  Put the result
+   at debugger address MYADDR.  Returns errno value.  */
+int
+remote_read_inferior_memory(memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int xfersize;
+  while (len > 0)
+    {
+      int mod;
+
+      if (len > MAXBUFBYTES)
+       xfersize = MAXBUFBYTES;
+      else
+       xfersize = len;
+
+      mod = memaddr % 4;
+      if  (mod == 0 && xfersize >= 4)
+       if  (mod == 0 && xfersize >= 16)
+         {
+           xfersize = remote_read_many(memaddr, myaddr, (len & ~3));
+           getpkt(IGNORE);
+         }
+       else
+         xfersize = remote_read(memaddr, myaddr, 4, 4, "%x @");
+      else
+       xfersize = remote_read(memaddr, myaddr, max(mod, 1), 1, "%x c@");
+      if (xfersize <= 0)
+       return EFAULT; /* error */
+      memaddr += xfersize;
+      myaddr  += xfersize;
+      len     -= xfersize;
+    }
+  return 0; /* no error */
+}
+static int baud_rate=B38400;
+
+static void set_term_raw(pTermio)
+     TERMINAL *pTermio;
+{
+  pTermio->c_cflag &= (CREAD|HUPCL|CLOCAL);
+  pTermio->c_cflag |= baud_rate | CS8;
+  pTermio->c_iflag = ISTRIP /* | IXON | IXOFF */;
+  pTermio->c_oflag = 0;
+  pTermio->c_lflag = 0;
+  pTermio->c_cc[VMIN] = 0;
+  pTermio->c_cc[VTIME] = 1;
+}
+
+/* setup the remote termio stream */
+setup_remote()
+{
+  TERMINAL temptempio;
+
+  ioctl(remote_desc, TCGETS, &temptempio);
+  set_term_raw(&temptempio);
+  ioctl(remote_desc, TCSETS, &temptempio);
+}
+
+/* step one machine instruction */
+remote_single_step ()
+{
+  CORE_ADDR next_pc, npc4, target, pc;
+  typedef enum
+    {
+      Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
+    } branch_type;
+  branch_type br, isannulled();
+
+  npc4 = remote_next_pc + 4; /* branch not taken */
+
+  /* Always set breakpoint for NPC.  */
+
+  remote_insert_breakpoint(remote_next_pc);
+  remove_thisbp_next_pc = remote_next_pc;
+
+  /* printf ("set break at %x\n",remote_next_pc); */
+  
+  br = isannulled (remote_pc, &target);
+  
+  if (br == bicca)
+    {
+      /* Conditional annulled branch will either end up at
+        npc (if taken) or at npc+4 (if not taken).
+        Trap npc+4.  */
+      remote_insert_breakpoint(npc4);
+      remove_thisbp_target = npc4;
+    }
+  else if (br == baa && target != remote_next_pc)
+    {
+      /* Unconditional annulled branch will always end up at
+        the target.  */
+      remote_insert_breakpoint(target);
+      remove_thisbp_target = target;
+    }
+}
+
+
+
+
+/* read many words of memory */
+long
+remote_read_many(memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     unsigned char *myaddr;
+     int len;
+{
+#define BLOCKSIZE 1024
+  static int max_number_of_blocks = 24;
+
+  char buf[PBUFSIZ];
+  char buf2[PBUFSIZ];
+  int i;
+  unsigned long *p;
+/* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  len = min(len, max_number_of_blocks * BLOCKSIZE);
+
+  sprintf(buf, "%x %x do i @ . cr 4 +loop", memaddr + len, memaddr);
+  putpkt(buf);
+  getline(buf2, PBUFSIZ, LONGTIMEOUT); /* I don't care */
+
+  p = (unsigned long *) myaddr;
+  for (i = 0; i < len; i += 4, p++)
+    {
+      extern int InspectIt;
+
+      if (!InspectIt && ((i % BLOCKSIZE) == 0))
+         fprintf(stderr, "+"); /* let 'em know that we are working */
+      switch (getline(buf2, PBUFSIZ, LONGTIMEOUT))
+       {
+       default:
+       case GL_PROMLINE:
+       case GL_READING:
+       case GL_OK:
+       case GL_OVERRUN:
+       case GL_TIMEOUT:
+       case GL_BLANKLINE:
+         /* resync and retry */
+         max_number_of_blocks = max(1, i / BLOCKSIZE);
+         fprintf(stderr, "-"); /* let 'em know that we are working */
+         
+         if (kiodebug & KD_BLOCKTRANSFER)
+           fprintf(stderr, "failed read_many %d %d/%d (%s)\n",
+                   max_number_of_blocks, i, len, buf2);
+         sendbreak();
+         return remote_read_many(memaddr, myaddr, len);
+       case GL_EXCEPTION:
+         return -i;      
+       case GL_SUCCESS:
+         sscanf(buf2, "%x\n", p);
+         break;
+       }
+    }
+  if (kiodebug & KD_BLOCKTRANSFER)
+    fprintf(stderr, "success read_many %d %d/%d (%s)\n", max_number_of_blocks,
+           i, len, buf2);
+  return i;
+}
+/*
+ * allow the user to type directly to the prom ! 
+ */
+prom_command()
+{
+  int readUser, readProm;
+
+  user_terminal_raw();
+  fprintf(stderr, "entering prom mode...\n");
+  while (1)
+    {
+      doselect(&readUser, &readProm);
+      if (readUser)
+       if (shuffleFromUserToProm())
+         {
+         fprintf(stderr, "exiting prom mode\n");
+         user_terminal_restore();
+         return;
+       }
+      if (readProm)
+       fprintf(stderr, "%c", readCharFromProm ());
+    }
+}
+static char *boot_set_msg = "boot needs a string in quotes of the form \"boot vmunix\"  ";
+static char *baud_set_msg = "baud rate should be of the form \"set baud=9600\"";
+
+static void
+set_boot (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  int h, i;
+
+  if (!arg)
+    {
+    print_boot_cmd();
+    error_no_arg (boot_set_msg);
+    }
+  
+  arg = tilde_expand (arg);
+  make_cleanup (free, arg);
+
+  i = strlen (arg) - 1;
+  
+  free (boot_cmd);
+  
+  h = 0;
+  while (*arg && h < i && (arg[h] == ' ' || arg[h] == '\t'))
+    {
+    h++;
+    arg++;
+    }
+  while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
+    i--;
+
+  if (h >= i || !*arg || arg[h] != '"' || arg[i] != '"')
+    error (boot_set_msg);
+  else
+    {
+    boot_cmd = savestring (++arg, i);
+    boot_cmd[i - 1] = '\0';
+    }
+ if (from_tty)
+    print_boot_cmd();
+}
+
+static int bauds[] = {
+       0, 50, 75, 110, 134, 150, 200, 300, 600,
+       1200, 1800, 2400, 4800, 9600, 19200, 38400, -1
+};
+
+
+static int convert_to_baud_B(n)
+       int n;
+{
+       register int *p;
+
+       for (p = bauds; *p != -1;  p++)
+               if (*p != 0 && *p == n)
+                       return (p - bauds);
+       return (NULL);
+}
+
+static void print_acceptable_bauds()
+{
+       register int *p;
+
+       for (p = bauds; *p != -1;  p++)
+               if (*p != 0 )
+                       fprintf(stderr, "%d\n", *p);
+}
+
+static void print_baud()
+{
+fprintf(stderr, "the baud rate is now %d\n", bauds[baud_rate]);
+}
+
+static void
+set_baud (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  int temp_baud_rate;
+
+  if (!arg)
+    {
+    print_baud();
+    print_acceptable_bauds();
+    error_no_arg (baud_set_msg);
+    return;
+    }
+
+  while (*arg && !isdigit(*arg))
+    arg++;
+  
+  if (*arg  && (temp_baud_rate = convert_to_baud_B(atoi(arg))) != NULL)
+    {
+       baud_rate = temp_baud_rate;
+       if (remote_debugging)
+         setup_remote();
+    }
+  else
+    {
+      fprintf(stderr, "bad baud rate %s, acceptable values are\n", arg);
+      print_acceptable_bauds();
+    }
+
+  print_baud();
+}
+
+
+
+
+void
+_initialize_remote()
+{
+/* Chain containing all defined set subcommands */
+
+extern struct cmd_list_element *setlist;
+
+
+  add_com ("prom", class_obscure, prom_command,
+          "Conduct a dialogue directly with the prom. \
+only useful after an attach\n\
+Terminate by typing ~.");
+
+  add_cmd ("boot_cmd", class_support, set_boot, boot_set_msg, &setlist);
+
+  add_cmd ("baud", class_support, set_baud, baud_set_msg, &setlist);
+
+  set_boot ("\"boot nucleus -d\"", 0);
+  }
+
+
+/* Store the remote registers from the contents of the block REGS.  */
+
+void
+remote_store_registers (registers)
+     char *registers;
+{
+  CORE_ADDR core;
+  struct regs inferior_registers;
+
+  core = parse_and_eval_address("breakpoint_regs");
+
+  bcopy (&registers[REGISTER_BYTE (1)],
+        &inferior_registers.r_g1, 15 * 4);
+
+  inferior_registers.r_ps =
+    *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc =
+    *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+  inferior_registers.r_npc =
+    *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
+  inferior_registers.r_y =
+    *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
+
+  remote_write_inferior_memory (*(int *)&registers[REGISTER_BYTE (SP_REGNUM)],
+                               &registers[REGISTER_BYTE (16)],
+                               16*4);
+  remote_write_inferior_memory (core,
+                               &inferior_registers, 
+                               sizeof(inferior_registers));
+}
+
+
+
+/* we have stopped. do some cleanup */
+remote_cleanup_after_stop()
+{
+  if (remove_thisbp_next_pc)
+    {
+      remote_remove_breakpoint (remove_thisbp_next_pc);
+      remove_thisbp_next_pc = 0;
+    }
+  if (remove_thisbp_target)
+    {
+      remote_remove_breakpoint (remove_thisbp_target);
+      remove_thisbp_target = 0;
+    }
+  user_terminal_restore();
+  
+  one_stepped = remote_set_one_stepped;
+}
diff --git a/gdb/remote-vx.68.c b/gdb/remote-vx.68.c
new file mode 100644 (file)
index 0000000..2c17b9e
--- /dev/null
@@ -0,0 +1,1527 @@
+/* Memory-access and commands for remote VxWorks processes, for GDB.
+   Copyright (C) 1990  Free Software Foundation, Inc.
+   Contributed by Wind River Systems and Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "tm-vxworks68.h"
+#include "param-no-tm.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h"           /* for struct complaint */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#define free bogon_free                /* Sun claims "int free()" not void */
+#include <rpc/rpc.h>
+#undef free
+#include <netdb.h>
+#include <ptrace.h>
+#include "xdr_ptrace.h"
+#include "xdr_ld.h"
+#include "xdr_rdb.h"
+#include "dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+extern value call_function_by_hand ();
+extern void symbol_file_command ();
+extern int stop_soon_quietly;          /* for wait_for_inferior */
+
+static int net_ptrace_clnt_call ();    /* Forward decl */
+static enum clnt_stat net_clnt_call ();        /* Forward decl */
+extern struct target_ops vx_ops, vx_run_ops;   /* Forward declaration */
+
+/* Saved name of target host and called function for "info files".
+   Both malloc'd.  */
+
+static char *vx_host;
+static char *vx_running;
+
+/* Nonzero means target that is being debugged remotely has a floating
+   point processor.  */
+
+static int target_has_fp;
+
+/* Default error message when the network is forking up.  */
+
+static const char rpcerr[] = "network target debugging:  rpc error";
+
+CLIENT *pClient;         /* client used in net debugging */
+static int ptraceSock = RPC_ANYSOCK;
+extern int errno;
+
+enum clnt_stat net_clnt_call();
+static void parse_args ();
+
+static struct timeval rpcTimeout = { 10, 0 };
+
+static char *skip_white_space ();
+static char *find_white_space ();
+/* Tell the VxWorks target system to download a file.
+   The load addresses of the text, data, and bss segments are
+   stored in pTextAddr, pDataAddr, and *pBssAddr (respectively).
+   Returns 0 for success, -1 for failure.  */
+
+static int
+net_load (filename, pTextAddr, pDataAddr, pBssAddr)
+    char *filename;
+    CORE_ADDR *pTextAddr;
+    CORE_ADDR *pDataAddr;
+    CORE_ADDR *pBssAddr;
+    {
+    enum clnt_stat status;
+    struct ldfile ldstruct;
+    struct timeval load_timeout;
+    bzero ((char *) &ldstruct, sizeof (ldstruct));
+
+    /* We invoke clnt_call () here directly, instead of through
+       net_clnt_call (), because we need to set a large timeout value.
+       The load on the target side can take quite a while, easily
+       more than 10 seconds.  The user can kill this call by typing
+       CTRL-C if there really is a problem with the load.  */
+
+    load_timeout.tv_sec = 0x7FFF7FFF;   /* A large number, effectively inf. */
+    load_timeout.tv_usec = 0;
+    status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+                       &ldstruct, load_timeout);
+
+    if (status == RPC_SUCCESS)
+      {
+        if (*ldstruct.name == NULL)    /* load failed on VxWorks side */
+          return -1;
+       *pTextAddr = ldstruct.txt_addr;
+       *pDataAddr = ldstruct.data_addr;
+       *pBssAddr = ldstruct.bss_addr;
+       return 0;
+      }
+    else
+        return -1;
+    }
+      
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
+
+static int
+net_break (addr, procnum)
+    int addr;
+    u_long procnum;
+    {
+    enum clnt_stat status;
+    int break_status;
+    Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
+                           structure.  How about something smaller? */
+
+    bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+    break_status = 0;
+
+    ptrace_in.addr = addr;
+    ptrace_in.pid = inferior_pid;
+
+    status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+                           &break_status);
+
+    if (status != RPC_SUCCESS)
+       return errno;
+
+    if (break_status == -1)
+      return ENOMEM;
+    return break_status;       /* probably (FIXME) zero */
+    }
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_insert_breakpoint (addr)
+    int addr;
+    {
+    return net_break (addr, VX_BREAK_ADD);
+    }
+
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_remove_breakpoint (addr)
+    int addr;
+    {
+    return net_break (addr, VX_BREAK_DELETE);
+    }
+
+/* Call a function on the VxWorks target system.
+   ARGS is a vector of values of arguments (NARGS of them).
+   FUNCTION is a value, the function to be called.
+   Returns a struct value * representing what the function returned.
+   May fail to return, if a breakpoint or signal is hit
+   during the execution of the function.  */
+
+#ifdef FIXME
+/* FIXME, function calls are really fried.  GO back to manual method. */
+value
+vx_call_function (function, nargs, args)
+     value function;
+     int nargs;
+     value *args;
+{
+  register CORE_ADDR sp;
+  register int i;
+  CORE_ADDR start_sp;
+  static REGISTER_TYPE dummy[] = CALL_DUMMY;
+  REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+  CORE_ADDR old_sp;
+  struct type *value_type;
+  unsigned char struct_return;
+  CORE_ADDR struct_addr;
+  struct inferior_status inf_status;
+  struct cleanup *old_chain;
+  CORE_ADDR funaddr;
+  int using_gcc;
+
+  save_inferior_status (&inf_status, 1);
+  old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+  /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+     (and POP_FRAME for restoring them).  (At least on most machines)
+     they are saved on the stack in the inferior.  */
+  PUSH_DUMMY_FRAME;
+
+  old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2             /* Stack grows down */
+  sp -= sizeof dummy;
+  start_sp = sp;
+#else                          /* Stack grows up */
+  start_sp = sp;
+  sp += sizeof dummy;
+#endif
+
+  funaddr = find_function_addr (function, &value_type);
+
+  {
+    struct block *b = block_for_pc (funaddr);
+    /* If compiled without -g, assume GCC.  */
+    using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
+  }
+
+  /* Are we returning a value using a structure return or a normal
+     value return? */
+
+  struct_return = using_struct_return (function, funaddr, value_type,
+                                      using_gcc);
+
+  /* Create a call sequence customized for this function
+     and the number of arguments for it.  */
+  bcopy (dummy, dummy1, sizeof dummy);
+  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+                 value_type, using_gcc);
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+  write_memory (start_sp, dummy1, sizeof dummy);
+
+#else /* Not on stack.  */
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+  /* Convex Unix prohibits executing in the stack segment. */
+  /* Hope there is empty room at the top of the text segment. */
+  {
+    static checked = 0;
+    if (!checked)
+      for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
+       if (read_memory_integer (start_sp, 1) != 0)
+         error ("text segment full -- no place to put call");
+    checked = 1;
+    sp = old_sp;
+    start_sp = text_end - sizeof dummy;
+    write_memory (start_sp, dummy1, sizeof dummy);
+  }
+#else /* After text_end.  */
+  {
+    int errcode;
+    sp = old_sp;
+    start_sp = text_end;
+    errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
+    if (errcode != 0)
+      error ("Cannot write text segment -- call_function failed");
+  }
+#endif /* After text_end.  */
+#endif /* Not on stack.  */
+
+#ifdef STACK_ALIGN
+  /* If stack grows down, we must leave a hole at the top. */
+  {
+    int len = 0;
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      len += TYPE_LENGTH (value_type);
+    
+    for (i = nargs - 1; i >= 0; i--)
+      len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
+#ifdef CALL_DUMMY_STACK_ADJUST
+    len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+    sp -= STACK_ALIGN (len) - len;
+#else
+    sp += STACK_ALIGN (len) - len;
+#endif
+  }
+#endif /* STACK_ALIGN */
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      {
+#if 1 INNER_THAN 2
+       sp -= TYPE_LENGTH (value_type);
+       struct_addr = sp;
+#else
+       struct_addr = sp;
+       sp += TYPE_LENGTH (value_type);
+#endif
+      }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+  {
+    /* This is a machine like the sparc, where we need to pass a pointer
+       to the structure, not the structure itself.  */
+    if (REG_STRUCT_HAS_ADDR (using_gcc))
+      for (i = nargs - 1; i >= 0; i--)
+       if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
+         {
+           CORE_ADDR addr;
+#if !(1 INNER_THAN 2)
+           /* The stack grows up, so the address of the thing we push
+              is the stack pointer before we push it.  */
+           addr = sp;
+#endif
+           /* Push the structure.  */
+           sp = value_push (sp, args[i]);
+#if 1 INNER_THAN 2
+           /* The stack grows down, so the address of the thing we push
+              is the stack pointer after we push it.  */
+           addr = sp;
+#endif
+           /* The value we're going to pass is the address of the thing
+              we just pushed.  */
+           args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
+         }
+  }
+#endif /* REG_STRUCT_HAS_ADDR.  */
+
+#ifdef PUSH_ARGUMENTS
+  PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+  for (i = nargs - 1; i >= 0; i--)
+    sp = value_arg_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+  sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+  sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+  /* Store the address at which the structure is supposed to be
+     written.  Note that this (and the code which reserved the space
+     above) assumes that gcc was used to compile this function.  Since
+     it doesn't cost us anything but space and if the function is pcc
+     it will ignore this value, we will make that assumption.
+
+     Also note that on some machines (like the sparc) pcc uses a 
+     convention like gcc's.  */
+
+  if (struct_return)
+    STORE_STRUCT_RETURN (struct_addr, sp);
+
+  /* Write the stack pointer.  This is here because the statements above
+     might fool with it.  On SPARC, this write also stores the register
+     window into the right place in the new stack frame, which otherwise
+     wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
+  write_register (SP_REGNUM, sp);
+
+  /* Figure out the value returned by the function.  */
+  {
+    char retbuf[REGISTER_BYTES];
+
+    /* Execute the stack dummy routine, calling FUNCTION.
+       When it is done, discard the empty frame
+       after storing the contents of all regs into retbuf.  */
+    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+    do_cleanups (old_chain);
+
+    return value_being_returned (value_type, retbuf, struct_return);
+  }
+}
+/* should return a value of some sort */
+value
+vx_call_function (funcAddr, nargs, args, valueType)
+    char *funcAddr;
+    int nargs;
+    value *args;
+    struct type * valueType;
+{
+    int i;
+    func_call funcInfo;
+    arg_value *argValue;
+    enum clnt_stat status;
+    register int len;
+    arg_value funcReturn;
+    value gdbValue;
+
+    argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
+
+    bzero (argValue, nargs * sizeof (arg_value));
+    bzero (&funcReturn, sizeof (funcReturn));
+
+    for (i = nargs - 1; i >= 0; i--)
+       {
+       len = TYPE_LENGTH (VALUE_TYPE (args [i]));
+
+       switch (TYPE_CODE (VALUE_TYPE (args[i])))
+           {
+           /* XXX put other types here.  Where's CHAR, etc??? */
+
+           case TYPE_CODE_FLT:
+               argValue[i].type = T_FLOAT;
+               break;
+           case TYPE_CODE_INT:
+           case TYPE_CODE_PTR:
+           case TYPE_CODE_ENUM:
+           case TYPE_CODE_FUNC:
+               argValue[i].type = T_INT;
+               break;
+
+           case TYPE_CODE_UNDEF:
+           case TYPE_CODE_ARRAY:
+           case TYPE_CODE_STRUCT:
+           case TYPE_CODE_UNION:
+           case TYPE_CODE_VOID:
+           case TYPE_CODE_SET:
+           case TYPE_CODE_RANGE:
+           case TYPE_CODE_PASCAL_ARRAY:
+           case TYPE_CODE_MEMBER:          /* C++ */
+           case TYPE_CODE_METHOD:          /* C++ */
+           case TYPE_CODE_REF:             /* C++ */
+           default:
+               error ("No corresponding VxWorks type for %d.  CHECK IT OUT!!!\n",
+                       TYPE_CODE(VALUE_TYPE(args[i])));
+           } /* switch */
+       if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
+           argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
+       else
+           bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
+                  len);
+       }
+
+    /* XXX what should the type of this function addr be?
+     * XXX Both in gdb and vxWorks
+     */
+    funcInfo.func_addr = (int) funcAddr;
+    funcInfo.args.args_len = nargs;
+    funcInfo.args.args_val = argValue;
+
+    status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
+                           xdr_arg_value, &funcReturn);
+
+    free ((char *) argValue);
+
+    if (status == RPC_SUCCESS)
+       {
+       /* XXX this assumes that vxWorks ALWAYS returns an int, and that
+        * XXX gdb isn't expecting anything more
+        */
+
+       /*******************
+       if (funcReturn.type == T_UNKNOWN)
+           return YYYXXX...;
+       *******************/
+       gdbValue = allocate_value (valueType);
+       bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
+               sizeof (int));
+        return gdbValue;
+       }
+    else 
+       error (rpcerr);
+    }
+#endif /* FIXME */
+/* Start an inferior process and sets inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.
+   Returns process id.  Errors reported with error().
+   On VxWorks, we ignore exec_file.  */
+void
+vx_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  enum clnt_stat status;
+  arg_array passArgs;
+  TASK_START taskStart;
+
+  bzero ((char *) &passArgs, sizeof (passArgs));
+  bzero ((char *) &taskStart, sizeof (taskStart));
+
+  /* parse arguments, put them in passArgs */
+
+  parse_args (args, &passArgs);
+
+  if (passArgs.arg_array_len == 0)
+    error ("You must specify a function name to run, and arguments if any");
+
+  status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
+                         xdr_TASK_START, &taskStart);
+
+  if ((status != RPC_SUCCESS) || (taskStart.status == -1))
+    error ("Can't create process on remote target machine");
+
+  /* Save the name of the running function */
+  if (vx_running)
+    free (vx_running);
+  vx_running = savestring (passArgs.arg_array_val[0],
+                          strlen (passArgs.arg_array_val[0]));
+
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
+
+  push_target (&vx_run_ops);
+  inferior_pid = taskStart.pid;
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  /* We will get a trace trap after one instruction.
+     Insert breakpoints and continue.  */
+
+  init_wait_for_inferior ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  /* remote_start(args); */
+  /* trap_expected = 0; */
+  stop_soon_quietly = 1;
+  wait_for_inferior ();                /* Get the task spawn event */
+  stop_soon_quietly = 0;
+
+  /* insert_step_breakpoint ();  FIXME, do we need this?  */
+  proceed(-1, -1, 0);
+}
+
+/* Fill ARGSTRUCT in argc/argv form with the arguments from the
+   argument string ARGSTRING.  */
+
+static void
+parse_args (arg_string, arg_struct)
+     register char *arg_string;
+     arg_array *arg_struct;
+{
+  register int arg_count = 0;  /* number of arguments */
+  register int arg_index = 0;
+  register char *p0;
+  bzero ((char *) arg_struct, sizeof (arg_array));
+  /* first count how many arguments there are */
+
+  p0 = arg_string;
+  while (*p0 != '\0')
+    {
+      if (*(p0 = skip_white_space (p0)) == '\0')
+       break;
+      p0 = find_white_space (p0);
+      arg_count++;
+    }
+
+  arg_struct->arg_array_len = arg_count;
+  arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
+                                                * sizeof (char *));
+
+  /* now copy argument strings into arg_struct.  */
+
+  while (*(arg_string = skip_white_space (arg_string)))
+    {
+      p0 = find_white_space (arg_string);
+      arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
+                                                          p0 - arg_string);
+      arg_string = p0;
+    }
+
+  arg_struct->arg_array_val[arg_count] = NULL;
+}
+
+/* Advance a string pointer across whitespace and return a pointer
+   to the first non-white character.  */
+
+static char *
+skip_white_space (p)
+     register char *p;
+{
+  while (*p == ' ' || *p == '\t')
+    p++;
+  return p;
+}
+    
+/* Search for the first unquoted whitespace character in a string.
+   Returns a pointer to the character, or to the null terminator
+   if no whitespace is found.  */
+
+static char *
+find_white_space (p)
+     register char *p;
+{
+  register int c;
+
+  while ((c = *p) != ' ' && c != '\t' && c)
+    {
+      if (c == '\'' || c == '"')
+       {
+         while (*++p != c && *p)
+           {
+             if (*p == '\\')
+               p++;
+           }
+         if (!*p)
+           break;
+       }
+      p++;
+    }
+  return p;
+}
+    
+/* Poll the VxWorks target system for an event related
+   to the debugged task.
+   Returns -1 if remote wait failed, task status otherwise.  */
+
+int
+net_wait (pEvent)
+    RDB_EVENT *pEvent;
+{
+    int pid;
+    enum clnt_stat status;
+
+    bzero ((char *) pEvent, sizeof (RDB_EVENT));
+
+    pid = inferior_pid;
+    status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
+
+    return (status == RPC_SUCCESS)? pEvent->status: -1;
+}
+    
+/* Suspend the remote task.
+   Returns -1 if suspend fails on target system, 0 otherwise.  */
+
+int
+net_quit ()
+{
+    int pid;
+    int quit_status;
+    enum clnt_stat status;
+
+    quit_status = 0;
+
+    /* don't let rdbTask suspend itself by passing a pid of 0 */
+
+    if ((pid = inferior_pid) == 0)
+       return -1;
+
+    status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+                           &quit_status);
+
+    return (status == RPC_SUCCESS)? quit_status: -1;
+}
+
+/* Read a register or registers from the remote system.  */
+
+int
+vx_read_register (regno)
+     int regno;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  /* FIXME, eventually only get the ones we need.  */
+  registers_fetched ();
+  
+  ptrace_in.pid = inferior_pid;
+  ptrace_out.info.more_data = (caddr_t) &inferior_registers;
+  status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
+  if (status)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      return -1;
+    }
+  
+#ifdef I80960
+#else  /* I80960 */
+  bcopy (&inferior_registers, registers, 16 * 4);
+  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+
+  if (target_has_fp)
+    {
+      ptrace_in.pid = inferior_pid;
+      ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
+      status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
+      if (status)
+       error (rpcerr);
+      if (ptrace_out.status == -1)
+       {
+         errno = ptrace_out.errno;
+         return -1;
+       }
+      
+      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      bcopy (&inferior_fp_registers.fps_control,
+        &registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+    }
+  else
+    {
+      bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+    }
+#endif
+  return 0;
+}
+
+/* Prepare to store registers.  Since we will store all of them,
+   read out their current values now.  */
+
+void
+vx_prepare_to_store ()
+{
+  vx_read_register (-1);
+}
+
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+   /* FIXME, look at REGNO to save time here */
+
+vx_write_register (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  bcopy (registers, &inferior_registers, 16 * 4);
+  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+  ptrace_in.pid = inferior_pid;
+  ptrace_in.info.ttype     = REGS;
+  ptrace_in.info.more_data = (caddr_t) &inferior_registers;
+
+  /* XXX change second param to be a proc number */
+  status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      return -1;
+    }
+
+  if (target_has_fp)
+    {
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+            sizeof inferior_fp_registers.fps_regs);
+      bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        &inferior_fp_registers.fps_control,
+         sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+      ptrace_in.pid = inferior_pid;
+      ptrace_in.info.ttype     = FPREGS;
+      ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
+
+      status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
+      if (status)
+         error (rpcerr);
+      if (ptrace_out.status == -1)
+       {
+         errno = ptrace_out.errno;
+         return -1;
+       }
+    }
+  return 0;
+}
+
+/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.  WRITE is true if writing to the
+   inferior.
+   Result is the number of bytes written or read (zero if error).  The
+   protocol allows us to return a negative count, indicating that we can't
+   handle the current address but can handle one N bytes further, but
+   vxworks doesn't give us that information.  */
+
+int
+vx_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  C_bytes data;
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  ptrace_in.pid = inferior_pid;                /* XXX pid unnecessary for READDATA */
+  ptrace_in.addr = (int) memaddr;      /* Where from */
+  ptrace_in.data = len;                        /* How many bytes */
+
+  if (write)
+    {
+      ptrace_in.info.ttype     = DATA;
+      ptrace_in.info.more_data = (caddr_t) &data;
+
+      data.bytes = (caddr_t) myaddr;   /* Where from */
+      data.len   = len;                        /* How many bytes (again, for XDR) */
+
+      /* XXX change second param to be a proc number */
+      status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
+    }
+  else
+    {
+      ptrace_out.info.more_data = (caddr_t) &data;
+      data.bytes = myaddr;             /* Where to */
+      data.len   = len;                        /* How many (again, for XDR) */
+
+      /* XXX change second param to be a proc number */
+      status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
+    }
+
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      return 0;                /* No bytes moved */
+    }
+  return len;          /* Moved *all* the bytes */
+}
+
+void
+vx_files_info ()
+{
+  printf ("\tAttached to host `%s'", vx_host);
+  printf (", which has %sfloating point", target_has_fp? "": "no ");
+  printf (".\n");
+}
+
+void
+vx_run_files_info ()
+{
+  printf ("\tRunning VxWorks process 0x%x, function `%s'.\n",
+         inferior_pid, vx_running);
+}
+
+void
+vx_resume (step, siggnal)
+     int step;
+     int siggnal;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+
+  if (siggnal != 0)
+    error ("Cannot send signals to VxWorks processes");
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  ptrace_in.pid = inferior_pid;
+  ptrace_in.addr = 1;  /* Target side insists on this, or it panics.  */
+
+  /* XXX change second param to be a proc number */
+  status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
+                                &ptrace_in, &ptrace_out);
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      perror_with_name ("Resuming remote process");
+    }
+}
+
+void
+vx_mourn_inferior ()
+{
+  pop_target ();               /* Pop back to no-child state */
+  generic_mourn_inferior ();
+}
+
+\f
+/* This function allows the addition of incrementally linked object files.  */
+
+void
+vx_add_file_command (arg_string, from_tty)
+     char* arg_string;
+     int from_tty;
+{
+  CORE_ADDR text_addr;
+  CORE_ADDR data_addr;
+  CORE_ADDR bss_addr;
+  
+  if (arg_string == 0)
+    error ("add-file takes a file name in VxWorks");
+
+  arg_string = tilde_expand (arg_string);
+  make_cleanup (free, arg_string);
+
+  dont_repeat ();
+
+  if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
+    error ("Load failed on target machine");
+
+  /* FIXME, for now we ignore data_addr and bss_addr.  */
+  symbol_file_add (arg_string, from_tty, text_addr, 0);
+}
+
+#ifdef FIXME  /* Not ready for prime time */
+/* Single step the target program at the source or machine level.
+   Takes an error exit if rpc fails.
+   Returns -1 if remote single-step operation fails, else 0.  */
+
+static int
+net_step ()
+{
+  enum clnt_stat status;
+  int step_status;
+  SOURCE_STEP source_step;
+
+  source_step.taskId = inferior_pid;
+
+  if (step_range_end)
+    {
+      source_step.startAddr = step_range_start;
+      source_step.endAddr = step_range_end;
+    }
+  else
+    {
+      source_step.startAddr = 0;
+      source_step.endAddr = 0;
+    }
+
+  status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
+                         xdr_int, &step_status);
+
+  if (status == RPC_SUCCESS)
+    return step_status;
+  else 
+    error (rpcerr);
+}
+#endif
+
+/* Emulate ptrace using RPC calls to the VxWorks target system.
+   Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
+
+static int
+net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
+    enum ptracereq request;
+    Rptrace *pPtraceIn;
+    Ptrace_return *pPtraceOut;
+{
+  enum clnt_stat status;
+
+  status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
+                         pPtraceOut);
+
+  if (status != RPC_SUCCESS)
+      return -1;
+
+  return 0;
+}
+
+/* Query the target for the name of the file from which VxWorks was
+   booted.  pBootFile is the address of a pointer to the buffer to
+   receive the file name; if the pointer pointed to by pBootFile is 
+   NULL, memory for the buffer will be allocated by XDR.
+   Returns -1 if rpc failed, 0 otherwise.  */
+
+int
+net_get_boot_file (pBootFile)
+     char **pBootFile;
+{
+  enum clnt_stat status;
+
+  status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
+                         xdr_wrapstring, pBootFile);
+  return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Fetch a list of loaded object modules from the VxWorks target.
+   Returns -1 if rpc failed, 0 otherwise
+   There's no way to check if the returned loadTable is correct.
+   VxWorks doesn't check it.  */
+
+int
+net_get_symbols (pLoadTable)
+     ldtabl *pLoadTable;               /* return pointer to ldtabl here */
+{
+  enum clnt_stat status;
+
+  bzero ((char *) pLoadTable, sizeof (struct ldtabl));
+
+  status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
+  return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Look up a symbol in the VxWorks target's symbol table.
+   Returns status of symbol read on target side (0=success, -1=fail)
+   Returns -1 and complain()s if rpc fails.  */
+
+struct complaint cant_contact_target =
+  {"Lost contact with VxWorks target", 0, 0};
+
+int
+vx_lookup_symbol (name, pAddr)
+     char *name;               /* symbol name */
+     CORE_ADDR *pAddr;
+{
+  enum clnt_stat status;
+  SYMBOL_ADDR symbolAddr;
+
+  *pAddr = 0;
+  bzero ((char *) &symbolAddr, sizeof (symbolAddr));
+
+  status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
+                         xdr_SYMBOL_ADDR, &symbolAddr);
+  if (status != RPC_SUCCESS) {
+      complain (&cant_contact_target, 0);
+      return -1;
+  }
+
+  *pAddr = symbolAddr.addr;
+  return symbolAddr.status;
+}
+
+/* Check to see if the VxWorks target has a floating point coprocessor.
+   Returns 1 if target has floating point processor, 0 otherwise.
+   Calls error() if rpc fails.  */
+
+int
+net_check_for_fp ()
+{
+  enum clnt_stat status;
+  bool_t fp = 0;       /* true if fp processor is present on target board */
+
+  status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
+  if (status != RPC_SUCCESS)
+      error (rpcerr);
+
+   return (int) fp;
+}
+
+/* Establish an RPC connection with the VxWorks target system.
+   Calls error () if unable to establish connection.  */
+
+void
+net_connect (host)
+     char *host;
+{
+  struct sockaddr_in destAddr;
+  struct hostent *destHost;
+
+  /* get the internet address for the given host */
+
+  if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
+      error ("Invalid hostname.  Couldn't attach remote target.");
+
+  bzero (&destAddr, sizeof (destAddr));
+
+  destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
+  destAddr.sin_family      = AF_INET;
+  destAddr.sin_port        = 0;        /* set to actual port that remote
+                                  ptrace is listening on.  */
+
+  /* Create a tcp client transport on which to issue
+     calls to the remote ptrace server.  */
+
+  ptraceSock = RPC_ANYSOCK;
+  pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
+  /* FIXME, here is where we deal with different version numbers of the proto */
+  
+  if (pClient == NULL)
+    {
+      clnt_pcreateerror ("\tnet_connect");
+      error ("Couldn't connect to remote target.");
+    }
+}
+\f
+/* Sleep for the specified number of milliseconds 
+ * (assumed to be less than 1000).
+ * If select () is interrupted, returns immediately;
+ * takes an error exit if select () fails for some other reason.
+ */
+
+static void
+sleep_ms (ms)
+     long ms;
+{
+  struct timeval select_timeout;
+  int status;
+
+  select_timeout.tv_sec = 0;
+  select_timeout.tv_usec = ms * 1000;
+
+  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
+
+  if (status < 0 && errno != EINTR)
+    perror_with_name ("select");
+}
+
+/* Wait for control to return from inferior to debugger.
+   If inferior gets a signal, we may decide to start it up again
+   instead of returning.  That is why there is a loop in this function.
+   When this function actually returns it means the inferior
+   should be left stopped and GDB should read more commands.  */
+
+/* For network debugging with VxWorks.
+ * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
+ * so vx_wait() receives this information directly from
+ * VxWorks instead of trying to figure out what happenned via a wait() call.
+ */
+
+static int
+vx_wait (status)
+     int *status;
+{
+  register int pid;
+  WAITTYPE w;
+  RDB_EVENT rdbEvent;
+  int quit_failed;
+
+  do
+    {
+      /* If CTRL-C is hit during this loop,
+        suspend the inferior process.  */
+
+      quit_failed = 0;
+      if (quit_flag)
+       {
+         quit_failed = (net_quit () == -1);
+         quit_flag = 0;
+       }
+
+      /* If a net_quit () or net_wait () call has failed,
+        allow the user to break the connection with the target.
+        We can't simply error () out of this loop, since the 
+        data structures representing the state of the inferior
+        are in an inconsistent state.  */
+
+      if (quit_failed || net_wait (&rdbEvent) == -1)
+       {
+         terminal_ours ();
+         if (query ("Can't %s.  Disconnect from target system? ",
+                    (quit_failed) ? "suspend remote task"
+                                  : "get status of remote task"))
+           {
+             target_mourn_inferior();
+             error ("Use the \"target\" command to reconnect.");
+           }
+         else
+           {
+             terminal_inferior ();
+             continue;
+           }
+       }
+      
+
+      if (quit_failed || net_wait (&rdbEvent) == -1)
+       {
+         error ("Wait on remote target failed");
+       }
+      
+      pid = rdbEvent.taskId;
+      if (pid == 0)
+       {
+         sleep_ms (200);       /* FIXME Don't kill the network too badly */
+       }
+      else if (pid != inferior_pid)
+       fatal ("Bad pid for debugged task: 0x%x\n", pid);
+    } while (pid == 0);
+
+  /* FIXME, eventually do more then SIGTRAP on everything...  */
+  switch (rdbEvent.eventType)
+    {
+    case EVENT_EXIT:
+      WSETEXIT (w, 0);
+      /* FIXME is it possible to distinguish between a
+        XXX   normal vs abnormal exit in VxWorks? */
+      break;
+
+    case EVENT_START:
+      WSETSTOP (w, SIGTRAP);
+      break;
+
+    case EVENT_STOP:
+      WSETSTOP (w, SIGTRAP);
+      /* XXX was it stopped by a signal?  act accordingly */
+      break;
+
+    case EVENT_BREAK:
+       /* Expecting a trace trap.  Stop the inferior and
+        * return silently when it happens.  */
+      WSETSTOP (w, SIGTRAP);
+      break;
+
+    case EVENT_SUSPEND:
+      target_terminal_ours_for_output ();
+      printf ("\nRemote task suspended\n");  /* FIXME */
+      fflush (stdout);
+      WSETSTOP (w, SIGTRAP);
+      break;
+
+    case EVENT_SIGNAL:
+      /* The target is not running Unix, and its
+        faults/traces do not map nicely into Unix signals.
+        Make sure they do not get confused with Unix signals
+        by numbering them with values higher than the highest
+        legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
+        routine will interpret the value for wait_for_inferior.  */
+      WSETSTOP (w, rdbEvent.sigType + NSIG);
+      break;
+    } /* switch */
+  *status = *(int *)&w;                /* Grumble union wait crap Grumble */
+  return pid;
+}
+\f
+static int
+symbol_stub (arg)
+     int arg;
+{
+  char *bootFile = (char *)arg;
+  symbol_file_command (bootFile, 0);
+  return 1;
+}
+
+static int
+add_symbol_stub (arg)
+     int arg;
+{
+  struct ldfile *pLoadFile = (struct ldfile *)arg;
+
+  symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
+  return 1;
+}
+/* Target command for VxWorks target systems.
+
+   Used in vxgdb.  Takes the name of a remote target machine
+   running vxWorks and connects to it to initialize remote network
+   debugging.  */
+
+static void
+vx_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  extern int close ();
+  char *bootFile;
+  extern char *source_path;
+  struct ldtabl loadTable;
+  struct ldfile *pLoadFile;
+  int i;
+  extern CLIENT *pClient;
+
+  if (!args)
+    error_no_arg ("target machine name");
+
+  printf ("Attaching remote machine across net...\n");
+  fflush (stdout);
+
+  /* Allow the user to kill the connect attempt by typing ^C.
+     Wait until the call to target_has_fp () completes before
+     disallowing an immediate quit, since even if net_connect ()
+     is successful, the remote debug server might be hung.  */
+
+  immediate_quit++;
+
+  net_connect (args);
+  target_has_fp = net_check_for_fp ();
+  printf_filtered ("Connected to %s\n", args);
+
+  immediate_quit--;
+
+  push_target (&vx_ops);
+
+  /* Save a copy of the target host's name.  */
+  if (vx_host)
+    free (vx_host);
+  vx_host = savestring (args, strlen (args));
+
+  /* Find out the name of the file from which the target was booted
+     and load its symbol table.  */
+
+  bootFile = NULL;
+  if (!net_get_boot_file (&bootFile))
+    {
+      if (*bootFile) {
+       printf_filtered ("%s: ", bootFile);
+       if (catch_errors (symbol_stub, (int)bootFile,
+               "Error reading symbols from boot file"))
+         puts_filtered ("ok\n");
+      } else if (from_tty)
+       printf ("VxWorks kernel symbols not loaded.\n");
+    }
+  else
+    error ("Can't retrieve boot file name from target machine.");
+
+  clnt_freeres (pClient, xdr_wrapstring, &bootFile);
+
+  if (net_get_symbols (&loadTable) != 0)
+    error ("Can't read loaded modules from target machine");
+
+  i = 0-1;
+  while (++i < loadTable.tbl_size)
+    {
+    QUIT;      /* FIXME, avoids clnt_freeres below:  mem leak */
+    pLoadFile = &loadTable.tbl_ent [i];
+#ifdef WRS_ORIG
+  {
+    register int desc;
+    struct cleanup *old_chain;
+    char *fullname = NULL;
+
+    desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
+    if (desc < 0)
+       perror_with_name (pLoadFile->name);
+    old_chain = make_cleanup (close, desc);
+    add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
+                     pLoadFile->bss_addr);
+    do_cleanups (old_chain);
+  }
+#else
+    /* Botches, FIXME:
+       (1)  Searches the PATH, not the source path.
+       (2)  data and bss are assumed to be at the usual offsets from text.  */
+    catch_errors (add_symbol_stub, (int)pLoadFile,
+       "Error in reading symbols from loaded module.");
+#endif
+    }
+
+  clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+
+  if (from_tty)
+    {
+      puts_filtered ("Success!\n");
+    }
+}
+\f
+/* Cross-net conversion of floats to and from extended form.
+   (This is needed because different target machines have different
+    extended floating point formats.)  */
+
+/* Convert from an extended float to a double.
+
+   The extended float is stored as raw data pointed to by FROM.
+   Return the converted value as raw data in the double pointed to by TO.
+*/
+
+static void
+vx_convert_to_virtual (regno, from, to)
+    int regno;
+    char *from;
+    char *to;
+{
+  enum clnt_stat status;
+  ext_fp from_ext_fp;
+  double to_double;
+
+  if (REGISTER_CONVERTIBLE (regno)) 
+    {
+      if (!target_has_fp) {
+       *(double *)to = 0.0;    /* Skip the trouble if no float anyway */
+       return;
+      }
+      bcopy (from, (char *) &from_ext_fp, sizeof (from_ext_fp));
+      bzero ((char *) &to_double, sizeof (to_double));
+
+      status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, &from_ext_fp,
+                             xdr_double, &to_double);
+      if (status == RPC_SUCCESS)
+         bcopy ((char *) &to_double, to, sizeof (to_double));
+      else
+         error (rpcerr);
+    }
+  else
+    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+
+
+/* The converse:  convert from a double to an extended float.
+
+   The double is stored as raw data pointed to by FROM.
+   Return the converted value as raw data in the extended
+   float pointed to by TO.
+*/
+
+static void
+vx_convert_from_virtual (regno, from, to)
+    int regno;
+    char *from;
+    char *to;
+{
+  enum clnt_stat status;
+  ext_fp to_ext_fp;
+  double from_double;
+
+  if (REGISTER_CONVERTIBLE (regno)) 
+    {
+      if (!target_has_fp) {
+       bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM));     /* Shrug */
+       return;
+      }
+      bcopy (from, (char *) &from_double, sizeof (from_double));
+      bzero ((char *) &to_ext_fp, sizeof (to_ext_fp));
+
+      status = net_clnt_call (VX_CONV_TO_68881, xdr_double, &from_double,
+                             xdr_ext_fp, &to_ext_fp);
+      if (status == RPC_SUCCESS)
+         bcopy ((char *) &to_ext_fp, to, sizeof (to_ext_fp));
+      else
+         error (rpcerr);
+    }
+  else
+    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+\f
+/* Make an RPC call to the VxWorks target.
+   Returns RPC status.  */
+
+static enum clnt_stat
+net_clnt_call (procNum, inProc, in, outProc, out)
+    enum ptracereq procNum;
+    xdrproc_t inProc;
+    char *in;
+    xdrproc_t outProc;
+    char *out;
+{
+  enum clnt_stat status;
+  
+  status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
+
+  if (status != RPC_SUCCESS)
+      clnt_perrno (status);
+
+  return status;
+}
+
+
+/* Target ops structure for accessing memory and such over the net */
+
+struct target_ops vx_ops = {
+       "vxworks", "VxWorks target memory via RPC over TCP/IP",
+       vx_open, 0, /* vx_detach, */
+       0, 0, /* resume, wait */
+       0, 0, /* read_reg, write_reg */
+       0, vx_convert_to_virtual, vx_convert_from_virtual,  /* prep_to_store, */
+       vx_xfer_memory, vx_files_info,
+       0, 0, /* insert_breakpoint, remove_breakpoint */
+       0, 0, 0, 0, 0,  /* terminal stuff */
+       0, /* vx_kill, */
+       vx_add_file_command,
+       call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
+       vx_lookup_symbol,
+       vx_create_inferior, 0,  /* mourn_inferior */
+       core_stratum, 0, /* next */
+       1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+/* Target ops structure for accessing VxWorks child processes over the net */
+
+struct target_ops vx_run_ops = {
+       "vxprocess", "VxWorks process",
+       vx_open, 0, /* vx_detach, */
+       vx_resume, vx_wait,
+       vx_read_register, vx_write_register,
+       vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
+       vx_xfer_memory, vx_run_files_info,
+       vx_insert_breakpoint, vx_remove_breakpoint,
+       0, 0, 0, 0, 0,  /* terminal stuff */
+       0, /* vx_kill, */
+       vx_add_file_command,
+       call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
+       vx_lookup_symbol,
+       vx_create_inferior, vx_mourn_inferior,
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+/* ==> Remember when reading at end of file, there are two "ops" structs here. */
+\f
+void
+_initialize_vx ()
+{
+  add_target (&vx_ops);
+  add_target (&vx_run_ops);
+}
diff --git a/gdb/symm-tdep.c b/gdb/symm-tdep.c
new file mode 100644 (file)
index 0000000..aba21c3
--- /dev/null
@@ -0,0 +1,494 @@
+/* Sequent Symmetry target interface, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+exec_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+
+  /* Eliminate all traces of old exec file.
+     Mark text segment as empty.  */
+
+  if (execfile)
+    free (execfile);
+  execfile = 0;
+  data_start = 0;
+  data_end -= exec_data_start;
+  text_start = 0;
+  text_end = 0;
+  exec_data_start = 0;
+  exec_data_end = 0;
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+
+  /* Now open and digest the file the user requested, if any.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                       &execfile);
+      if (execchan < 0)
+       perror_with_name (filename);
+
+#ifdef COFF_FORMAT
+      {
+       int aout_hdrsize;
+       int num_sections;
+
+       if (read_file_hdr (execchan, &file_hdr) < 0)
+         error ("\"%s\": not in executable format.", execfile);
+
+       aout_hdrsize = file_hdr.f_opthdr;
+       num_sections = file_hdr.f_nscns;
+
+       if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+         error ("\"%s\": can't read optional aouthdr", execfile);
+
+       if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
+                             aout_hdrsize) < 0)
+         error ("\"%s\": can't read text section header", execfile);
+
+       if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
+                             aout_hdrsize) < 0)
+         error ("\"%s\": can't read data section header", execfile);
+
+       text_start = exec_aouthdr.text_start;
+       text_end = text_start + exec_aouthdr.tsize;
+       text_offset = text_hdr.s_scnptr;
+       exec_data_start = exec_aouthdr.data_start;
+       exec_data_end = exec_data_start + exec_aouthdr.dsize;
+       exec_data_offset = data_hdr.s_scnptr;
+       data_start = exec_data_start;
+       data_end += exec_data_start;
+       exec_mtime = file_hdr.f_timdat;
+      }
+#else /* not COFF_FORMAT */
+      {
+       struct stat st_exec;
+
+       val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
+
+       if (val < 0)
+         perror_with_name (filename);
+
+       text_start = N_ADDRADJ(exec_aouthdr);
+        exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
+       text_offset = N_TXTOFF (exec_aouthdr);
+       exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+       text_end = exec_aouthdr.a_text;
+        exec_data_end = exec_data_start + exec_aouthdr.a_data;
+       data_start = exec_data_start;
+       data_end = data_start + exec_aouthdr.a_data;
+       exec_data_offset = N_TXTOFF(exec_aouthdr);
+       fstat (execchan, &st_exec);
+       exec_mtime = st_exec.st_mtime;
+      }
+#endif /* not COFF_FORMAT */
+
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No exec file now.\n");
+
+  /* Tell display code (if any) about the changed file name.  */
+  if (exec_file_display_hook)
+    (*exec_file_display_hook) (filename);
+}
+
+/* rounds 'one' up to divide evenly by 'two' */
+
+int
+round(one,two)
+register int one, two;
+
+{
+    register int temp;
+    temp = (one/two)*two;
+    if (one != temp) {
+       temp += two;
+    }
+    return temp;
+}
+
+
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+                          codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+                        codestream_fill(0) : codestream_buf[codestream_off++])
+
+
+static unsigned char 
+codestream_fill (peek_flag)
+{
+  codestream_addr = codestream_next_addr;
+  codestream_next_addr += sizeof (int);
+  codestream_off = 0;
+  codestream_cnt = sizeof (int);
+  read_memory (codestream_addr,
+              (unsigned char *)codestream_buf,
+              sizeof (int));
+  
+  if (peek_flag)
+    return (codestream_peek());
+  else
+    return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+  codestream_next_addr = place & -sizeof (int);
+  codestream_cnt = 0;
+  codestream_fill (1);
+  while (codestream_tell() != place)
+    codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+     unsigned char *buf;
+{
+  unsigned char *p;
+  int i;
+  p = buf;
+  for (i = 0; i < count; i++)
+    *p++ = codestream_get ();
+}
+
+/*
+ * Following macro translates i386 opcode register numbers to Symmetry
+ * register numbers.  This is used by FRAME_FIND_SAVED_REGS.
+ *
+ *           %eax  %ecx  %edx  %ebx  %esp  %ebp  %esi  %edi
+ * i386        0     1     2     3     4     5     6     7
+ * Symmetry    0     2     1     5    14    15     6     7
+ *
+ */
+#define I386_REGNO_TO_SYMMETRY(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
+
+/* from i386-dep.c */
+i386_frame_find_saved_regs (fip, fsrp)
+     struct frame_info *fip;
+     struct frame_saved_regs *fsrp;
+{
+  unsigned long locals;
+  unsigned char *p;
+  unsigned char op;
+  CORE_ADDR dummy_bottom;
+  CORE_ADDR adr;
+  int i;
+  
+  bzero (fsrp, sizeof *fsrp);
+  
+  /* if frame is the end of a dummy, compute where the
+   * beginning would be
+   */
+  dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
+  
+  /* check if the PC is in the stack, in a dummy frame */
+  if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
+    {
+      /* all regs were saved by push_call_dummy () */
+      adr = fip->frame - 4;
+      for (i = 0; i < NUM_REGS; i++) 
+       {
+         fsrp->regs[i] = adr;
+         adr -= 4;
+       }
+      return;
+    }
+  
+  locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+  
+  if (locals >= 0) 
+    {
+      adr = fip->frame - 4 - locals;
+      for (i = 0; i < 8; i++) 
+       {
+         op = codestream_get ();
+         if (op < 0x50 || op > 0x57)
+           break;
+         fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
+         adr -= 4;
+       }
+    }
+  
+  fsrp->regs[PC_REGNUM] = fip->frame + 4;
+  fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+static long
+i386_get_frame_setup (pc)
+{
+  unsigned char op;
+  
+  codestream_seek (pc);
+  
+  i386_follow_jump ();
+  
+  op = codestream_get ();
+  
+  if (op == 0x58) /* popl %eax */
+    {
+      /*
+       * this function must start with
+       * 
+       *    popl %eax            0x58
+       *    xchgl %eax, (%esp)  0x87 0x04 0x24
+       * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+       *
+       * (the system 5 compiler puts out the second xchg
+       * inst, and the assembler doesn't try to optimize it,
+       * so the 'sib' form gets generated)
+       * 
+       * this sequence is used to get the address of the return
+       * buffer for a function that returns a structure
+       */
+      int pos;
+      unsigned char buf[4];
+      static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+      static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+      pos = codestream_tell ();
+      codestream_read (buf, 4);
+      if (bcmp (buf, proto1, 3) == 0)
+       pos += 3;
+      else if (bcmp (buf, proto2, 4) == 0)
+       pos += 4;
+      
+      codestream_seek (pos);
+      op = codestream_get (); /* update next opcode */
+    }
+  
+  if (op == 0x55)                      /* pushl %esp */
+    {
+      if (codestream_get () != 0x8b)   /* movl %esp, %ebp (2bytes) */
+       return (-1);
+      if (codestream_get () != 0xec)
+       return (-1);
+      /*
+       * check for stack adjustment 
+       *
+       *  subl $XXX, %esp
+       *
+       * note: you can't subtract a 16 bit immediate
+       * from a 32 bit reg, so we don't have to worry
+       * about a data16 prefix 
+       */
+      op = codestream_peek ();
+      if (op == 0x83)  /* subl with 8 bit immed */
+       {
+         codestream_get ();
+         if (codestream_get () != 0xec)
+           return (-1);
+         /* subl with signed byte immediate 
+          * (though it wouldn't make sense to be negative)
+          */
+         return (codestream_get());
+       }
+      else if (op == 0x81)  /* subl with 32 bit immed */
+       {
+         int locals;
+         if (codestream_get () != 0xec)
+           return (-1);
+         /* subl with 32 bit immediate */
+         codestream_read ((unsigned char *)&locals, 4);
+         return (locals);
+       } 
+      else 
+       {
+         return (0);
+       }
+    } 
+  else if (op == 0xc8) 
+    {
+      /* enter instruction: arg is 16 unsigned immed */
+      unsigned short slocals;
+      codestream_read ((unsigned char *)&slocals, 2);
+      codestream_get (); /* flush final byte of enter instruction */
+      return (slocals);
+    }
+  return (-1);
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+  int long_delta;
+  short short_delta;
+  char byte_delta;
+  int data16;
+  int pos;
+  
+  pos = codestream_tell ();
+  
+  data16 = 0;
+  if (codestream_peek () == 0x66)
+    {
+      codestream_get ();
+      data16 = 1;
+    }
+  
+  switch (codestream_get ())
+    {
+    case 0xe9:
+      /* relative jump: if data16 == 0, disp32, else disp16 */
+      if (data16)
+       {
+         codestream_read ((unsigned char *)&short_delta, 2);
+         pos += short_delta + 3; /* include size of jmp inst */
+       }
+      else
+       {
+         codestream_read ((unsigned char *)&long_delta, 4);
+         pos += long_delta + 5;
+       }
+      break;
+    case 0xeb:
+      /* relative jump, disp8 (ignore data16) */
+      codestream_read ((unsigned char *)&byte_delta, 1);
+      pos += byte_delta + 2;
+      break;
+    }
+  codestream_seek (pos + data16);
+}
+
+/* return pc of first real instruction */
+/* from i386-dep.c */
+
+i386_skip_prologue (pc)
+{
+  unsigned char op;
+  int i;
+  
+  if (i386_get_frame_setup (pc) < 0)
+    return (pc);
+  
+  /* found valid frame setup - codestream now points to 
+   * start of push instructions for saving registers
+   */
+  
+  /* skip over register saves */
+  for (i = 0; i < 8; i++)
+    {
+      op = codestream_peek ();
+      /* break if not pushl inst */
+      if (op < 0x50 || op > 0x57) 
+       break;
+      codestream_get ();
+    }
+  
+  i386_follow_jump ();
+  
+  return (codestream_tell ());
+}
+
+symmetry_extract_return_value(type, regbuf, valbuf)
+     struct type *type;
+     char *regbuf;
+     char *valbuf;
+{
+  union { 
+    double     d; 
+    int        l[2]; 
+  } xd; 
+  int i;
+  float f;
+
+  if (TYPE_CODE_FLT == TYPE_CODE(type)) { 
+    for (i = 0; i < misc_function_count; i++) {
+      if (!strcmp(misc_function_vector[i].name, "1167_flt"))
+       break;
+    }
+    if (i < misc_function_count) {
+      /* found "1167_flt" means 1167, %fp2-%fp3 */ 
+      /* float & double; 19= %fp2, 20= %fp3 */
+      /* no single precision on 1167 */
+      xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
+      xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
+      switch (TYPE_LENGTH(type)) {
+      case 4:
+       f = (float) xd.d;
+       bcopy(&f, valbuf, TYPE_LENGTH(type));
+       break;
+      case 8:
+       bcopy(&xd.d, valbuf, TYPE_LENGTH(type)); 
+       break;
+      default:
+       error("Unknown floating point size");
+       break;
+      }
+    } else { 
+      /* 387 %st(0), gcc uses this */ 
+      i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
+                    &xd.d); 
+      switch (TYPE_LENGTH(type)) {
+      case 4:                  /* float */
+       f = (float) xd.d;
+       bcopy(&f, valbuf, 4); 
+       break;
+      case 8:                  /* double */
+       bcopy(&xd.d, valbuf, 8);
+       break;
+      default:
+       error("Unknown floating point size");
+       break;
+      }
+    }
+  } else { 
+    bcopy (regbuf, valbuf, TYPE_LENGTH (type)); 
+  }
+}
diff --git a/gdb/symm-xdep.c b/gdb/symm-xdep.c
new file mode 100644 (file)
index 0000000..3449678
--- /dev/null
@@ -0,0 +1,557 @@
+/* Sequent Symmetry host interface, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+store_inferior_registers(regno)
+int regno;
+{
+  struct pt_regset regs;
+  int reg_tmp, i;
+  extern char registers[];
+  
+#if 0
+  /* PREPARE_TO_STORE deals with this.  */
+  if (-1 == regno)
+    {
+#endif
+      regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+      regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+      regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+      regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+      regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+      regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+      regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+      regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+      regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+      regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+      for (i = 0; i < 31; i++) {
+       regs.pr_fpa.fpa_regs[i] =
+         *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)];
+      }
+#if 0
+    }
+  else
+    {
+      reg_tmp = *(int *)&registers[REGISTER_BYTE(regno)];
+      ptrace(XPT_RREGS, inferior_pid, &regs, 0);
+      switch (regno)
+       {
+       case 0:
+         regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+         break;
+       case 5:
+         regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+         break;
+       case 2:
+         regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+         break;
+       case 1:
+         regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+         break;
+       case 6:
+         regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+         break;
+       case 7:
+         regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+         break;
+       case 15:
+         regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+         break;
+       case 14:
+         regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+         break;
+       case 16:
+         regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+         break;
+       case 17:
+         regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+         break;
+       }
+    }
+#endif /* 0 */
+  ptrace(XPT_WREGS, inferior_pid, &regs, 0);
+}
+
+void
+fetch_inferior_registers()
+{
+    int i;
+    struct pt_regset regs;
+    extern char registers[];
+
+    registers_fetched ();
+    
+    ptrace(XPT_RREGS, inferior_pid, &regs, 0);
+    *(int *)&registers[REGISTER_BYTE(0)] = regs.pr_eax;
+    *(int *)&registers[REGISTER_BYTE(5)] = regs.pr_ebx;
+    *(int *)&registers[REGISTER_BYTE(2)] = regs.pr_ecx;
+    *(int *)&registers[REGISTER_BYTE(1)] = regs.pr_edx;
+    *(int *)&registers[REGISTER_BYTE(6)] = regs.pr_esi;
+    *(int *)&registers[REGISTER_BYTE(7)] = regs.pr_edi;
+    *(int *)&registers[REGISTER_BYTE(15)] = regs.pr_ebp;
+    *(int *)&registers[REGISTER_BYTE(14)] = regs.pr_esp;
+    *(int *)&registers[REGISTER_BYTE(16)] = regs.pr_eip;
+    *(int *)&registers[REGISTER_BYTE(17)] = regs.pr_flags;
+    for (i = 0; i < FPA_NREGS; i++) {
+       *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i];
+    }
+    bcopy(regs.pr_fpu.fpu_stack[0], &registers[REGISTER_BYTE(3)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[1], &registers[REGISTER_BYTE(4)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[2], &registers[REGISTER_BYTE(8)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[3], &registers[REGISTER_BYTE(9)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[4], &registers[REGISTER_BYTE(10)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[5], &registers[REGISTER_BYTE(11)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[6], &registers[REGISTER_BYTE(12)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[7], &registers[REGISTER_BYTE(13)], 10);
+}
+
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+#include "gdbcore.h"
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * (u.u_dsize - u.u_tsize);
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = ctob(UPAGES + u.u_dsize - u.u_tsize);
+       reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+printf("u.u_tsize= %#x, u.u_dsize= %#x, u.u_ssize= %#x, stack_off= %#x\n",
+       u.u_tsize, u.u_dsize, u.u_ssize, stack_offset);
+
+       core_aouthdr.a_magic = 0;
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0)
+               perror_with_name (filename);
+
+             val = myread (corechan, buf, sizeof buf);
+             if (val < 0)
+               perror_with_name (filename);
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame(create_new_frame(read_register(FP_REGNUM),
+                                        read_pc()));
+/*      set_current_frame (read_register (FP_REGNUM));*/
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
+
+/* from i386-dep.c */
+static
+print_387_control_word (control)
+unsigned short control;
+{
+  printf ("control 0x%04x: ", control);
+  printf ("compute to ");
+  switch ((control >> 8) & 3) 
+    {
+    case 0: printf ("24 bits; "); break;
+    case 1: printf ("(bad); "); break;
+    case 2: printf ("53 bits; "); break;
+    case 3: printf ("64 bits; "); break;
+    }
+  printf ("round ");
+  switch ((control >> 10) & 3) 
+    {
+    case 0: printf ("NEAREST; "); break;
+    case 1: printf ("DOWN; "); break;
+    case 2: printf ("UP; "); break;
+    case 3: printf ("CHOP; "); break;
+    }
+  if (control & 0x3f) 
+    {
+      printf ("mask:");
+      if (control & 0x0001) printf (" INVALID");
+      if (control & 0x0002) printf (" DENORM");
+      if (control & 0x0004) printf (" DIVZ");
+      if (control & 0x0008) printf (" OVERF");
+      if (control & 0x0010) printf (" UNDERF");
+      if (control & 0x0020) printf (" LOS");
+      printf (";");
+    }
+  printf ("\n");
+  if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+                               control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+     unsigned short status;
+{
+  printf ("status %#04x: ", status);
+  if (status & 0xff) {
+      printf ("exceptions:");  /* exception names match <machine/fpu.h> */
+      if (status & 0x0001) printf (" FLTINV");
+      if (status & 0x0002) printf (" FLTDEN");
+      if (status & 0x0004) printf (" FLTDIV");
+      if (status & 0x0008) printf (" FLTOVF");
+      if (status & 0x0010) printf (" FLTUND");
+      if (status & 0x0020) printf (" FLTPRE");
+      if (status & 0x0040) printf (" FLTSTK");
+      printf ("; ");
+    }
+  printf ("flags: %d%d%d%d; ",
+         (status & 0x4000) != 0,
+         (status & 0x0400) != 0,
+         (status & 0x0200) != 0,
+         (status & 0x0100) != 0);
+  
+  printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_fpu_status(ep)
+struct pt_regset ep;
+
+{
+    int i;
+    int bothstatus;
+    int top;
+    int fpreg;
+    unsigned char *p;
+    
+    printf("80387:");
+    if (ep.pr_fpu.fpu_ip == 0) {
+       printf(" not in use.\n");
+       return;
+    } else {
+       printf("\n");
+    }
+    if (ep.pr_fpu.fpu_status != 0) {
+       print_387_status_word (ep.pr_fpu.fpu_status);
+    }
+    print_387_control_word (ep.pr_fpu.fpu_control);
+    printf ("last exception: ");
+    printf ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
+    printf ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
+    printf ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
+    
+    top = (ep.pr_fpu.fpu_status >> 11) & 7;
+    
+    printf ("regno  tag  msb              lsb  value\n");
+    for (fpreg = 7; fpreg >= 0; fpreg--) 
+       {
+           double val;
+           
+           printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
+           
+           switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3) 
+               {
+               case 0: printf ("valid "); break;
+               case 1: printf ("zero  "); break;
+               case 2: printf ("trap  "); break;
+               case 3: printf ("empty "); break;
+               }
+           for (i = 9; i >= 0; i--)
+               printf ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
+           
+           i387_to_double (ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
+           printf ("  %g\n", val);
+       }
+    if (ep.pr_fpu.fpu_rsvd1)
+       printf ("warning: rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
+    if (ep.pr_fpu.fpu_rsvd2)
+       printf ("warning: rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
+    if (ep.pr_fpu.fpu_rsvd3)
+       printf ("warning: rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
+    if (ep.pr_fpu.fpu_rsvd5)
+       printf ("warning: rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
+}
+
+
+print_1167_control_word(pcr)
+unsigned int pcr;
+
+{
+    int pcr_tmp;
+
+    pcr_tmp = pcr & FPA_PCR_MODE;
+    printf("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
+    switch (pcr_tmp & 12) {
+    case 0:
+       printf("RN (Nearest Value)");
+       break;
+    case 1:
+       printf("RZ (Zero)");
+       break;
+    case 2:
+       printf("RP (Positive Infinity)");
+       break;
+    case 3:
+       printf("RM (Negative Infinity)");
+       break;
+    }
+    printf("; IRND= %d ", pcr_tmp & 2);
+    if (0 == pcr_tmp & 2) {
+       printf("(same as RND)\n");
+    } else {
+       printf("(toward zero)\n");
+    }
+    pcr_tmp = pcr & FPA_PCR_EM;
+    printf("\tEM= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_EM_DM) printf(" DM");
+    if (pcr_tmp & FPA_PCR_EM_UOM) printf(" UOM");
+    if (pcr_tmp & FPA_PCR_EM_PM) printf(" PM");
+    if (pcr_tmp & FPA_PCR_EM_UM) printf(" UM");
+    if (pcr_tmp & FPA_PCR_EM_OM) printf(" OM");
+    if (pcr_tmp & FPA_PCR_EM_ZM) printf(" ZM");
+    if (pcr_tmp & FPA_PCR_EM_IM) printf(" IM");
+    printf("\n");
+    pcr_tmp = FPA_PCR_CC;
+    printf("\tCC= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_20MHZ) printf(" 20MHZ");
+    if (pcr_tmp & FPA_PCR_CC_Z) printf(" Z");
+    if (pcr_tmp & FPA_PCR_CC_C2) printf(" C2");
+    if (pcr_tmp & FPA_PCR_CC_C1) printf(" C1");
+    switch (pcr_tmp) {
+    case FPA_PCR_CC_Z:
+       printf(" (Equal)");
+       break;
+    case FPA_PCR_CC_C1:
+       printf(" (Less than)");
+       break;
+    case 0:
+       printf(" (Greater than)");
+       break;
+    case FPA_PCR_CC_Z | FPA_PCR_CC_C1 | FPA_PCR_CC_C2:
+       printf(" (Unordered)");
+       break;
+    default:
+       printf(" (Undefined)");
+       break;
+    }
+    printf("\n");
+    pcr_tmp = pcr & FPA_PCR_AE;
+    printf("\tAE= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_AE_DE) printf(" DE");
+    if (pcr_tmp & FPA_PCR_AE_UOE) printf(" UOE");
+    if (pcr_tmp & FPA_PCR_AE_PE) printf(" PE");
+    if (pcr_tmp & FPA_PCR_AE_UE) printf(" UE");
+    if (pcr_tmp & FPA_PCR_AE_OE) printf(" OE");
+    if (pcr_tmp & FPA_PCR_AE_ZE) printf(" ZE");
+    if (pcr_tmp & FPA_PCR_AE_EE) printf(" EE");
+    if (pcr_tmp & FPA_PCR_AE_IE) printf(" IE");
+    printf("\n");
+}
+
+print_1167_regs(regs)
+long regs[FPA_NREGS];
+
+{
+    int i;
+
+    union {
+       double  d;
+       long    l[2];
+    } xd;
+    union {
+       float   f;
+       long    l;
+    } xf;
+
+
+    for (i = 0; i < FPA_NREGS; i++) {
+       xf.l = regs[i];
+       printf("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
+       if (!(i & 1)) {
+           printf("\n");
+       } else {
+           xd.l[1] = regs[i];
+           xd.l[0] = regs[i+1];
+           printf(", double= %f\n", xd.d);
+       }
+    }
+}
+
+print_fpa_status(ep)
+struct pt_regset ep;
+
+{
+
+    printf("WTL 1167:");
+    if (ep.pr_fpa.fpa_pcr !=0) {
+       printf("\n");
+       print_1167_control_word(ep.pr_fpa.fpa_pcr);
+       print_1167_regs(ep.pr_fpa.fpa_regs);
+    } else {
+       printf(" not in use.\n");
+    }
+}
+
+i386_float_info ()
+
+{
+    char ubuf[UPAGES*NBPG];
+    struct pt_regset regset;
+    extern int corechan;
+    
+    if (have_inferior_p()) {
+       call_ptrace(XPT_RREGS, inferior_pid, &regset, 0);
+    } else {
+       if (lseek (corechan, 0, 0) < 0) {
+           perror ("seek on core file");
+       }
+       if (myread (corechan, ubuf, UPAGES*NBPG) < 0) {
+           perror ("read on core file");
+       }
+       /* only interested in the floating point registers */
+       regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
+       regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
+    }
+    print_fpu_status(regset);
+    print_fpa_status(regset);
+}
+
+i387_to_double (from, to)
+     char *from;
+     char *to;
+{
+  long *lp;
+  /* push extended mode on 387 stack, then pop in double mode
+   *
+   * first, set exception masks so no error is generated -
+   * number will be rounded to inf or 0, if necessary 
+   */
+  asm ("pushl %eax");          /* grab a stack slot */
+  asm ("fstcw (%esp)");                /* get 387 control word */
+  asm ("movl (%esp),%eax");    /* save old value */
+  asm ("orl $0x3f,%eax");              /* mask all exceptions */
+  asm ("pushl %eax");
+  asm ("fldcw (%esp)");                /* load new value into 387 */
+  
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldt (%eax)");         /* push extended number on 387 stack */
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpl (%eax)");                /* pop double */
+  asm ("fwait");
+  
+  asm ("popl %eax");           /* flush modified control word */
+  asm ("fnclex");                      /* clear exceptions */
+  asm ("fldcw (%esp)");                /* restore original control word */
+  asm ("popl %eax");           /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+     char *from;
+     char *to;
+{
+  /* push double mode on 387 stack, then pop in extended mode
+   * no errors are possible because every 64-bit pattern
+   * can be converted to an extended
+   */
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldl (%eax)");
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpt (%eax)");
+  asm ("fwait");
+}
diff --git a/gdb/tm-vx68.h b/gdb/tm-vx68.h
new file mode 100644 (file)
index 0000000..a3cd7c2
--- /dev/null
@@ -0,0 +1,48 @@
+/* Parameters for execution on VxWorks 68k's, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define        GDBINIT_FILENAME        ".vxgdbinit"
+
+#define        DEFAULT_PROMPT          "(vxgdb) "
+
+/* Kludge... */
+#include "tm-sun3.h"
+
+/* We have more complex, useful breakpoints on the target.  */
+#undef DECR_PC_AFTER_BREAK
+#define        DECR_PC_AFTER_BREAK     0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+#undef FRAME_CHAIN
+#undef FRAME_CHAIN_VALID
+
+/* Takes the current frame-struct pointer and returns the chain-pointer
+   to get to the calling frame.
+
+   If our current frame pointer is zero, we're at the top; else read out
+   the saved FP from memory pointed to by the current FP.  */
+
+#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
+
+/* If the chain pointer is zero (either because the saved value fetched
+   by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
+   never fetched anything), we are at the top of the stack.  */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
diff --git a/gdb/tm-vx960.h b/gdb/tm-vx960.h
new file mode 100644 (file)
index 0000000..fc5c214
--- /dev/null
@@ -0,0 +1,48 @@
+/* Parameters for VxWorks Intel 960's, for GDB, the GNU debugger.
+   Copyright (C) 1986-1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "tm-i960.h"
+
+#define        GDBINIT_FILENAME        ".vxgdbinit"
+
+#define        DEFAULT_PROMPT          "(vxgdb) "
+
+/* We have more complex, useful breakpoints on the target.
+   Amount ip must be decremented by after a breakpoint.  */
+
+#define        DECR_PC_AFTER_BREAK     0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
+
+/* Breakpoint patching is handled at the target end in VxWorks.  */
+/* #define BREAKPOINT {0x00, 0x3e, 0x00, 0x66} */
+
+/* Not needed, because we don't support core files:
+       #define KERNEL_U_ADDR
+       #define REGISTER_U_ADDR(addr, blockend, regno)
+ */
+
+/* Address of end of stack space.
+       This doesn't matter for VxWorks, because it's only used
+       in manipulation of core files, which we don't support.  */
+
+/* #define STACK_END_ADDR (0xfe000000) */
diff --git a/gdb/xm-i386sco.h b/gdb/xm-i386sco.h
new file mode 100644 (file)
index 0000000..e8ecc99
--- /dev/null
@@ -0,0 +1,37 @@
+/* Macro defintions for i386, running SCO Unix System V/386 3.2.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+   the name of this field is.  */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
+   is not.  This makes problems for inflow.c.  */
+#define TIOCGETC_BROKEN
+
+/* All the job control definitions exist in SCO Unix, but the standard
+   shells don't use them.  So we must disable job control. */
+#define NO_JOB_CONTROL
+
+/* SCO's assembler doesn't grok dollar signs in identifiers.
+   So we use dots instead.  This item must be coordinated with G++. */
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'