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