]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/m68hc11-dis.c
Avoid crash in dwarf2_init_complex_target_type
[thirdparty/binutils-gdb.git] / opcodes / m68hc11-dis.c
CommitLineData
60bcf0fa 1/* m68hc11-dis.c -- Motorola 68HC11 & 68HC12 disassembly
82704155 2 Copyright (C) 1999-2019 Free Software Foundation, Inc.
f07534f6 3 Written by Stephane Carrez (stcarrez@nerim.fr)
6927f982 4 XGATE and S12X added by James Murray (jsm@jsm-net.demon.co.uk)
60bcf0fa 5
9b201bb5 6 This file is part of the GNU opcodes library.
60bcf0fa 7
9b201bb5
NC
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
60bcf0fa 12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
60bcf0fa 22
5eb3690e 23#include "sysdep.h"
60bcf0fa
NC
24#include <stdio.h>
25
60bcf0fa 26#include "opcode/m68hc11.h"
88c1242d 27#include "disassemble.h"
60bcf0fa 28
2fd84db3
SC
29#define PC_REGNUM 3
30
6927f982
NC
31static const char *const reg_name[] =
32{
60bcf0fa
NC
33 "X", "Y", "SP", "PC"
34};
35
6927f982
NC
36static const char *const reg_src_table[] =
37{
60bcf0fa
NC
38 "A", "B", "CCR", "TMP3", "D", "X", "Y", "SP"
39};
40
6927f982
NC
41static const char *const reg_dst_table[] =
42{
60bcf0fa
NC
43 "A", "B", "CCR", "TMP2", "D", "X", "Y", "SP"
44};
45
46#define OP_PAGE_MASK (M6811_OP_PAGE2|M6811_OP_PAGE3|M6811_OP_PAGE4)
47
b849bb42 48/* Prototypes for local functions. */
fde8b632
SC
49static int read_memory (bfd_vma, bfd_byte *, int, struct disassemble_info *);
50static int print_indexed_operand (bfd_vma, struct disassemble_info *,
6927f982 51 int*, int, int, bfd_vma, int);
fde8b632 52static int print_insn (bfd_vma, struct disassemble_info *, int);
b849bb42 53
60bcf0fa 54static int
fde8b632
SC
55read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
56 struct disassemble_info* info)
60bcf0fa
NC
57{
58 int status;
59
60 /* Get first byte. Only one at a time because we don't know the
61 size of the insn. */
62 status = (*info->read_memory_func) (memaddr, buffer, size, info);
63 if (status != 0)
64 {
65 (*info->memory_error_func) (status, memaddr, info);
66 return -1;
67 }
68 return 0;
69}
70
71
72/* Read the 68HC12 indexed operand byte and print the corresponding mode.
73 Returns the number of bytes read or -1 if failure. */
74static int
fde8b632
SC
75print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
76 int* indirect, int mov_insn, int pc_offset,
6927f982 77 bfd_vma endaddr, int arch)
60bcf0fa
NC
78{
79 bfd_byte buffer[4];
80 int reg;
81 int status;
82 short sval;
83 int pos = 1;
84
f07534f6
SC
85 if (indirect)
86 *indirect = 0;
87
60bcf0fa
NC
88 status = read_memory (memaddr, &buffer[0], 1, info);
89 if (status != 0)
90 {
91 return status;
92 }
93
94 /* n,r with 5-bits signed constant. */
95 if ((buffer[0] & 0x20) == 0)
96 {
97 reg = (buffer[0] >> 6) & 3;
98 sval = (buffer[0] & 0x1f);
99 if (sval & 0x10)
100 sval |= 0xfff0;
2fd84db3
SC
101 /* 68HC12 requires an adjustment for movb/movw pc relative modes. */
102 if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn)
103 sval += pc_offset;
6927f982
NC
104 (*info->fprintf_func) (info->stream, "0x%x,%s",
105 (unsigned short) sval, reg_name[reg]);
2fd84db3
SC
106
107 if (reg == PC_REGNUM)
108 {
109 (* info->fprintf_func) (info->stream, " {");
6927f982
NC
110 if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */
111 (*info->fprintf_func) (info->stream, "0x");
2fd84db3
SC
112 (* info->print_address_func) (endaddr + sval, info);
113 (* info->fprintf_func) (info->stream, "}");
114 }
60bcf0fa
NC
115 }
116
117 /* Auto pre/post increment/decrement. */
118 else if ((buffer[0] & 0xc0) != 0xc0)
119 {
120 const char *mode;
121
122 reg = (buffer[0] >> 6) & 3;
123 sval = (buffer[0] & 0x0f);
124 if (sval & 0x8)
125 {
126 sval |= 0xfff0;
127 sval = -sval;
128 mode = "-";
129 }
130 else
131 {
132 sval = sval + 1;
133 mode = "+";
134 }
135 (*info->fprintf_func) (info->stream, "%d,%s%s%s",
6927f982 136 (unsigned short) sval,
60bcf0fa
NC
137 (buffer[0] & 0x10 ? "" : mode),
138 reg_name[reg], (buffer[0] & 0x10 ? mode : ""));
139 }
140
141 /* [n,r] 16-bits offset indexed indirect. */
142 else if ((buffer[0] & 0x07) == 3)
143 {
6927f982
NC
144 if ((mov_insn) && (!(arch & cpu9s12x)))
145 {
146 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>",
147 buffer[0] & 0x0ff);
148 return 0;
149 }
60bcf0fa
NC
150 reg = (buffer[0] >> 3) & 0x03;
151 status = read_memory (memaddr + pos, &buffer[0], 2, info);
152 if (status != 0)
153 {
154 return status;
155 }
156
157 pos += 2;
158 sval = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
6927f982 159 (*info->fprintf_func) (info->stream, "[0x%x,%s]",
60bcf0fa 160 sval & 0x0ffff, reg_name[reg]);
f07534f6
SC
161 if (indirect)
162 *indirect = 1;
60bcf0fa 163 }
2fd84db3
SC
164
165 /* n,r with 9 and 16 bit signed constant. */
60bcf0fa
NC
166 else if ((buffer[0] & 0x4) == 0)
167 {
6927f982
NC
168 if ((mov_insn) && (!(arch & cpu9s12x)))
169 {
170 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>",
171 buffer[0] & 0x0ff);
172 return 0;
173 }
174
60bcf0fa
NC
175 reg = (buffer[0] >> 3) & 0x03;
176 status = read_memory (memaddr + pos,
177 &buffer[1], (buffer[0] & 0x2 ? 2 : 1), info);
178 if (status != 0)
179 {
180 return status;
181 }
182 if (buffer[0] & 2)
183 {
184 sval = ((buffer[1] << 8) | (buffer[2] & 0x0FF));
185 sval &= 0x0FFFF;
186 pos += 2;
b394d696 187 endaddr += 2;
60bcf0fa
NC
188 }
189 else
190 {
191 sval = buffer[1] & 0x00ff;
192 if (buffer[0] & 0x01)
193 sval |= 0xff00;
194 pos++;
b394d696 195 endaddr++;
60bcf0fa 196 }
6927f982
NC
197 (*info->fprintf_func) (info->stream, "0x%x,%s",
198 (unsigned short) sval, reg_name[reg]);
2fd84db3
SC
199 if (reg == PC_REGNUM)
200 {
6927f982 201 (* info->fprintf_func) (info->stream, " {0x");
2fd84db3
SC
202 (* info->print_address_func) (endaddr + sval, info);
203 (* info->fprintf_func) (info->stream, "}");
204 }
60bcf0fa
NC
205 }
206 else
207 {
208 reg = (buffer[0] >> 3) & 0x03;
209 switch (buffer[0] & 3)
210 {
211 case 0:
212 (*info->fprintf_func) (info->stream, "A,%s", reg_name[reg]);
213 break;
214 case 1:
215 (*info->fprintf_func) (info->stream, "B,%s", reg_name[reg]);
216 break;
217 case 2:
218 (*info->fprintf_func) (info->stream, "D,%s", reg_name[reg]);
219 break;
220 case 3:
221 default:
222 (*info->fprintf_func) (info->stream, "[D,%s]", reg_name[reg]);
f07534f6
SC
223 if (indirect)
224 *indirect = 1;
60bcf0fa
NC
225 break;
226 }
227 }
228
229 return pos;
230}
231
232/* Disassemble one instruction at address 'memaddr'. Returns the number
233 of bytes used by that instruction. */
234static int
fde8b632 235print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
60bcf0fa
NC
236{
237 int status;
238 bfd_byte buffer[4];
6927f982 239 unsigned int code;
60bcf0fa
NC
240 long format, pos, i;
241 short sval;
242 const struct m68hc11_opcode *opcode;
243
6927f982
NC
244 if (arch & cpuxgate)
245 {
246 int val;
247 /* Get two bytes as all XGATE instructions are 16bit. */
248 status = read_memory (memaddr, buffer, 2, info);
249 if (status != 0)
250 return status;
251
252 format = 0;
253 code = (buffer[0] << 8) + buffer[1];
254
255 /* Scan the opcode table until we find the opcode
256 with the corresponding page. */
257 opcode = m68hc11_opcodes;
258 for (i = 0; i < m68hc11_num_opcodes; i++, opcode++)
259 {
260 if ((opcode->opcode != (code & opcode->xg_mask)) || (opcode->arch != cpuxgate))
261 continue;
262 /* We have found the opcode. Extract the operand and print it. */
263 (*info->fprintf_func) (info->stream, "%s", opcode->name);
264 format = opcode->format;
265 if (format & (M68XG_OP_NONE))
266 {
267 /* Nothing to print. */
268 }
269 else if (format & M68XG_OP_IMM3)
270 (*info->fprintf_func) (info->stream, " #0x%x", (code >> 8) & 0x7);
271 else if (format & M68XG_OP_R_R)
272 (*info->fprintf_func) (info->stream, " R%x, R%x",
273 (code >> 8) & 0x7, (code >> 5) & 0x7);
274 else if (format & M68XG_OP_R_R_R)
275 (*info->fprintf_func) (info->stream, " R%x, R%x, R%x",
276 (code >> 8) & 0x7, (code >> 5) & 0x7, (code >> 2) & 0x7);
277 else if (format & M68XG_OP_RD_RB_RI)
278 (*info->fprintf_func) (info->stream, " R%x, (R%x, R%x)",
279 (code >> 8) & 0x7, (code >> 5) & 0x7, (code >> 2) & 0x7);
280 else if (format & M68XG_OP_RD_RB_RIp)
281 (*info->fprintf_func) (info->stream, " R%x, (R%x, R%x+)",
282 (code >> 8) & 0x7, (code >> 5) & 0x7, (code >> 2) & 0x7);
283 else if (format & M68XG_OP_RD_RB_mRI)
284 (*info->fprintf_func) (info->stream, " R%x, (R%x, -R%x)",
285 (code >> 8) & 0x7, (code >> 5) & 0x7, (code >> 2) & 0x7);
286 else if (format & M68XG_OP_R_R_OFFS5)
287 (*info->fprintf_func) (info->stream, " R%x, (R%x, #0x%x)",
288 (code >> 8) & 0x7, (code >> 5) & 0x7, code & 0x1f);
289 else if (format & M68XG_OP_R_IMM8)
290 (*info->fprintf_func) (info->stream, " R%x, #0x%02x",
291 (code >> 8) & 0x7, code & 0xff);
292 else if (format & M68XG_OP_R_IMM4)
293 (*info->fprintf_func) (info->stream, " R%x, #0x%x",
294 (code >> 8) & 0x7, (code & 0xf0) >> 4);
295 else if (format & M68XG_OP_REL9)
296 {
297 (*info->fprintf_func) (info->stream, " 0x");
298 val = (buffer[0] & 0x1) ? buffer[1] | 0xFFFFFF00 : buffer[1];
299 (*info->print_address_func) (memaddr + (val << 1) + 2, info);
300 }
301 else if (format & M68XG_OP_REL10)
302 {
303 (*info->fprintf_func) (info->stream, " 0x");
304 val = (buffer[0] << 8) | (unsigned int) buffer[1];
305 if (val & 0x200)
306 val |= 0xfffffc00;
307 else
308 val &= 0x000001ff;
309 (*info->print_address_func) (memaddr + (val << 1) + 2, info);
310 }
311 else if ((code & 0x00ff) == 0x00f8)
312 (*info->fprintf_func) (info->stream, " R%x, CCR", (code >> 8) & 0x7);
313 else if ((code & 0x00ff) == 0x00f9)
314 (*info->fprintf_func) (info->stream, " CCR, R%x", (code >> 8) & 0x7);
315 else if ((code & 0x00ff) == 0x0)
316 (*info->fprintf_func) (info->stream, " R%x, PC", (code >> 8) & 0x7);
317 else if (format & M68XG_OP_R)
318 {
319 /* Special cases for TFR. */
320 if ((code & 0xf8ff) == 0x00f8)
321 (*info->fprintf_func) (info->stream, " R%x, CCR", (code >> 8) & 0x7);
322 else if ((code & 0xf8ff) == 0x00f9)
323 (*info->fprintf_func) (info->stream, " CCR, R%x", (code >> 8) & 0x7);
324 else if ((code & 0xf8ff) == 0x00fa)
325 (*info->fprintf_func) (info->stream, " R%x, PC", (code >> 8) & 0x7);
326 else
327 (*info->fprintf_func) (info->stream, " R%x", (code >> 8) & 0x7);
328 }
329 else
330 /* Opcode not recognized. */
331 (*info->fprintf_func) (info->stream, "Not yet handled TEST .byte\t0x%04x", code);
332 return 2;
333 }
334
335 /* Opcode not recognized. */
336 (*info->fprintf_func) (info->stream, ".byte\t0x%04x", code);
337 return 2; /* Everything is two bytes. */
338 }
339
340 /* HC11 and HC12. */
341
60bcf0fa
NC
342 /* Get first byte. Only one at a time because we don't know the
343 size of the insn. */
344 status = read_memory (memaddr, buffer, 1, info);
345 if (status != 0)
6927f982 346 return status;
60bcf0fa
NC
347
348 format = 0;
349 code = buffer[0];
350 pos = 0;
351
352 /* Look for page2,3,4 opcodes. */
353 if (code == M6811_OPCODE_PAGE2)
354 {
355 pos++;
356 format = M6811_OP_PAGE2;
357 }
358 else if (code == M6811_OPCODE_PAGE3 && arch == cpu6811)
359 {
360 pos++;
361 format = M6811_OP_PAGE3;
362 }
363 else if (code == M6811_OPCODE_PAGE4 && arch == cpu6811)
364 {
365 pos++;
366 format = M6811_OP_PAGE4;
367 }
368
369 /* We are in page2,3,4; get the real opcode. */
370 if (pos == 1)
371 {
372 status = read_memory (memaddr + pos, &buffer[1], 1, info);
373 if (status != 0)
6927f982
NC
374 return status;
375
60bcf0fa
NC
376 code = buffer[1];
377 }
378
60bcf0fa
NC
379 /* Look first for a 68HC12 alias. All of them are 2-bytes long and
380 in page 1. There is no operand to print. We read the second byte
381 only when we have a possible match. */
382 if ((arch & cpu6812) && format == 0)
383 {
384 int must_read = 1;
385
386 /* Walk the alias table to find a code1+code2 match. */
387 for (i = 0; i < m68hc12_num_alias; i++)
388 {
389 if (m68hc12_alias[i].code1 == code)
390 {
391 if (must_read)
392 {
393 status = read_memory (memaddr + pos + 1,
394 &buffer[1], 1, info);
395 if (status != 0)
396 break;
397
398 must_read = 1;
399 }
400 if (m68hc12_alias[i].code2 == (unsigned char) buffer[1])
401 {
402 (*info->fprintf_func) (info->stream, "%s",
403 m68hc12_alias[i].name);
404 return 2;
405 }
406 }
407 }
408 }
409
410 pos++;
411
412 /* Scan the opcode table until we find the opcode
413 with the corresponding page. */
414 opcode = m68hc11_opcodes;
415 for (i = 0; i < m68hc11_num_opcodes; i++, opcode++)
416 {
417 int offset;
2fd84db3 418 int pc_src_offset;
fde8b632 419 int pc_dst_offset = 0;
60bcf0fa
NC
420
421 if ((opcode->arch & arch) == 0)
422 continue;
423 if (opcode->opcode != code)
424 continue;
425 if ((opcode->format & OP_PAGE_MASK) != format)
426 continue;
427
428 if (opcode->format & M6812_OP_REG)
429 {
430 int j;
431 int is_jump;
432
433 if (opcode->format & M6811_OP_JUMP_REL)
434 is_jump = 1;
435 else
436 is_jump = 0;
437
438 status = read_memory (memaddr + pos, &buffer[0], 1, info);
439 if (status != 0)
440 {
441 return status;
442 }
443 for (j = 0; i + j < m68hc11_num_opcodes; j++)
444 {
445 if ((opcode[j].arch & arch) == 0)
446 continue;
447 if (opcode[j].opcode != code)
448 continue;
449 if (is_jump)
450 {
451 if (!(opcode[j].format & M6811_OP_JUMP_REL))
452 continue;
453
454 if ((opcode[j].format & M6812_OP_IBCC_MARKER)
455 && (buffer[0] & 0xc0) != 0x80)
456 continue;
457 if ((opcode[j].format & M6812_OP_TBCC_MARKER)
458 && (buffer[0] & 0xc0) != 0x40)
459 continue;
460 if ((opcode[j].format & M6812_OP_DBCC_MARKER)
461 && (buffer[0] & 0xc0) != 0)
462 continue;
463 if ((opcode[j].format & M6812_OP_EQ_MARKER)
464 && (buffer[0] & 0x20) == 0)
465 break;
466 if (!(opcode[j].format & M6812_OP_EQ_MARKER)
467 && (buffer[0] & 0x20) != 0)
468 break;
469 continue;
470 }
471 if (opcode[j].format & M6812_OP_EXG_MARKER && buffer[0] & 0x80)
472 break;
473 if ((opcode[j].format & M6812_OP_SEX_MARKER)
474 && (((buffer[0] & 0x07) >= 3 && (buffer[0] & 7) <= 7))
475 && ((buffer[0] & 0x0f0) <= 0x20))
476 break;
6927f982
NC
477 if ((opcode[j].format & M6812_OP_SEX_MARKER)
478 && (arch & cpu9s12x)
479 && ((buffer[0] == 0x4d) || (buffer[0] == 0x4e)))
480 break;
60bcf0fa
NC
481 if (opcode[j].format & M6812_OP_TFR_MARKER
482 && !(buffer[0] & 0x80))
483 break;
484 }
485 if (i + j < m68hc11_num_opcodes)
486 opcode = &opcode[j];
487 }
488
489 /* We have found the opcode. Extract the operand and print it. */
490 (*info->fprintf_func) (info->stream, "%s", opcode->name);
491
492 format = opcode->format;
493 if (format & (M6811_OP_MASK | M6811_OP_BITMASK
494 | M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
495 {
496 (*info->fprintf_func) (info->stream, "\t");
497 }
498
64e38312 499 /* The movb and movw must be handled in a special way...
6927f982
NC
500 The source constant 'ii' is not always at the same place.
501 This is the same for the destination for the post-indexed byte.
502 The 'offset' is used to do the appropriate correction.
503
504 offset offset
505 for constant for destination
506 movb 18 OB ii hh ll 0 0
507 18 08 xb ii 1 -1
508 18 08 xb ff ii 2 1 9 bit
509 18 08 xb ee ff ii 3 1 16 bit
510 18 0C hh ll hh ll 0 0
511 18 09 xb hh ll 1 -1
512 18 0D xb hh ll 0 0
513 18 0A xb xb 0 0
514
515 movw 18 03 jj kk hh ll 0 0
516 18 00 xb jj kk 1 -1
517 18 04 hh ll hh ll 0 0
518 18 01 xb hh ll 1 -1
519 18 05 xb hh ll 0 0
520 18 02 xb xb 0 0
521
522 After the source operand is read, the position 'pos' is incremented
523 this explains the negative offset for destination.
524
525 movb/movw above are the only instructions with this matching
526 format. */
64e38312 527 offset = ((format & M6812_OP_IDX_P2)
6927f982
NC
528 && (format & (M6811_OP_IMM8 | M6811_OP_IMM16 |
529 M6811_OP_IND16)));
530
531 if (offset)
532 {
533 /* Check xb to see position of data. */
534 status = read_memory (memaddr + pos, &buffer[0], 1, info);
535 if (status != 0)
536 {
537 return status;
538 }
539
540 if (((buffer[0] & 0xe0) == 0xe0) && ((buffer[0] & 0x04) == 0))
541 {
542 /* 9 or 16 bit. */
543 if ((buffer[0] & 0x02) == 0)
544 {
545 /* 9 bit. */
546 offset = 2;
547 }
548 else
549 {
550 /* 16 bit. */
551 offset = 3;
552 }
553 }
554 }
60bcf0fa
NC
555
556 /* Operand with one more byte: - immediate, offset,
6927f982 557 direct-low address. */
60bcf0fa
NC
558 if (format &
559 (M6811_OP_IMM8 | M6811_OP_IX | M6811_OP_IY | M6811_OP_DIRECT))
560 {
561 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info);
562 if (status != 0)
6927f982
NC
563 return status;
564
565 /* This movb/movw is special (see above). */
566 if (offset < 2)
60bcf0fa 567 {
6927f982
NC
568 offset = -offset;
569 pc_dst_offset = 2;
570 }
571 else
572 {
573 offset = -1;
574 pc_dst_offset = 5;
60bcf0fa 575 }
60bcf0fa 576 pos++;
64e38312 577
60bcf0fa
NC
578 if (format & M6811_OP_IMM8)
579 {
6927f982 580 (*info->fprintf_func) (info->stream, "#0x%x", (int) buffer[0]);
60bcf0fa 581 format &= ~M6811_OP_IMM8;
6927f982
NC
582 /* Set PC destination offset. */
583 pc_dst_offset = 1;
60bcf0fa
NC
584 }
585 else if (format & M6811_OP_IX)
586 {
587 /* Offsets are in range 0..255, print them unsigned. */
6927f982 588 (*info->fprintf_func) (info->stream, "0x%x,x", buffer[0] & 0x0FF);
60bcf0fa
NC
589 format &= ~M6811_OP_IX;
590 }
591 else if (format & M6811_OP_IY)
592 {
6927f982 593 (*info->fprintf_func) (info->stream, "0x%x,y", buffer[0] & 0x0FF);
60bcf0fa
NC
594 format &= ~M6811_OP_IY;
595 }
596 else if (format & M6811_OP_DIRECT)
597 {
598 (*info->fprintf_func) (info->stream, "*");
6927f982
NC
599 if (info->symtab_size > 0) /* Avoid duplicate 0x. */
600 (*info->fprintf_func) (info->stream, "0x");
60bcf0fa
NC
601 (*info->print_address_func) (buffer[0] & 0x0FF, info);
602 format &= ~M6811_OP_DIRECT;
603 }
604 }
605
2fd84db3 606#define M6812_DST_MOVE (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)
60bcf0fa
NC
607#define M6812_INDEXED_FLAGS (M6812_OP_IDX|M6812_OP_IDX_1|M6812_OP_IDX_2)
608 /* Analyze the 68HC12 indexed byte. */
609 if (format & M6812_INDEXED_FLAGS)
610 {
6927f982
NC
611 int indirect;
612 bfd_vma endaddr;
613
614 endaddr = memaddr + pos + 1;
615 if (format & M6811_OP_IND16)
616 endaddr += 2;
617 pc_src_offset = -1;
618 pc_dst_offset = 1;
2fd84db3 619 status = print_indexed_operand (memaddr + pos, info, &indirect,
6927f982
NC
620 (format & M6812_DST_MOVE),
621 pc_src_offset, endaddr, arch);
60bcf0fa 622 if (status < 0)
6927f982
NC
623 return status;
624
60bcf0fa 625 pos += status;
f07534f6 626
6927f982
NC
627 /* The indirect addressing mode of the call instruction does
628 not need the page code. */
629 if ((format & M6812_OP_PAGE) && indirect)
630 format &= ~M6812_OP_PAGE;
60bcf0fa
NC
631 }
632
633 /* 68HC12 dbcc/ibcc/tbcc operands. */
634 if ((format & M6812_OP_REG) && (format & M6811_OP_JUMP_REL))
635 {
636 status = read_memory (memaddr + pos, &buffer[0], 2, info);
637 if (status != 0)
6927f982
NC
638 return status;
639
60bcf0fa
NC
640 (*info->fprintf_func) (info->stream, "%s,",
641 reg_src_table[buffer[0] & 0x07]);
642 sval = buffer[1] & 0x0ff;
643 if (buffer[0] & 0x10)
644 sval |= 0xff00;
645
646 pos += 2;
6927f982 647 (*info->fprintf_func) (info->stream, "0x");
60bcf0fa
NC
648 (*info->print_address_func) (memaddr + pos + sval, info);
649 format &= ~(M6812_OP_REG | M6811_OP_JUMP_REL);
650 }
651 else if (format & (M6812_OP_REG | M6812_OP_REG_2))
652 {
653 status = read_memory (memaddr + pos, &buffer[0], 1, info);
654 if (status != 0)
6927f982 655 return status;
60bcf0fa
NC
656
657 pos++;
658 (*info->fprintf_func) (info->stream, "%s,%s",
659 reg_src_table[(buffer[0] >> 4) & 7],
660 reg_dst_table[(buffer[0] & 7)]);
661 }
662
60bcf0fa
NC
663 if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
664 {
665 int val;
6927f982
NC
666 bfd_vma addr;
667 unsigned page = 0;
60bcf0fa
NC
668
669 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info);
670 if (status != 0)
6927f982
NC
671 return status;
672
60bcf0fa
NC
673 if (format & M6812_OP_IDX_P2)
674 offset = -2;
675 else
676 offset = 0;
677 pos += 2;
678
679 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
680 val &= 0x0FFFF;
6927f982
NC
681 addr = val;
682 pc_dst_offset = 2;
683 if (format & M6812_OP_PAGE)
684 {
685 status = read_memory (memaddr + pos + offset, buffer, 1, info);
686 if (status != 0)
687 return status;
688
689 page = (unsigned) buffer[0];
690 if (addr >= M68HC12_BANK_BASE && addr < 0x0c000)
691 addr = ((val - M68HC12_BANK_BASE)
692 | (page << M68HC12_BANK_SHIFT))
693 + M68HC12_BANK_VIRT;
694 }
695 else if ((arch & cpu6812)
696 && addr >= M68HC12_BANK_BASE && addr < 0x0c000)
697 {
698 int cur_page;
699 bfd_vma vaddr;
43e65147 700
6927f982
NC
701 if (memaddr >= M68HC12_BANK_VIRT)
702 cur_page = ((memaddr - M68HC12_BANK_VIRT)
703 >> M68HC12_BANK_SHIFT);
704 else
705 cur_page = 0;
706
707 vaddr = ((addr - M68HC12_BANK_BASE)
708 + (cur_page << M68HC12_BANK_SHIFT))
709 + M68HC12_BANK_VIRT;
710 if (!info->symbol_at_address_func (addr, info)
711 && info->symbol_at_address_func (vaddr, info))
712 addr = vaddr;
713 }
60bcf0fa
NC
714 if (format & M6811_OP_IMM16)
715 {
716 format &= ~M6811_OP_IMM16;
717 (*info->fprintf_func) (info->stream, "#");
718 }
719 else
6927f982
NC
720 {
721 format &= ~M6811_OP_IND16;
722 }
723
724 if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */
725 (*info->fprintf_func) (info->stream, "0x");
60bcf0fa 726
f07534f6 727 (*info->print_address_func) (addr, info);
6927f982
NC
728 if (format & M6812_OP_PAGE)
729 {
730 (* info->fprintf_func) (info->stream, " {");
731 if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */
732 (*info->fprintf_func) (info->stream, "0x");
733 (* info->print_address_func) (val, info);
734 (* info->fprintf_func) (info->stream, ", 0x%x}", page);
735 format &= ~M6812_OP_PAGE;
736 pos += 1;
737 }
60bcf0fa
NC
738 }
739
740 if (format & M6812_OP_IDX_P2)
741 {
742 (*info->fprintf_func) (info->stream, ", ");
2fd84db3 743 status = print_indexed_operand (memaddr + pos + offset, info,
6927f982
NC
744 0, 1, pc_dst_offset,
745 memaddr + pos + offset + 1, arch);
60bcf0fa
NC
746 if (status < 0)
747 return status;
748 pos += status;
749 }
750
751 if (format & M6812_OP_IND16_P2)
752 {
753 int val;
754
755 (*info->fprintf_func) (info->stream, ", ");
756
757 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info);
758 if (status != 0)
6927f982
NC
759 return status;
760
60bcf0fa
NC
761 pos += 2;
762
763 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
764 val &= 0x0FFFF;
6927f982
NC
765 if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */
766 (*info->fprintf_func) (info->stream, "0x");
60bcf0fa
NC
767 (*info->print_address_func) (val, info);
768 }
769
ac8c616a 770 /* M6811_OP_BITMASK and M6811_OP_JUMP_REL must be treated separately
6927f982
NC
771 and in that order. The brset/brclr insn have a bitmask and then
772 a relative branch offset. */
ac8c616a
SC
773 if (format & M6811_OP_BITMASK)
774 {
775 status = read_memory (memaddr + pos, &buffer[0], 1, info);
776 if (status != 0)
6927f982
NC
777 return status;
778
ac8c616a 779 pos++;
6927f982 780 (*info->fprintf_func) (info->stream, ", #0x%02x%s",
ac8c616a 781 buffer[0] & 0x0FF,
6927f982 782 (format & M6811_OP_JUMP_REL ? ", " : ""));
ac8c616a
SC
783 format &= ~M6811_OP_BITMASK;
784 }
785 if (format & M6811_OP_JUMP_REL)
786 {
787 int val;
788
789 status = read_memory (memaddr + pos, &buffer[0], 1, info);
790 if (status != 0)
6927f982 791 return status;
ac8c616a 792
6927f982 793 (*info->fprintf_func) (info->stream, "0x");
ac8c616a
SC
794 pos++;
795 val = (buffer[0] & 0x80) ? buffer[0] | 0xFFFFFF00 : buffer[0];
796 (*info->print_address_func) (memaddr + pos + val, info);
797 format &= ~M6811_OP_JUMP_REL;
798 }
799 else if (format & M6812_OP_JUMP_REL16)
800 {
801 int val;
802
803 status = read_memory (memaddr + pos, &buffer[0], 2, info);
804 if (status != 0)
6927f982 805 return status;
ac8c616a
SC
806
807 pos += 2;
808 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
809 if (val & 0x8000)
810 val |= 0xffff0000;
811
6927f982 812 (*info->fprintf_func) (info->stream, "0x");
ac8c616a
SC
813 (*info->print_address_func) (memaddr + pos + val, info);
814 format &= ~M6812_OP_JUMP_REL16;
815 }
816
f07534f6
SC
817 if (format & M6812_OP_PAGE)
818 {
819 int val;
820
821 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info);
822 if (status != 0)
6927f982
NC
823 return status;
824
f07534f6
SC
825 pos += 1;
826
827 val = buffer[0] & 0x0ff;
6927f982 828 (*info->fprintf_func) (info->stream, ", 0x%x", val);
f07534f6 829 }
43e65147 830
60bcf0fa
NC
831#ifdef DEBUG
832 /* Consistency check. 'format' must be 0, so that we have handled
6927f982
NC
833 all formats; and the computed size of the insn must match the
834 opcode table content. */
60bcf0fa 835 if (format & ~(M6811_OP_PAGE4 | M6811_OP_PAGE3 | M6811_OP_PAGE2))
6927f982
NC
836 (*info->fprintf_func) (info->stream, "; Error, format: %lx", format);
837
60bcf0fa 838 if (pos != opcode->size)
6927f982
NC
839 (*info->fprintf_func) (info->stream, "; Error, size: %ld expect %d",
840 pos, opcode->size);
60bcf0fa
NC
841#endif
842 return pos;
843 }
844
845 /* Opcode not recognized. */
846 if (format == M6811_OP_PAGE2 && arch & cpu6812
fde8b632 847 && ((code >= 0x30 && code <= 0x39) || (code >= 0x40)))
6927f982 848 (*info->fprintf_func) (info->stream, "trap\t#0x%02x", code & 0x0ff);
60bcf0fa
NC
849
850 else if (format == M6811_OP_PAGE2)
851 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
852 M6811_OPCODE_PAGE2, code);
853 else if (format == M6811_OP_PAGE3)
854 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
855 M6811_OPCODE_PAGE3, code);
856 else if (format == M6811_OP_PAGE4)
857 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
858 M6811_OPCODE_PAGE4, code);
859 else
860 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", code);
861
862 return pos;
863}
864
865/* Disassemble one instruction at address 'memaddr'. Returns the number
866 of bytes used by that instruction. */
867int
fde8b632 868print_insn_m68hc11 (bfd_vma memaddr, struct disassemble_info* info)
60bcf0fa
NC
869{
870 return print_insn (memaddr, info, cpu6811);
871}
872
873int
fde8b632 874print_insn_m68hc12 (bfd_vma memaddr, struct disassemble_info* info)
60bcf0fa
NC
875{
876 return print_insn (memaddr, info, cpu6812);
877}
6927f982
NC
878
879int
880print_insn_m9s12x (bfd_vma memaddr, struct disassemble_info* info)
881{
882 return print_insn (memaddr, info, cpu6812|cpu9s12x);
883}
884
885int
886print_insn_m9s12xg (bfd_vma memaddr, struct disassemble_info* info)
887{
888 return print_insn (memaddr, info, cpuxgate);
889}