]>
Commit | Line | Data |
---|---|---|
dd3b648e RP |
1 | /* Print Convex instructions for GDB, the GNU debugger. |
2 | Copyright (C) 1989 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GDB. | |
5 | ||
99a7de40 | 6 | This program is free software; you can redistribute it and/or modify |
dd3b648e | 7 | it under the terms of the GNU General Public License as published by |
99a7de40 JG |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. | |
dd3b648e | 10 | |
99a7de40 | 11 | This program is distributed in the hope that it will be useful, |
dd3b648e RP |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
99a7de40 JG |
17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
dd3b648e RP |
19 | |
20 | #include <stdio.h> | |
21 | ||
22 | #include "defs.h" | |
23 | #include "param.h" | |
24 | #include "symtab.h" | |
25 | ||
26 | /* reg (fmt_field, inst_field) -- | |
27 | the {first,second,third} operand of instruction as fmt_field = [ijk] | |
28 | gets the value of the field from the [ijk] position of the instruction */ | |
29 | ||
30 | #define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b] | |
31 | ||
32 | /* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */ | |
33 | ||
34 | #define lit(i) op[fmt->i] | |
35 | ||
36 | /* aj[j] -- name for A register j */ | |
37 | ||
38 | #define aj ((char (*)[3])(op[A])) | |
39 | \f | |
40 | union inst { | |
41 | struct { | |
42 | unsigned : 7; | |
43 | unsigned i : 3; | |
44 | unsigned j : 3; | |
45 | unsigned k : 3; | |
46 | unsigned : 16; | |
47 | unsigned : 32; | |
48 | } f0; | |
49 | struct { | |
50 | unsigned : 8; | |
51 | unsigned indir : 1; | |
52 | unsigned len : 1; | |
53 | unsigned j : 3; | |
54 | unsigned k : 3; | |
55 | unsigned : 16; | |
56 | unsigned : 32; | |
57 | } f1; | |
58 | unsigned char byte[8]; | |
59 | unsigned short half[4]; | |
60 | char signed_byte[8]; | |
61 | short signed_half[4]; | |
62 | }; | |
63 | ||
64 | struct opform { | |
65 | int mask; /* opcode mask */ | |
66 | int shift; /* opcode align */ | |
67 | struct formstr *formstr[3]; /* ST, E0, E1 */ | |
68 | }; | |
69 | ||
70 | struct formstr { | |
71 | unsigned lop:8, rop:5; /* opcode */ | |
72 | unsigned fmt:5; /* inst format */ | |
73 | unsigned i:5, j:5, k:2; /* operand formats */ | |
74 | }; | |
75 | ||
3f2e006b | 76 | #include "convx-opcode.h" |
dd3b648e RP |
77 | |
78 | unsigned char formdecode [] = { | |
79 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, | |
80 | 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, | |
81 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, | |
82 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, | |
83 | 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, | |
84 | 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, | |
85 | 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, | |
86 | 4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8, | |
87 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
88 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
89 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
90 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
91 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
92 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
93 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
94 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
95 | }; | |
96 | ||
97 | struct opform opdecode[] = { | |
98 | 0x7e00, 9, format0, e0_format0, e1_format0, | |
99 | 0x3f00, 8, format1, e0_format1, e1_format1, | |
100 | 0x1fc0, 6, format2, e0_format2, e1_format2, | |
101 | 0x0fc0, 6, format3, e0_format3, e1_format3, | |
102 | 0x0700, 8, format4, e0_format4, e1_format4, | |
103 | 0x03c0, 6, format5, e0_format5, e1_format5, | |
104 | 0x01f8, 3, format6, e0_format6, e1_format6, | |
105 | 0x00f8, 3, format7, e0_format7, e1_format7, | |
106 | 0x0000, 0, formatx, formatx, formatx, | |
107 | 0x0f80, 7, formatx, formatx, formatx, | |
108 | 0x0f80, 7, formatx, formatx, formatx, | |
109 | }; | |
110 | \f | |
111 | /* Print the instruction at address MEMADDR in debugged memory, | |
112 | on STREAM. Returns length of the instruction, in bytes. */ | |
113 | ||
114 | int | |
115 | print_insn (memaddr, stream) | |
116 | CORE_ADDR memaddr; | |
117 | FILE *stream; | |
118 | { | |
119 | union inst inst; | |
120 | struct formstr *fmt; | |
121 | register int format, op1, pfx; | |
122 | int l; | |
123 | ||
124 | read_memory (memaddr, &inst, sizeof inst); | |
125 | ||
126 | /* Remove and note prefix, if present */ | |
127 | ||
128 | pfx = inst.half[0]; | |
129 | if ((pfx & 0xfff0) == 0x7ef0) | |
130 | { | |
131 | pfx = ((pfx >> 3) & 1) + 1; | |
132 | *(long long *) &inst = *(long long *) &inst.half[1]; | |
133 | } | |
134 | else pfx = 0; | |
135 | ||
136 | /* Split opcode into format.op1 and look up in appropriate table */ | |
137 | ||
138 | format = formdecode[inst.byte[0]]; | |
139 | op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift; | |
140 | if (format == 9) | |
141 | { | |
142 | if (pfx) | |
143 | fmt = formatx; | |
144 | else if (inst.f1.j == 0) | |
145 | fmt = &format1a[op1]; | |
146 | else if (inst.f1.j == 1) | |
147 | fmt = &format1b[op1]; | |
148 | else | |
149 | fmt = formatx; | |
150 | } | |
151 | else | |
152 | fmt = &opdecode[format].formstr[pfx][op1]; | |
153 | ||
154 | /* Print it */ | |
155 | ||
156 | if (fmt->fmt == xxx) | |
157 | { | |
158 | /* noninstruction */ | |
159 | fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]); | |
160 | return 2; | |
161 | } | |
162 | ||
163 | if (pfx) | |
164 | pfx = 2; | |
165 | ||
166 | fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop], | |
167 | &" "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]); | |
168 | ||
169 | switch (fmt->fmt) | |
170 | { | |
171 | case rrr: /* three register */ | |
172 | fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k)); | |
173 | return pfx + 2; | |
174 | ||
175 | case rr: /* two register */ | |
176 | fprintf (stream, "%s,%s", reg(i,j), reg(j,k)); | |
177 | return pfx + 2; | |
178 | ||
179 | case rxr: /* two register, reversed i and j fields */ | |
180 | fprintf (stream, "%s,%s", reg(i,k), reg(j,j)); | |
181 | return pfx + 2; | |
182 | ||
183 | case r: /* one register */ | |
184 | fprintf (stream, "%s", reg(i,k)); | |
185 | return pfx + 2; | |
186 | ||
187 | case nops: /* no operands */ | |
188 | return pfx + 2; | |
189 | ||
190 | case nr: /* short immediate, one register */ | |
191 | fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k)); | |
192 | return pfx + 2; | |
193 | ||
194 | case pcrel: /* pc relative */ | |
195 | print_address (memaddr + 2 * inst.signed_byte[1], stream); | |
196 | return pfx + 2; | |
197 | ||
198 | case lr: /* literal, one register */ | |
199 | fprintf (stream, "%s,%s", lit(i), reg(j,k)); | |
200 | return pfx + 2; | |
201 | ||
202 | case rxl: /* one register, literal */ | |
203 | fprintf (stream, "%s,%s", reg(i,k), lit(j)); | |
204 | return pfx + 2; | |
205 | ||
206 | case rlr: /* register, literal, register */ | |
207 | fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k)); | |
208 | return pfx + 2; | |
209 | ||
210 | case rrl: /* register, register, literal */ | |
211 | fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k)); | |
212 | return pfx + 2; | |
213 | ||
214 | case iml: /* immediate, literal */ | |
215 | if (inst.f1.len) | |
216 | { | |
217 | fprintf (stream, "#%#x,%s", | |
218 | (inst.signed_half[1] << 16) + inst.half[2], lit(i)); | |
219 | return pfx + 6; | |
220 | } | |
221 | else | |
222 | { | |
223 | fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i)); | |
224 | return pfx + 4; | |
225 | } | |
226 | ||
227 | case imr: /* immediate, register */ | |
228 | if (inst.f1.len) | |
229 | { | |
230 | fprintf (stream, "#%#x,%s", | |
231 | (inst.signed_half[1] << 16) + inst.half[2], reg(i,k)); | |
232 | return pfx + 6; | |
233 | } | |
234 | else | |
235 | { | |
236 | fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k)); | |
237 | return pfx + 4; | |
238 | } | |
239 | ||
240 | case a1r: /* memory, register */ | |
241 | l = print_effa (inst, stream); | |
242 | fprintf (stream, ",%s", reg(i,k)); | |
243 | return pfx + l; | |
244 | ||
245 | case a1l: /* memory, literal */ | |
246 | l = print_effa (inst, stream); | |
247 | fprintf (stream, ",%s", lit(i)); | |
248 | return pfx + l; | |
249 | ||
250 | case a2r: /* register, memory */ | |
251 | fprintf (stream, "%s,", reg(i,k)); | |
252 | return pfx + print_effa (inst, stream); | |
253 | ||
254 | case a2l: /* literal, memory */ | |
255 | fprintf (stream, "%s,", lit(i)); | |
256 | return pfx + print_effa (inst, stream); | |
257 | ||
258 | case a3: /* memory */ | |
259 | return pfx + print_effa (inst, stream); | |
260 | ||
261 | case a4: /* system call */ | |
262 | l = 29; goto a4a5; | |
263 | case a5: /* trap */ | |
264 | l = 27; | |
265 | a4a5: | |
266 | if (inst.f1.len) | |
267 | { | |
268 | unsigned int m = (inst.signed_half[1] << 16) + inst.half[2]; | |
269 | fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l))); | |
270 | return pfx + 6; | |
271 | } | |
272 | else | |
273 | { | |
274 | unsigned int m = inst.signed_half[1]; | |
275 | fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l))); | |
276 | return pfx + 4; | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | ||
282 | /* print effective address @nnn(aj), return instruction length */ | |
283 | ||
284 | int print_effa (inst, stream) | |
285 | union inst inst; | |
286 | FILE *stream; | |
287 | { | |
288 | int n, l; | |
289 | ||
290 | if (inst.f1.len) | |
291 | { | |
292 | n = (inst.signed_half[1] << 16) + inst.half[2]; | |
293 | l = 6; | |
294 | } | |
295 | else | |
296 | { | |
297 | n = inst.signed_half[1]; | |
298 | l = 4; | |
299 | } | |
300 | ||
301 | if (inst.f1.indir) | |
302 | printf ("@"); | |
303 | ||
304 | if (!inst.f1.j) | |
305 | { | |
306 | print_address (n, stream); | |
307 | return l; | |
308 | } | |
309 | ||
310 | fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)", | |
311 | n, aj[inst.f1.j]); | |
312 | ||
313 | return l; | |
314 | } |