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