1 /* Print DEC PDP-11 instructions.
2 Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
4 This file is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20 #include "opcode/pdp11.h"
22 #define AFTER_INSTRUCTION "\t"
23 #define OPERAND_SEPARATOR ", "
25 #define JUMP 0x1000 /* flag that this operand is used in a jump */
27 #define FPRINTF (*info->fprintf_func)
28 #define F info->stream
30 /* sign-extend a 16-bit number in an int */
31 #define SIGN_BITS (8 * sizeof (int) - 16)
32 #define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
34 static int read_word
PARAMS ((bfd_vma memaddr
, int *word
,
35 disassemble_info
*info
));
36 static void print_signed_octal
PARAMS ((int n
, disassemble_info
*info
));
37 static void print_reg
PARAMS ((int reg
, disassemble_info
*info
));
38 static void print_freg
PARAMS ((int freg
, disassemble_info
*info
));
39 static int print_operand
PARAMS ((bfd_vma
*memaddr
, int code
,
40 disassemble_info
*info
));
41 static int print_foperand
PARAMS ((bfd_vma
*memaddr
, int code
,
42 disassemble_info
*info
));
43 int print_insn_pdp11
PARAMS ((bfd_vma memaddr
, disassemble_info
*info
));
46 read_word (memaddr
, word
, info
)
49 disassemble_info
*info
;
54 status
= (*info
->read_memory_func
) (memaddr
, x
, 2, info
);
58 *word
= x
[1] << 8 | x
[0];
63 print_signed_octal (n
, info
)
65 disassemble_info
*info
;
68 FPRINTF (F
, "-%o", -n
);
76 disassemble_info
*info
;
78 /* mask off the addressing mode, if any */
83 case 0: case 1: case 2: case 3: case 4: case 5:
84 FPRINTF (F
, "r%d", reg
); break;
85 case 6: FPRINTF (F
, "sp"); break;
86 case 7: FPRINTF (F
, "pc"); break;
87 default: ; /* error */
92 print_freg (freg
, info
)
94 disassemble_info
*info
;
96 FPRINTF (F
, "fr%d", freg
);
100 print_operand (memaddr
, code
, info
)
103 disassemble_info
*info
;
105 int mode
= (code
>> 3) & 7;
112 print_reg (reg
, info
);
116 print_reg (reg
, info
);
123 if (read_word (*memaddr
, &data
, info
) < 0)
126 print_signed_octal (sign_extend (data
), info
);
132 print_reg (reg
, info
);
140 if (read_word (*memaddr
, &address
, info
) < 0)
142 FPRINTF (F
, "*$%o", address
);
148 print_reg (reg
, info
);
154 print_reg (reg
, info
);
159 print_reg (reg
, info
);
164 if (read_word (*memaddr
, &disp
, info
) < 0)
169 bfd_vma address
= *memaddr
+ sign_extend (disp
);
174 (*info
->print_address_func
) (address
, info
);
180 print_signed_octal (sign_extend (disp
), info
);
182 print_reg (reg
, info
);
192 print_foperand (memaddr
, code
, info
)
195 disassemble_info
*info
;
197 int mode
= (code
>> 3) & 7;
201 print_freg (reg
, info
);
203 return print_operand (memaddr
, code
, info
);
208 /* Print the PDP-11 instruction at address MEMADDR in debugged memory,
209 on INFO->STREAM. Returns length of the instruction, in bytes. */
212 print_insn_pdp11 (memaddr
, info
)
214 disassemble_info
*info
;
216 bfd_vma start_memaddr
= memaddr
;
221 info
->bytes_per_line
= 6;
222 info
->bytes_per_chunk
= 2;
223 info
->display_endian
= BFD_ENDIAN_LITTLE
;
225 if (read_word (memaddr
, &opcode
, info
) != 0)
229 src
= (opcode
>> 6) & 0x3f;
232 for (i
= 0; i
< pdp11_num_opcodes
; i
++)
234 #define OP pdp11_opcodes[i]
235 if ((opcode
& OP
.mask
) == OP
.opcode
)
238 case PDP11_OPCODE_NO_OPS
:
239 FPRINTF (F
, OP
.name
);
241 case PDP11_OPCODE_REG
:
242 FPRINTF (F
, OP
.name
);
243 FPRINTF (F
, AFTER_INSTRUCTION
);
244 print_reg (dst
, info
);
246 case PDP11_OPCODE_OP
:
247 FPRINTF (F
, OP
.name
);
248 FPRINTF (F
, AFTER_INSTRUCTION
);
249 if (strcmp (OP
.name
, "jmp") == 0)
251 if (print_operand (&memaddr
, dst
, info
) < 0)
254 case PDP11_OPCODE_FOP
:
255 FPRINTF (F
, OP
.name
);
256 FPRINTF (F
, AFTER_INSTRUCTION
);
257 if (strcmp (OP
.name
, "jmp") == 0)
259 if (print_foperand (&memaddr
, dst
, info
) < 0)
262 case PDP11_OPCODE_REG_OP
:
263 FPRINTF (F
, OP
.name
);
264 FPRINTF (F
, AFTER_INSTRUCTION
);
265 print_reg (src
, info
);
266 FPRINTF (F
, OPERAND_SEPARATOR
);
267 if (strcmp (OP
.name
, "jsr") == 0)
269 if (print_operand (&memaddr
, dst
, info
) < 0)
272 case PDP11_OPCODE_REG_OP_REV
:
273 FPRINTF (F
, OP
.name
);
274 FPRINTF (F
, AFTER_INSTRUCTION
);
275 if (print_operand (&memaddr
, dst
, info
) < 0)
277 FPRINTF (F
, OPERAND_SEPARATOR
);
278 print_reg (src
, info
);
280 case PDP11_OPCODE_AC_FOP
:
282 int ac
= (opcode
& 0xe0) >> 6;
283 FPRINTF (F
, OP
.name
);
284 FPRINTF (F
, AFTER_INSTRUCTION
);
285 print_freg (ac
, info
);
286 FPRINTF (F
, OPERAND_SEPARATOR
);
287 if (print_foperand (&memaddr
, dst
, info
) < 0)
291 case PDP11_OPCODE_FOP_AC
:
293 int ac
= (opcode
& 0xe0) >> 6;
294 FPRINTF (F
, OP
.name
);
295 FPRINTF (F
, AFTER_INSTRUCTION
);
296 if (print_foperand (&memaddr
, dst
, info
) < 0)
298 FPRINTF (F
, OPERAND_SEPARATOR
);
299 print_freg (ac
, info
);
302 case PDP11_OPCODE_AC_OP
:
304 int ac
= (opcode
& 0xe0) >> 6;
305 FPRINTF (F
, OP
.name
);
306 FPRINTF (F
, AFTER_INSTRUCTION
);
307 print_freg (ac
, info
);
308 FPRINTF (F
, OPERAND_SEPARATOR
);
309 if (print_operand (&memaddr
, dst
, info
) < 0)
313 case PDP11_OPCODE_OP_AC
:
315 int ac
= (opcode
& 0xe0) >> 6;
316 FPRINTF (F
, OP
.name
);
317 FPRINTF (F
, AFTER_INSTRUCTION
);
318 if (print_operand (&memaddr
, dst
, info
) < 0)
320 FPRINTF (F
, OPERAND_SEPARATOR
);
321 print_freg (ac
, info
);
324 case PDP11_OPCODE_OP_OP
:
325 FPRINTF (F
, OP
.name
);
326 FPRINTF (F
, AFTER_INSTRUCTION
);
327 if (print_operand (&memaddr
, src
, info
) < 0)
329 FPRINTF (F
, OPERAND_SEPARATOR
);
330 if (print_operand (&memaddr
, dst
, info
) < 0)
333 case PDP11_OPCODE_DISPL
:
335 int displ
= (opcode
& 0xff) << 8;
336 bfd_vma address
= memaddr
+ (sign_extend (displ
) >> 7);
337 FPRINTF (F
, OP
.name
);
338 FPRINTF (F
, AFTER_INSTRUCTION
);
339 (*info
->print_address_func
) (address
, info
);
342 case PDP11_OPCODE_REG_DISPL
:
344 int displ
= (opcode
& 0x3f) << 10;
345 bfd_vma address
= memaddr
- (displ
>> 9);
347 FPRINTF (F
, OP
.name
);
348 FPRINTF (F
, AFTER_INSTRUCTION
);
349 print_reg (src
, info
);
350 FPRINTF (F
, OPERAND_SEPARATOR
);
351 (*info
->print_address_func
) (address
, info
);
354 case PDP11_OPCODE_IMM8
:
356 int code
= opcode
& 0xff;
357 FPRINTF (F
, OP
.name
);
358 FPRINTF (F
, AFTER_INSTRUCTION
);
359 FPRINTF (F
, "%o", code
);
362 case PDP11_OPCODE_IMM6
:
364 int code
= opcode
& 0x3f;
365 FPRINTF (F
, OP
.name
);
366 FPRINTF (F
, AFTER_INSTRUCTION
);
367 FPRINTF (F
, "%o", code
);
370 case PDP11_OPCODE_IMM3
:
372 int code
= opcode
& 7;
373 FPRINTF (F
, OP
.name
);
374 FPRINTF (F
, AFTER_INSTRUCTION
);
375 FPRINTF (F
, "%o", code
);
378 case PDP11_OPCODE_ILLEGAL
:
380 FPRINTF (F
, ".word");
381 FPRINTF (F
, AFTER_INSTRUCTION
);
382 FPRINTF (F
, "%o", opcode
);
386 /* TODO: is this a proper way of signalling an error? */
387 FPRINTF (F
, "<internal error: unrecognized instruction type>");
394 return memaddr
- start_memaddr
;