1 /* Print DEC PDP-11 instructions.
2 Copyright 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #include "opcode/pdp11.h"
21 #define AFTER_INSTRUCTION "\t"
22 #define OPERAND_SEPARATOR ", "
24 #define JUMP 0x1000 /* flag that this operand is used in a jump */
26 #define FPRINTF (*info->fprintf_func)
27 #define F info->stream
29 /* sign-extend a 16-bit number in an int */
30 #define SIGN_BITS (8 * sizeof (int) - 16)
31 #define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
33 static int read_word
PARAMS ((bfd_vma memaddr
, int *word
,
34 disassemble_info
*info
));
35 static void print_signed_octal
PARAMS ((int n
, disassemble_info
*info
));
36 static void print_reg
PARAMS ((int reg
, disassemble_info
*info
));
37 static void print_freg
PARAMS ((int freg
, disassemble_info
*info
));
38 static int print_operand
PARAMS ((bfd_vma
*memaddr
, int code
,
39 disassemble_info
*info
));
40 int print_insn_pdp11
PARAMS ((bfd_vma memaddr
, disassemble_info
*info
));
43 read_word (memaddr
, word
, info
)
46 disassemble_info
*info
;
51 status
= (*info
->read_memory_func
) (memaddr
, x
, 2, info
);
55 *word
= x
[1] << 8 | x
[0];
60 print_signed_octal (n
, info
)
62 disassemble_info
*info
;
65 FPRINTF (F
, "-%o", -n
);
73 disassemble_info
*info
;
75 /* mask off the addressing mode, if any */
80 case 0: case 1: case 2: case 3: case 4: case 5:
81 FPRINTF (F
, "r%d", reg
); break;
82 case 6: FPRINTF (F
, "sp"); break;
83 case 7: FPRINTF (F
, "pc"); break;
89 print_freg (freg
, info
)
91 disassemble_info
*info
;
93 FPRINTF (F
, "fr%d", freg
);
97 print_operand (memaddr
, code
, info
)
100 disassemble_info
*info
;
102 int mode
= (code
>> 3) & 7;
109 print_reg (reg
, info
);
113 print_reg (reg
, info
);
120 if (read_word (*memaddr
, &data
, info
) < 0)
123 print_signed_octal (sign_extend (data
), info
);
129 print_reg (reg
, info
);
137 if (read_word (*memaddr
, &address
, info
) < 0)
139 FPRINTF (F
, "*$%o", address
);
145 print_reg (reg
, info
);
151 print_reg (reg
, info
);
156 print_reg (reg
, info
);
161 if (read_word (*memaddr
, &disp
, info
) < 0)
166 bfd_vma address
= *memaddr
+ sign_extend (disp
);
169 (*info
->print_address_func
) (address
, info
);
175 print_signed_octal (sign_extend (disp
), info
);
177 print_reg (reg
, info
);
186 /* Print the PDP-11 instruction at address MEMADDR in debugged memory,
187 on INFO->STREAM. Returns length of the instruction, in bytes. */
190 print_insn_pdp11 (memaddr
, info
)
192 disassemble_info
*info
;
194 bfd_vma start_memaddr
= memaddr
;
199 info
->bytes_per_line
= 6;
200 info
->bytes_per_chunk
= 2;
201 info
->display_endian
= BFD_ENDIAN_LITTLE
;
203 if (read_word (memaddr
, &opcode
, info
) != 0)
207 src
= (opcode
>> 6) & 0x3f;
210 for (i
= 0; i
< pdp11_num_opcodes
; i
++)
212 #define OP pdp11_opcodes[i]
213 if ((opcode
& OP
.mask
) == OP
.opcode
)
216 case PDP11_OPCODE_NO_OPS
:
217 FPRINTF (F
, OP
.name
);
219 case PDP11_OPCODE_REG
:
220 FPRINTF (F
, OP
.name
);
221 FPRINTF (F
, AFTER_INSTRUCTION
);
222 print_reg (dst
, info
);
224 case PDP11_OPCODE_OP
:
225 FPRINTF (F
, OP
.name
);
226 FPRINTF (F
, AFTER_INSTRUCTION
);
227 if (strcmp (OP
.name
, "jmp") == 0)
229 if (print_operand (&memaddr
, dst
, info
) < 0)
232 case PDP11_OPCODE_REG_OP
:
233 FPRINTF (F
, OP
.name
);
234 FPRINTF (F
, AFTER_INSTRUCTION
);
235 print_reg (src
, info
);
236 FPRINTF (F
, OPERAND_SEPARATOR
);
237 if (strcmp (OP
.name
, "jsr") == 0)
239 if (print_operand (&memaddr
, dst
, info
) < 0)
242 case PDP11_OPCODE_REG_OP_REV
:
243 FPRINTF (F
, OP
.name
);
244 FPRINTF (F
, AFTER_INSTRUCTION
);
245 if (print_operand (&memaddr
, dst
, info
) < 0)
247 FPRINTF (F
, OPERAND_SEPARATOR
);
248 print_reg (src
, info
);
250 case PDP11_OPCODE_AC_OP
:
252 int ac
= (opcode
& 0xe0) >> 6;
253 FPRINTF (F
, OP
.name
);
254 FPRINTF (F
, AFTER_INSTRUCTION
);
255 print_freg (ac
, info
);
256 FPRINTF (F
, OPERAND_SEPARATOR
);
257 if (print_operand (&memaddr
, dst
, info
) < 0)
261 case PDP11_OPCODE_OP_OP
:
262 FPRINTF (F
, OP
.name
);
263 FPRINTF (F
, AFTER_INSTRUCTION
);
264 if (print_operand (&memaddr
, src
, info
) < 0)
266 FPRINTF (F
, OPERAND_SEPARATOR
);
267 if (print_operand (&memaddr
, dst
, info
) < 0)
270 case PDP11_OPCODE_DISPL
:
272 int displ
= (opcode
& 0xff) << 8;
273 bfd_vma address
= memaddr
+ (sign_extend (displ
) >> 7);
274 FPRINTF (F
, OP
.name
);
275 FPRINTF (F
, AFTER_INSTRUCTION
);
276 (*info
->print_address_func
) (address
, info
);
279 case PDP11_OPCODE_REG_DISPL
:
281 int displ
= (opcode
& 0x3f) << 10;
282 bfd_vma address
= memaddr
+ (sign_extend (displ
) >> 9);
283 FPRINTF (F
, OP
.name
);
284 FPRINTF (F
, AFTER_INSTRUCTION
);
285 print_reg (src
, info
);
286 FPRINTF (F
, OPERAND_SEPARATOR
);
287 (*info
->print_address_func
) (address
, info
);
290 case PDP11_OPCODE_IMM8
:
292 int code
= opcode
& 0xff;
293 FPRINTF (F
, OP
.name
);
294 FPRINTF (F
, AFTER_INSTRUCTION
);
295 FPRINTF (F
, "%o", code
);
298 case PDP11_OPCODE_IMM6
:
300 int code
= opcode
& 0x3f;
301 FPRINTF (F
, OP
.name
);
302 FPRINTF (F
, AFTER_INSTRUCTION
);
303 FPRINTF (F
, "%o", code
);
306 case PDP11_OPCODE_IMM3
:
308 int code
= opcode
& 7;
309 FPRINTF (F
, OP
.name
);
310 FPRINTF (F
, AFTER_INSTRUCTION
);
311 FPRINTF (F
, "%o", code
);
315 /* TODO: is this a proper way of signalling an error? */
316 FPRINTF (F
, "<internal error: unrecognized instruction type>");
322 return memaddr
- start_memaddr
;