import gdb-1999-05-25 snapshot
[deliverable/binutils-gdb.git] / gdb / tahoe-tdep.c
1 /* Print instructions for Tahoe target machines, for GDB.
2 Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
3 Contributed by the State University of New York at Buffalo, by the
4 Distributed Computer Systems Lab, Department of Computer Science, 1991.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "opcode/tahoe.h"
25
26 /* Tahoe instructions are never longer than this. */
27 #define MAXLEN 62
28
29 /* Number of elements in the opcode table. */
30 #define NOPCODES (sizeof votstrs / sizeof votstrs[0])
31
32 static unsigned char *print_insn_arg ();
33
34 /* Advance PC across any function entry prologue instructions
35 to reach some "real" code. */
36
37 CORE_ADDR
38 tahoe_skip_prologue (pc)
39 CORE_ADDR pc;
40 {
41 register int op = (unsigned char) read_memory_integer (pc, 1);
42 if (op == 0x11)
43 pc += 2; /* skip brb */
44 if (op == 0x13)
45 pc += 3; /* skip brw */
46 if (op == 0x2c
47 && ((unsigned char) read_memory_integer (pc+2, 1)) == 0x5e)
48 pc += 3; /* skip subl2 */
49 if (op == 0xe9
50 && ((unsigned char) read_memory_integer (pc+1, 1)) == 0xae
51 && ((unsigned char) read_memory_integer(pc+3, 1)) == 0x5e)
52 pc += 4; /* skip movab */
53 if (op == 0xe9
54 && ((unsigned char) read_memory_integer (pc+1, 1)) == 0xce
55 && ((unsigned char) read_memory_integer(pc+4, 1)) == 0x5e)
56 pc += 5; /* skip movab */
57 if (op == 0xe9
58 && ((unsigned char) read_memory_integer (pc+1, 1)) == 0xee
59 && ((unsigned char) read_memory_integer(pc+6, 1)) == 0x5e)
60 pc += 7; /* skip movab */
61 return pc;
62 }
63
64 /* Return number of args passed to a frame.
65 Can return -1, meaning no way to tell. */
66
67 int
68 tahoe_frame_num_args (fi)
69 struct frame_info *fi;
70 {
71 return (((0xffff & read_memory_integer(((fi)->frame-4),4)) - 4) >> 2);
72 }
73
74 /* Print the Tahoe instruction at address MEMADDR in debugged memory,
75 on STREAM. Returns length of the instruction, in bytes. */
76
77 int
78 tahoe_print_insn (memaddr, stream)
79 CORE_ADDR memaddr;
80 GDB_FILE *stream;
81 {
82 unsigned char buffer[MAXLEN];
83 register int i;
84 register unsigned char *p;
85 register char *d;
86
87 read_memory (memaddr, buffer, MAXLEN);
88
89 for (i = 0; i < NOPCODES; i++)
90 if (votstrs[i].detail.code == buffer[0]
91 || votstrs[i].detail.code == *(unsigned short *)buffer)
92 break;
93
94 /* Handle undefined instructions. */
95 if (i == NOPCODES)
96 {
97 fprintf_unfiltered (stream, "0%o", buffer[0]);
98 return 1;
99 }
100
101 fprintf_unfiltered (stream, "%s", votstrs[i].name);
102
103 /* Point at first byte of argument data,
104 and at descriptor for first argument. */
105 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
106 d = votstrs[i].detail.args;
107
108 if (*d)
109 fputc_unfiltered ('\t', stream);
110
111 while (*d)
112 {
113 p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
114 d += 2;
115 if (*d)
116 fprintf_unfiltered (stream, ",");
117 }
118 return p - buffer;
119 }
120 /*******************************************************************/
121 static unsigned char *
122 print_insn_arg (d, p, addr, stream)
123 char *d;
124 register char *p;
125 CORE_ADDR addr;
126 GDB_FILE *stream;
127 {
128 int temp1 = 0;
129 register int regnum = *p & 0xf;
130 float floatlitbuf;
131
132 if (*d == 'b')
133 {
134 if (d[1] == 'b')
135 fprintf_unfiltered (stream, "0x%x", addr + *p++ + 1);
136 else
137 {
138
139 temp1 = *p;
140 temp1 <<= 8;
141 temp1 |= *(p + 1);
142 fprintf_unfiltered (stream, "0x%x", addr + temp1 + 2);
143 p += 2;
144 }
145 }
146 else
147 switch ((*p++ >> 4) & 0xf)
148 {
149 case 0:
150 case 1:
151 case 2:
152 case 3: /* Literal (short immediate byte) mode */
153 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
154 {
155 *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
156 fprintf_unfiltered (stream, "$%f", floatlitbuf);
157 }
158 else
159 fprintf_unfiltered (stream, "$%d", p[-1] & 0x3f);
160 break;
161
162 case 4: /* Indexed */
163 p = (char *) print_insn_arg (d, p, addr + 1, stream);
164 fprintf_unfiltered (stream, "[%s]", REGISTER_NAME (regnum));
165 break;
166
167 case 5: /* Register */
168 fprintf_unfiltered (stream, REGISTER_NAME (regnum));
169 break;
170
171 case 7: /* Autodecrement */
172 fputc_unfiltered ('-', stream);
173 case 6: /* Register deferred */
174 fprintf_unfiltered (stream, "(%s)", REGISTER_NAME (regnum));
175 break;
176
177 case 9: /* Absolute Address & Autoincrement deferred */
178 fputc_unfiltered ('*', stream);
179 if (regnum == PC_REGNUM)
180 {
181 temp1 = *p;
182 temp1 <<= 8;
183 temp1 |= *(p +1);
184
185 fputc_unfiltered ('$', stream);
186 print_address (temp1, stream);
187 p += 4;
188 break;
189 }
190 case 8: /*Immediate & Autoincrement SP */
191 if (regnum == 8) /*88 is Immediate Byte Mode*/
192 fprintf_unfiltered (stream, "$%d", *p++);
193
194 else if (regnum == 9) /*89 is Immediate Word Mode*/
195 {
196 temp1 = *p;
197 temp1 <<= 8;
198 temp1 |= *(p +1);
199 fprintf_unfiltered (stream, "$%d", temp1);
200 p += 2;
201 }
202
203 else if (regnum == PC_REGNUM) /*8F is Immediate Long Mode*/
204 {
205 temp1 = *p;
206 temp1 <<=8;
207 temp1 |= *(p +1);
208 temp1 <<=8;
209 temp1 |= *(p +2);
210 temp1 <<= 8;
211 temp1 |= *(p +3);
212 fprintf_unfiltered (stream, "$%d", temp1);
213 p += 4;
214 }
215
216 else /*8E is Autoincrement SP Mode*/
217 fprintf_unfiltered (stream, "(%s)+", REGISTER_NAME (regnum));
218 break;
219
220 case 11: /* Register + Byte Displacement Deferred Mode*/
221 fputc_unfiltered ('*', stream);
222 case 10: /* Register + Byte Displacement Mode*/
223 if (regnum == PC_REGNUM)
224 print_address (addr + *p + 2, stream);
225 else
226 fprintf_unfiltered (stream, "%d(%s)", *p, REGISTER_NAME (regnum));
227 p += 1;
228 break;
229
230 case 13: /* Register + Word Displacement Deferred Mode*/
231 fputc_unfiltered ('*', stream);
232 case 12: /* Register + Word Displacement Mode*/
233 temp1 = *p;
234 temp1 <<= 8;
235 temp1 |= *(p +1);
236 if (regnum == PC_REGNUM)
237 print_address (addr + temp1 + 3, stream);
238 else
239 fprintf_unfiltered (stream, "%d(%s)", temp1, REGISTER_NAME (regnum));
240 p += 2;
241 break;
242
243 case 15: /* Register + Long Displacement Deferred Mode*/
244 fputc_unfiltered ('*', stream);
245 case 14: /* Register + Long Displacement Mode*/
246 temp1 = *p;
247 temp1 <<= 8;
248 temp1 |= *(p +1);
249 temp1 <<= 8;
250 temp1 |= *(p +2);
251 temp1 <<= 8;
252 temp1 |= *(p +3);
253 if (regnum == PC_REGNUM)
254 print_address (addr + temp1 + 5, stream);
255 else
256 fprintf_unfiltered (stream, "%d(%s)", temp1, REGISTER_NAME (regnum));
257 p += 4;
258 }
259
260 return (unsigned char *) p;
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
This page took 0.035206 seconds and 4 git commands to generate.