pdp11-dis.c revision 1.1.1.1.12.1 1 1.1 skrll /* Print DEC PDP-11 instructions.
2 1.1 skrll Copyright 2001, 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
3 1.1 skrll
4 1.1 skrll This file is part of the GNU opcodes library.
5 1.1 skrll
6 1.1 skrll This library is free software; you can redistribute it and/or modify
7 1.1 skrll it under the terms of the GNU General Public License as published by
8 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
9 1.1 skrll any later version.
10 1.1 skrll
11 1.1 skrll It is distributed in the hope that it will be useful, but WITHOUT
12 1.1 skrll ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.1 skrll or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.1 skrll License for more details.
15 1.1 skrll
16 1.1 skrll You should have received a copy of the GNU General Public License
17 1.1 skrll along with this program; if not, write to the Free Software
18 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 skrll MA 02110-1301, USA. */
20 1.1 skrll
21 1.1 skrll #include "sysdep.h"
22 1.1 skrll #include "dis-asm.h"
23 1.1 skrll #include "opcode/pdp11.h"
24 1.1 skrll
25 1.1 skrll #define AFTER_INSTRUCTION "\t"
26 1.1 skrll #define OPERAND_SEPARATOR ", "
27 1.1 skrll
28 1.1 skrll #define JUMP 0x1000 /* Flag that this operand is used in a jump. */
29 1.1 skrll
30 1.1 skrll #define FPRINTF (*info->fprintf_func)
31 1.1 skrll #define F info->stream
32 1.1 skrll
33 1.1 skrll /* Sign-extend a 16-bit number in an int. */
34 1.1 skrll #define SIGN_BITS (8 * sizeof (int) - 16)
35 1.1 skrll #define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
36 1.1 skrll
37 1.1 skrll static int
38 1.1 skrll read_word (bfd_vma memaddr, int *word, disassemble_info *info)
39 1.1 skrll {
40 1.1 skrll int status;
41 1.1 skrll bfd_byte x[2];
42 1.1 skrll
43 1.1 skrll status = (*info->read_memory_func) (memaddr, x, 2, info);
44 1.1 skrll if (status != 0)
45 1.1 skrll return -1;
46 1.1 skrll
47 1.1 skrll *word = x[1] << 8 | x[0];
48 1.1 skrll return 0;
49 1.1 skrll }
50 1.1 skrll
51 1.1 skrll static void
52 1.1 skrll print_signed_octal (int n, disassemble_info *info)
53 1.1 skrll {
54 1.1 skrll if (n < 0)
55 1.1 skrll FPRINTF (F, "-%o", -n);
56 1.1 skrll else
57 1.1 skrll FPRINTF (F, "%o", n);
58 1.1 skrll }
59 1.1 skrll
60 1.1 skrll static void
61 1.1 skrll print_reg (int reg, disassemble_info *info)
62 1.1 skrll {
63 1.1 skrll /* Mask off the addressing mode, if any. */
64 1.1 skrll reg &= 7;
65 1.1 skrll
66 1.1 skrll switch (reg)
67 1.1 skrll {
68 1.1 skrll case 0: case 1: case 2: case 3: case 4: case 5:
69 1.1 skrll FPRINTF (F, "r%d", reg); break;
70 1.1 skrll case 6: FPRINTF (F, "sp"); break;
71 1.1 skrll case 7: FPRINTF (F, "pc"); break;
72 1.1 skrll default: ; /* error */
73 1.1 skrll }
74 1.1 skrll }
75 1.1 skrll
76 1.1 skrll static void
77 1.1 skrll print_freg (int freg, disassemble_info *info)
78 1.1 skrll {
79 1.1 skrll FPRINTF (F, "fr%d", freg);
80 1.1 skrll }
81 1.1 skrll
82 1.1 skrll static int
83 1.1 skrll print_operand (bfd_vma *memaddr, int code, disassemble_info *info)
84 1.1 skrll {
85 1.1 skrll int mode = (code >> 3) & 7;
86 1.1 skrll int reg = code & 7;
87 1.1 skrll int disp;
88 1.1 skrll
89 1.1 skrll switch (mode)
90 1.1 skrll {
91 1.1 skrll case 0:
92 1.1 skrll print_reg (reg, info);
93 1.1 skrll break;
94 1.1 skrll case 1:
95 1.1 skrll FPRINTF (F, "(");
96 1.1 skrll print_reg (reg, info);
97 1.1 skrll FPRINTF (F, ")");
98 1.1 skrll break;
99 1.1 skrll case 2:
100 1.1 skrll if (reg == 7)
101 1.1 skrll {
102 1.1 skrll int data;
103 1.1 skrll
104 1.1 skrll if (read_word (*memaddr, &data, info) < 0)
105 1.1 skrll return -1;
106 1.1 skrll FPRINTF (F, "$");
107 1.1 skrll print_signed_octal (sign_extend (data), info);
108 1.1 skrll *memaddr += 2;
109 1.1 skrll }
110 1.1 skrll else
111 1.1 skrll {
112 1.1 skrll FPRINTF (F, "(");
113 1.1 skrll print_reg (reg, info);
114 1.1 skrll FPRINTF (F, ")+");
115 1.1 skrll }
116 1.1 skrll break;
117 1.1 skrll case 3:
118 1.1 skrll if (reg == 7)
119 1.1 skrll {
120 1.1 skrll int address;
121 1.1 skrll
122 1.1 skrll if (read_word (*memaddr, &address, info) < 0)
123 1.1 skrll return -1;
124 1.1 skrll FPRINTF (F, "*$%o", address);
125 1.1 skrll *memaddr += 2;
126 1.1 skrll }
127 1.1 skrll else
128 1.1 skrll {
129 1.1 skrll FPRINTF (F, "*(");
130 1.1 skrll print_reg (reg, info);
131 1.1 skrll FPRINTF (F, ")+");
132 1.1 skrll }
133 1.1 skrll break;
134 1.1 skrll case 4:
135 1.1 skrll FPRINTF (F, "-(");
136 1.1 skrll print_reg (reg, info);
137 1.1 skrll FPRINTF (F, ")");
138 1.1 skrll break;
139 1.1 skrll case 5:
140 1.1 skrll FPRINTF (F, "*-(");
141 1.1 skrll print_reg (reg, info);
142 1.1 skrll FPRINTF (F, ")");
143 1.1 skrll break;
144 1.1 skrll case 6:
145 1.1 skrll case 7:
146 1.1 skrll if (read_word (*memaddr, &disp, info) < 0)
147 1.1 skrll return -1;
148 1.1 skrll *memaddr += 2;
149 1.1 skrll if (reg == 7)
150 1.1 skrll {
151 1.1 skrll bfd_vma address = *memaddr + sign_extend (disp);
152 1.1 skrll
153 1.1 skrll if (mode == 7)
154 1.1 skrll FPRINTF (F, "*");
155 1.1 skrll if (!(code & JUMP))
156 1.1 skrll FPRINTF (F, "$");
157 1.1 skrll (*info->print_address_func) (address, info);
158 1.1 skrll }
159 1.1 skrll else
160 1.1 skrll {
161 1.1 skrll if (mode == 7)
162 1.1 skrll FPRINTF (F, "*");
163 1.1 skrll print_signed_octal (sign_extend (disp), info);
164 1.1 skrll FPRINTF (F, "(");
165 1.1 skrll print_reg (reg, info);
166 1.1 skrll FPRINTF (F, ")");
167 1.1 skrll }
168 1.1 skrll break;
169 1.1 skrll }
170 1.1 skrll
171 1.1 skrll return 0;
172 1.1 skrll }
173 1.1 skrll
174 1.1 skrll static int
175 1.1 skrll print_foperand (bfd_vma *memaddr, int code, disassemble_info *info)
176 1.1 skrll {
177 1.1 skrll int mode = (code >> 3) & 7;
178 1.1 skrll int reg = code & 7;
179 1.1 skrll
180 1.1 skrll if (mode == 0)
181 1.1 skrll print_freg (reg, info);
182 1.1 skrll else
183 1.1 skrll return print_operand (memaddr, code, info);
184 1.1 skrll
185 1.1 skrll return 0;
186 1.1 skrll }
187 1.1 skrll
188 1.1 skrll /* Print the PDP-11 instruction at address MEMADDR in debugged memory,
189 1.1 skrll on INFO->STREAM. Returns length of the instruction, in bytes. */
190 1.1 skrll
191 1.1 skrll int
192 1.1 skrll print_insn_pdp11 (bfd_vma memaddr, disassemble_info *info)
193 1.1 skrll {
194 1.1 skrll bfd_vma start_memaddr = memaddr;
195 1.1 skrll int opcode;
196 1.1 skrll int src, dst;
197 1.1 skrll int i;
198 1.1 skrll
199 1.1 skrll info->bytes_per_line = 6;
200 1.1 skrll info->bytes_per_chunk = 2;
201 1.1 skrll info->display_endian = BFD_ENDIAN_LITTLE;
202 1.1 skrll
203 1.1 skrll if (read_word (memaddr, &opcode, info) != 0)
204 1.1 skrll return -1;
205 1.1 skrll memaddr += 2;
206 1.1 skrll
207 1.1 skrll src = (opcode >> 6) & 0x3f;
208 1.1 skrll dst = opcode & 0x3f;
209 1.1 skrll
210 1.1 skrll for (i = 0; i < pdp11_num_opcodes; i++)
211 1.1 skrll {
212 1.1 skrll #define OP pdp11_opcodes[i]
213 1.1 skrll if ((opcode & OP.mask) == OP.opcode)
214 1.1 skrll switch (OP.type)
215 1.1 skrll {
216 1.1 skrll case PDP11_OPCODE_NO_OPS:
217 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
218 1.1 skrll goto done;
219 1.1 skrll case PDP11_OPCODE_REG:
220 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
221 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
222 1.1 skrll print_reg (dst, info);
223 1.1 skrll goto done;
224 1.1 skrll case PDP11_OPCODE_OP:
225 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
226 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
227 1.1 skrll if (strcmp (OP.name, "jmp") == 0)
228 1.1 skrll dst |= JUMP;
229 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
230 1.1 skrll return -1;
231 1.1 skrll goto done;
232 1.1 skrll case PDP11_OPCODE_FOP:
233 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
234 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
235 1.1 skrll if (strcmp (OP.name, "jmp") == 0)
236 1.1 skrll dst |= JUMP;
237 1.1 skrll if (print_foperand (&memaddr, dst, info) < 0)
238 1.1 skrll return -1;
239 1.1 skrll goto done;
240 1.1 skrll case PDP11_OPCODE_REG_OP:
241 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
242 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
243 1.1 skrll print_reg (src, info);
244 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
245 1.1 skrll if (strcmp (OP.name, "jsr") == 0)
246 1.1 skrll dst |= JUMP;
247 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
248 1.1 skrll return -1;
249 1.1 skrll goto done;
250 1.1 skrll case PDP11_OPCODE_REG_OP_REV:
251 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
252 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
253 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
254 1.1 skrll return -1;
255 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
256 1.1 skrll print_reg (src, info);
257 1.1 skrll goto done;
258 1.1 skrll case PDP11_OPCODE_AC_FOP:
259 1.1 skrll {
260 1.1 skrll int ac = (opcode & 0xe0) >> 6;
261 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
262 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
263 1.1 skrll print_freg (ac, info);
264 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
265 1.1 skrll if (print_foperand (&memaddr, dst, info) < 0)
266 1.1 skrll return -1;
267 1.1 skrll goto done;
268 1.1 skrll }
269 1.1 skrll case PDP11_OPCODE_FOP_AC:
270 1.1 skrll {
271 1.1 skrll int ac = (opcode & 0xe0) >> 6;
272 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
273 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
274 1.1 skrll if (print_foperand (&memaddr, dst, info) < 0)
275 1.1 skrll return -1;
276 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
277 1.1 skrll print_freg (ac, info);
278 1.1 skrll goto done;
279 1.1 skrll }
280 1.1 skrll case PDP11_OPCODE_AC_OP:
281 1.1 skrll {
282 1.1 skrll int ac = (opcode & 0xe0) >> 6;
283 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
284 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
285 1.1 skrll print_freg (ac, info);
286 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
287 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
288 1.1 skrll return -1;
289 1.1 skrll goto done;
290 1.1 skrll }
291 1.1 skrll case PDP11_OPCODE_OP_AC:
292 1.1 skrll {
293 1.1 skrll int ac = (opcode & 0xe0) >> 6;
294 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
295 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
296 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
297 1.1 skrll return -1;
298 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
299 1.1 skrll print_freg (ac, info);
300 1.1 skrll goto done;
301 1.1 skrll }
302 1.1 skrll case PDP11_OPCODE_OP_OP:
303 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
304 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
305 1.1 skrll if (print_operand (&memaddr, src, info) < 0)
306 1.1 skrll return -1;
307 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
308 1.1 skrll if (print_operand (&memaddr, dst, info) < 0)
309 1.1 skrll return -1;
310 1.1 skrll goto done;
311 1.1 skrll case PDP11_OPCODE_DISPL:
312 1.1 skrll {
313 1.1 skrll int displ = (opcode & 0xff) << 8;
314 1.1 skrll bfd_vma address = memaddr + (sign_extend (displ) >> 7);
315 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
316 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
317 1.1 skrll (*info->print_address_func) (address, info);
318 1.1 skrll goto done;
319 1.1 skrll }
320 1.1 skrll case PDP11_OPCODE_REG_DISPL:
321 1.1 skrll {
322 1.1 skrll int displ = (opcode & 0x3f) << 10;
323 1.1 skrll bfd_vma address = memaddr - (displ >> 9);
324 1.1 skrll
325 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
326 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
327 1.1 skrll print_reg (src, info);
328 1.1 skrll FPRINTF (F, OPERAND_SEPARATOR);
329 1.1 skrll (*info->print_address_func) (address, info);
330 1.1 skrll goto done;
331 1.1 skrll }
332 1.1 skrll case PDP11_OPCODE_IMM8:
333 1.1 skrll {
334 1.1 skrll int code = opcode & 0xff;
335 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
336 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
337 1.1 skrll FPRINTF (F, "%o", code);
338 1.1 skrll goto done;
339 1.1 skrll }
340 1.1 skrll case PDP11_OPCODE_IMM6:
341 1.1 skrll {
342 1.1 skrll int code = opcode & 0x3f;
343 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
344 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
345 1.1 skrll FPRINTF (F, "%o", code);
346 1.1 skrll goto done;
347 1.1 skrll }
348 1.1 skrll case PDP11_OPCODE_IMM3:
349 1.1 skrll {
350 1.1 skrll int code = opcode & 7;
351 1.1.1.1.12.1 tls FPRINTF (F, "%s", OP.name);
352 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
353 1.1 skrll FPRINTF (F, "%o", code);
354 1.1 skrll goto done;
355 1.1 skrll }
356 1.1 skrll case PDP11_OPCODE_ILLEGAL:
357 1.1 skrll {
358 1.1 skrll FPRINTF (F, ".word");
359 1.1 skrll FPRINTF (F, AFTER_INSTRUCTION);
360 1.1 skrll FPRINTF (F, "%o", opcode);
361 1.1 skrll goto done;
362 1.1 skrll }
363 1.1 skrll default:
364 1.1 skrll /* TODO: is this a proper way of signalling an error? */
365 1.1 skrll FPRINTF (F, "<internal error: unrecognized instruction type>");
366 1.1 skrll return -1;
367 1.1 skrll }
368 1.1 skrll #undef OP
369 1.1 skrll }
370 1.1 skrll done:
371 1.1 skrll
372 1.1 skrll return memaddr - start_memaddr;
373 1.1 skrll }
374