--- /dev/null
+/* 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 */
+};
--- /dev/null
+_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
--- /dev/null
+_divert__(-1)
+_define__(<_AMD29K__>,<1>)
+_define__(<_HOST__>,<AMD 29K>)
+_define__(<_MACH_DEP__>,<AMD29K Dependent>
+_divert__<>
\ No newline at end of file
--- /dev/null
+_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
--- /dev/null
+_divert__(-1)
+_define__(<_I80386__>,<1>)
+_define__(<_HOST__>,<Intel 80386>)
+_define__(<_MACH_DEP__>,<80386 Dependent>
+_divert__<>
\ No newline at end of file
--- /dev/null
+_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
--- /dev/null
+_divert__(-1)
+_define__(<_M680X0__>,<1>)
+_define__(<_HOST__>,<Motorola 680x0>)
+_define__(<_MACH_DEP__>,<M680x0 Dependent>)
+_divert__<>
\ No newline at end of file
--- /dev/null
+_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
--- /dev/null
+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__<>
--- /dev/null
+_divert__(-1)
+_define__(<_SPARC__>,<1>)
+_define__(<_HOST__>,<SPARC>)
+_define__(<_MACH_DEP__>,<SPARC Dependent>)
+_divert__<>
\ No newline at end of file
--- /dev/null
+_divert__(-1)
+_define__(<_VAX__>,<1>)
+_define__(<_HOST__>,<VAX>)
+_define__(<_MACH_DEP__>,<VAX Dependent>)
+_divert__<>
\ No newline at end of file
--- /dev/null
+/* 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, ®val);
+ }
+ 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 *) ®isters[(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);
+ }
+ }
+}
--- /dev/null
+/* 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 */
+}
+
--- /dev/null
+#
+# 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];
+ }
--- /dev/null
+/* 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;
+ }
+ }
+}
--- /dev/null
+# 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",®isters[ 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
+
--- /dev/null
+#!/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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ bcopy (®isters[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 *) ®isters[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 *) ®isters[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
--- /dev/null
+/* 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, ®isters[REGISTER_BYTE (1)], 15 * 4);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+ *(int *)®isters[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,
+ ®isters[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 (®isters[REGISTER_BYTE (1)],
+ &inferior_registers.r_g1, 15 * 4);
+
+ inferior_registers.r_ps =
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc =
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ inferior_registers.r_npc =
+ *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
+ inferior_registers.r_y =
+ *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
+
+ remote_write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)],
+ ®isters[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;
+}
--- /dev/null
+/* 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 *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+ }
+ else
+ {
+ bzero (®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ bzero (®isters[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 *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ bcopy (®isters[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);
+}
--- /dev/null
+/* 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 *)®buf[REGISTER_BYTE(19)]);
+ xd.l[0] = *((int *)®buf[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 *)®buf[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));
+ }
+}
--- /dev/null
+/* 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 *)®isters[REGISTER_BYTE(0)];
+ regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
+ regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
+ regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
+ regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
+ regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
+ regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
+ regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
+ regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
+ regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
+ for (i = 0; i < 31; i++) {
+ regs.pr_fpa.fpa_regs[i] =
+ *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)];
+ }
+#if 0
+ }
+ else
+ {
+ reg_tmp = *(int *)®isters[REGISTER_BYTE(regno)];
+ ptrace(XPT_RREGS, inferior_pid, ®s, 0);
+ switch (regno)
+ {
+ case 0:
+ regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)];
+ break;
+ case 5:
+ regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
+ break;
+ case 2:
+ regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
+ break;
+ case 1:
+ regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
+ break;
+ case 6:
+ regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
+ break;
+ case 7:
+ regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
+ break;
+ case 15:
+ regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
+ break;
+ case 14:
+ regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
+ break;
+ case 16:
+ regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
+ break;
+ case 17:
+ regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
+ break;
+ }
+ }
+#endif /* 0 */
+ ptrace(XPT_WREGS, inferior_pid, ®s, 0);
+}
+
+void
+fetch_inferior_registers()
+{
+ int i;
+ struct pt_regset regs;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace(XPT_RREGS, inferior_pid, ®s, 0);
+ *(int *)®isters[REGISTER_BYTE(0)] = regs.pr_eax;
+ *(int *)®isters[REGISTER_BYTE(5)] = regs.pr_ebx;
+ *(int *)®isters[REGISTER_BYTE(2)] = regs.pr_ecx;
+ *(int *)®isters[REGISTER_BYTE(1)] = regs.pr_edx;
+ *(int *)®isters[REGISTER_BYTE(6)] = regs.pr_esi;
+ *(int *)®isters[REGISTER_BYTE(7)] = regs.pr_edi;
+ *(int *)®isters[REGISTER_BYTE(15)] = regs.pr_ebp;
+ *(int *)®isters[REGISTER_BYTE(14)] = regs.pr_esp;
+ *(int *)®isters[REGISTER_BYTE(16)] = regs.pr_eip;
+ *(int *)®isters[REGISTER_BYTE(17)] = regs.pr_flags;
+ for (i = 0; i < FPA_NREGS; i++) {
+ *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i];
+ }
+ bcopy(regs.pr_fpu.fpu_stack[0], ®isters[REGISTER_BYTE(3)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[1], ®isters[REGISTER_BYTE(4)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[2], ®isters[REGISTER_BYTE(8)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[3], ®isters[REGISTER_BYTE(9)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[4], ®isters[REGISTER_BYTE(10)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[5], ®isters[REGISTER_BYTE(11)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[6], ®isters[REGISTER_BYTE(12)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[7], ®isters[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, ®set, 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");
+}
--- /dev/null
+/* 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)
--- /dev/null
+/* 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) */
--- /dev/null
+/* 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 '.'