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