00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020
00021 #include "ansidecl.h"
00022 #include "opcode/m68hc11.h"
00023 #include "dis-asm.h"
00024
00025 #define PC_REGNUM 3
00026
00027 static const char *const reg_name[] = {
00028 "X", "Y", "SP", "PC"
00029 };
00030
00031 static const char *const reg_src_table[] = {
00032 "A", "B", "CCR", "TMP3", "D", "X", "Y", "SP"
00033 };
00034
00035 static const char *const reg_dst_table[] = {
00036 "A", "B", "CCR", "TMP2", "D", "X", "Y", "SP"
00037 };
00038
00039 #define OP_PAGE_MASK (M6811_OP_PAGE2|M6811_OP_PAGE3|M6811_OP_PAGE4)
00040
00041
00042 static int read_memory (bfd_vma, bfd_byte *, int, struct disassemble_info *);
00043 static int print_indexed_operand (bfd_vma, struct disassemble_info *,
00044 int*, int, int, bfd_vma);
00045 static int print_insn (bfd_vma, struct disassemble_info *, int);
00046
00047 static int
00048 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
00049 struct disassemble_info* info)
00050 {
00051 int status;
00052
00053
00054
00055 status = (*info->read_memory_func) (memaddr, buffer, size, info);
00056 if (status != 0)
00057 {
00058 (*info->memory_error_func) (status, memaddr, info);
00059 return -1;
00060 }
00061 return 0;
00062 }
00063
00064
00065
00066
00067 static int
00068 print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
00069 int* indirect, int mov_insn, int pc_offset,
00070 bfd_vma endaddr)
00071 {
00072 bfd_byte buffer[4];
00073 int reg;
00074 int status;
00075 short sval;
00076 int pos = 1;
00077
00078 if (indirect)
00079 *indirect = 0;
00080
00081 status = read_memory (memaddr, &buffer[0], 1, info);
00082 if (status != 0)
00083 {
00084 return status;
00085 }
00086
00087
00088 if ((buffer[0] & 0x20) == 0)
00089 {
00090 reg = (buffer[0] >> 6) & 3;
00091 sval = (buffer[0] & 0x1f);
00092 if (sval & 0x10)
00093 sval |= 0xfff0;
00094
00095 if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn)
00096 sval += pc_offset;
00097 (*info->fprintf_func) (info->stream, "%d,%s",
00098 (int) sval, reg_name[reg]);
00099
00100 if (reg == PC_REGNUM)
00101 {
00102 (* info->fprintf_func) (info->stream, " {");
00103 (* info->print_address_func) (endaddr + sval, info);
00104 (* info->fprintf_func) (info->stream, "}");
00105 }
00106 }
00107
00108
00109 else if ((buffer[0] & 0xc0) != 0xc0)
00110 {
00111 const char *mode;
00112
00113 reg = (buffer[0] >> 6) & 3;
00114 sval = (buffer[0] & 0x0f);
00115 if (sval & 0x8)
00116 {
00117 sval |= 0xfff0;
00118 sval = -sval;
00119 mode = "-";
00120 }
00121 else
00122 {
00123 sval = sval + 1;
00124 mode = "+";
00125 }
00126 (*info->fprintf_func) (info->stream, "%d,%s%s%s",
00127 (int) sval,
00128 (buffer[0] & 0x10 ? "" : mode),
00129 reg_name[reg], (buffer[0] & 0x10 ? mode : ""));
00130 }
00131
00132
00133 else if ((buffer[0] & 0x07) == 3)
00134 {
00135 if (mov_insn)
00136 {
00137 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>",
00138 buffer[0] & 0x0ff);
00139 return 0;
00140 }
00141 reg = (buffer[0] >> 3) & 0x03;
00142 status = read_memory (memaddr + pos, &buffer[0], 2, info);
00143 if (status != 0)
00144 {
00145 return status;
00146 }
00147
00148 pos += 2;
00149 sval = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
00150 (*info->fprintf_func) (info->stream, "[%u,%s]",
00151 sval & 0x0ffff, reg_name[reg]);
00152 if (indirect)
00153 *indirect = 1;
00154 }
00155
00156
00157 else if ((buffer[0] & 0x4) == 0)
00158 {
00159 if (mov_insn)
00160 {
00161 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>",
00162 buffer[0] & 0x0ff);
00163 return 0;
00164 }
00165 reg = (buffer[0] >> 3) & 0x03;
00166 status = read_memory (memaddr + pos,
00167 &buffer[1], (buffer[0] & 0x2 ? 2 : 1), info);
00168 if (status != 0)
00169 {
00170 return status;
00171 }
00172 if (buffer[0] & 2)
00173 {
00174 sval = ((buffer[1] << 8) | (buffer[2] & 0x0FF));
00175 sval &= 0x0FFFF;
00176 pos += 2;
00177 endaddr += 2;
00178 }
00179 else
00180 {
00181 sval = buffer[1] & 0x00ff;
00182 if (buffer[0] & 0x01)
00183 sval |= 0xff00;
00184 pos++;
00185 endaddr++;
00186 }
00187 (*info->fprintf_func) (info->stream, "%d,%s",
00188 (int) sval, reg_name[reg]);
00189 if (reg == PC_REGNUM)
00190 {
00191 (* info->fprintf_func) (info->stream, " {");
00192 (* info->print_address_func) (endaddr + sval, info);
00193 (* info->fprintf_func) (info->stream, "}");
00194 }
00195 }
00196 else
00197 {
00198 reg = (buffer[0] >> 3) & 0x03;
00199 switch (buffer[0] & 3)
00200 {
00201 case 0:
00202 (*info->fprintf_func) (info->stream, "A,%s", reg_name[reg]);
00203 break;
00204 case 1:
00205 (*info->fprintf_func) (info->stream, "B,%s", reg_name[reg]);
00206 break;
00207 case 2:
00208 (*info->fprintf_func) (info->stream, "D,%s", reg_name[reg]);
00209 break;
00210 case 3:
00211 default:
00212 (*info->fprintf_func) (info->stream, "[D,%s]", reg_name[reg]);
00213 if (indirect)
00214 *indirect = 1;
00215 break;
00216 }
00217 }
00218
00219 return pos;
00220 }
00221
00222
00223
00224 static int
00225 print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
00226 {
00227 int status;
00228 bfd_byte buffer[4];
00229 unsigned char code;
00230 long format, pos, i;
00231 short sval;
00232 const struct m68hc11_opcode *opcode;
00233
00234
00235
00236 status = read_memory (memaddr, buffer, 1, info);
00237 if (status != 0)
00238 {
00239 return status;
00240 }
00241
00242 format = 0;
00243 code = buffer[0];
00244 pos = 0;
00245
00246
00247 if (code == M6811_OPCODE_PAGE2)
00248 {
00249 pos++;
00250 format = M6811_OP_PAGE2;
00251 }
00252 else if (code == M6811_OPCODE_PAGE3 && arch == cpu6811)
00253 {
00254 pos++;
00255 format = M6811_OP_PAGE3;
00256 }
00257 else if (code == M6811_OPCODE_PAGE4 && arch == cpu6811)
00258 {
00259 pos++;
00260 format = M6811_OP_PAGE4;
00261 }
00262
00263
00264 if (pos == 1)
00265 {
00266 status = read_memory (memaddr + pos, &buffer[1], 1, info);
00267 if (status != 0)
00268 {
00269 return status;
00270 }
00271 code = buffer[1];
00272 }
00273
00274
00275
00276
00277
00278 if ((arch & cpu6812) && format == 0)
00279 {
00280 int must_read = 1;
00281
00282
00283 for (i = 0; i < m68hc12_num_alias; i++)
00284 {
00285 if (m68hc12_alias[i].code1 == code)
00286 {
00287 if (must_read)
00288 {
00289 status = read_memory (memaddr + pos + 1,
00290 &buffer[1], 1, info);
00291 if (status != 0)
00292 break;
00293
00294 must_read = 1;
00295 }
00296 if (m68hc12_alias[i].code2 == (unsigned char) buffer[1])
00297 {
00298 (*info->fprintf_func) (info->stream, "%s",
00299 m68hc12_alias[i].name);
00300 return 2;
00301 }
00302 }
00303 }
00304 }
00305
00306 pos++;
00307
00308
00309
00310 opcode = m68hc11_opcodes;
00311 for (i = 0; i < m68hc11_num_opcodes; i++, opcode++)
00312 {
00313 int offset;
00314 int pc_src_offset;
00315 int pc_dst_offset = 0;
00316
00317 if ((opcode->arch & arch) == 0)
00318 continue;
00319 if (opcode->opcode != code)
00320 continue;
00321 if ((opcode->format & OP_PAGE_MASK) != format)
00322 continue;
00323
00324 if (opcode->format & M6812_OP_REG)
00325 {
00326 int j;
00327 int is_jump;
00328
00329 if (opcode->format & M6811_OP_JUMP_REL)
00330 is_jump = 1;
00331 else
00332 is_jump = 0;
00333
00334 status = read_memory (memaddr + pos, &buffer[0], 1, info);
00335 if (status != 0)
00336 {
00337 return status;
00338 }
00339 for (j = 0; i + j < m68hc11_num_opcodes; j++)
00340 {
00341 if ((opcode[j].arch & arch) == 0)
00342 continue;
00343 if (opcode[j].opcode != code)
00344 continue;
00345 if (is_jump)
00346 {
00347 if (!(opcode[j].format & M6811_OP_JUMP_REL))
00348 continue;
00349
00350 if ((opcode[j].format & M6812_OP_IBCC_MARKER)
00351 && (buffer[0] & 0xc0) != 0x80)
00352 continue;
00353 if ((opcode[j].format & M6812_OP_TBCC_MARKER)
00354 && (buffer[0] & 0xc0) != 0x40)
00355 continue;
00356 if ((opcode[j].format & M6812_OP_DBCC_MARKER)
00357 && (buffer[0] & 0xc0) != 0)
00358 continue;
00359 if ((opcode[j].format & M6812_OP_EQ_MARKER)
00360 && (buffer[0] & 0x20) == 0)
00361 break;
00362 if (!(opcode[j].format & M6812_OP_EQ_MARKER)
00363 && (buffer[0] & 0x20) != 0)
00364 break;
00365 continue;
00366 }
00367 if (opcode[j].format & M6812_OP_EXG_MARKER && buffer[0] & 0x80)
00368 break;
00369 if ((opcode[j].format & M6812_OP_SEX_MARKER)
00370 && (((buffer[0] & 0x07) >= 3 && (buffer[0] & 7) <= 7))
00371 && ((buffer[0] & 0x0f0) <= 0x20))
00372 break;
00373 if (opcode[j].format & M6812_OP_TFR_MARKER
00374 && !(buffer[0] & 0x80))
00375 break;
00376 }
00377 if (i + j < m68hc11_num_opcodes)
00378 opcode = &opcode[j];
00379 }
00380
00381
00382 (*info->fprintf_func) (info->stream, "%s", opcode->name);
00383
00384 format = opcode->format;
00385 if (format & (M6811_OP_MASK | M6811_OP_BITMASK
00386 | M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
00387 {
00388 (*info->fprintf_func) (info->stream, "\t");
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 offset = ((format & M6812_OP_IDX_P2)
00418 && (format & (M6811_OP_IMM8 | M6811_OP_IMM16 |
00419 M6811_OP_IND16)));
00420
00421
00422
00423 if (format &
00424 (M6811_OP_IMM8 | M6811_OP_IX | M6811_OP_IY | M6811_OP_DIRECT))
00425 {
00426 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info);
00427 if (status != 0)
00428 {
00429 return status;
00430 }
00431
00432 pos++;
00433
00434
00435 offset = -offset;
00436
00437 pc_dst_offset = 2;
00438 if (format & M6811_OP_IMM8)
00439 {
00440 (*info->fprintf_func) (info->stream, "#%d", (int) buffer[0]);
00441 format &= ~M6811_OP_IMM8;
00442
00443 pc_dst_offset = 1;
00444 }
00445 else if (format & M6811_OP_IX)
00446 {
00447
00448 (*info->fprintf_func) (info->stream, "%u,x", buffer[0] & 0x0FF);
00449 format &= ~M6811_OP_IX;
00450 }
00451 else if (format & M6811_OP_IY)
00452 {
00453 (*info->fprintf_func) (info->stream, "%u,y", buffer[0] & 0x0FF);
00454 format &= ~M6811_OP_IY;
00455 }
00456 else if (format & M6811_OP_DIRECT)
00457 {
00458 (*info->fprintf_func) (info->stream, "*");
00459 (*info->print_address_func) (buffer[0] & 0x0FF, info);
00460 format &= ~M6811_OP_DIRECT;
00461 }
00462 }
00463
00464 #define M6812_DST_MOVE (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)
00465 #define M6812_INDEXED_FLAGS (M6812_OP_IDX|M6812_OP_IDX_1|M6812_OP_IDX_2)
00466
00467 if (format & M6812_INDEXED_FLAGS)
00468 {
00469 int indirect;
00470 bfd_vma endaddr;
00471
00472 endaddr = memaddr + pos + 1;
00473 if (format & M6811_OP_IND16)
00474 endaddr += 2;
00475 pc_src_offset = -1;
00476 pc_dst_offset = 1;
00477 status = print_indexed_operand (memaddr + pos, info, &indirect,
00478 (format & M6812_DST_MOVE),
00479 pc_src_offset, endaddr);
00480 if (status < 0)
00481 {
00482 return status;
00483 }
00484 pos += status;
00485
00486
00487
00488 if ((format & M6812_OP_PAGE) && indirect)
00489 format &= ~M6812_OP_PAGE;
00490 }
00491
00492
00493 if ((format & M6812_OP_REG) && (format & M6811_OP_JUMP_REL))
00494 {
00495 status = read_memory (memaddr + pos, &buffer[0], 2, info);
00496 if (status != 0)
00497 {
00498 return status;
00499 }
00500 (*info->fprintf_func) (info->stream, "%s,",
00501 reg_src_table[buffer[0] & 0x07]);
00502 sval = buffer[1] & 0x0ff;
00503 if (buffer[0] & 0x10)
00504 sval |= 0xff00;
00505
00506 pos += 2;
00507 (*info->print_address_func) (memaddr + pos + sval, info);
00508 format &= ~(M6812_OP_REG | M6811_OP_JUMP_REL);
00509 }
00510 else if (format & (M6812_OP_REG | M6812_OP_REG_2))
00511 {
00512 status = read_memory (memaddr + pos, &buffer[0], 1, info);
00513 if (status != 0)
00514 {
00515 return status;
00516 }
00517
00518 pos++;
00519 (*info->fprintf_func) (info->stream, "%s,%s",
00520 reg_src_table[(buffer[0] >> 4) & 7],
00521 reg_dst_table[(buffer[0] & 7)]);
00522 }
00523
00524 if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
00525 {
00526 int val;
00527 bfd_vma addr;
00528 unsigned page = 0;
00529
00530 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info);
00531 if (status != 0)
00532 {
00533 return status;
00534 }
00535 if (format & M6812_OP_IDX_P2)
00536 offset = -2;
00537 else
00538 offset = 0;
00539 pos += 2;
00540
00541 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
00542 val &= 0x0FFFF;
00543 addr = val;
00544 pc_dst_offset = 2;
00545 if (format & M6812_OP_PAGE)
00546 {
00547 status = read_memory (memaddr + pos + offset, buffer, 1, info);
00548 if (status != 0)
00549 return status;
00550
00551 page = (unsigned) buffer[0];
00552 if (addr >= M68HC12_BANK_BASE && addr < 0x0c000)
00553 addr = ((val - M68HC12_BANK_BASE)
00554 | (page << M68HC12_BANK_SHIFT))
00555 + M68HC12_BANK_VIRT;
00556 }
00557 else if ((arch & cpu6812)
00558 && addr >= M68HC12_BANK_BASE && addr < 0x0c000)
00559 {
00560 int cur_page;
00561 bfd_vma vaddr;
00562
00563 if (memaddr >= M68HC12_BANK_VIRT)
00564 cur_page = ((memaddr - M68HC12_BANK_VIRT)
00565 >> M68HC12_BANK_SHIFT);
00566 else
00567 cur_page = 0;
00568
00569 vaddr = ((addr - M68HC12_BANK_BASE)
00570 + (cur_page << M68HC12_BANK_SHIFT))
00571 + M68HC12_BANK_VIRT;
00572 if (!info->symbol_at_address_func (addr, info)
00573 && info->symbol_at_address_func (vaddr, info))
00574 addr = vaddr;
00575 }
00576 if (format & M6811_OP_IMM16)
00577 {
00578 format &= ~M6811_OP_IMM16;
00579 (*info->fprintf_func) (info->stream, "#");
00580 }
00581 else
00582 format &= ~M6811_OP_IND16;
00583
00584 (*info->print_address_func) (addr, info);
00585 if (format & M6812_OP_PAGE)
00586 {
00587 (* info->fprintf_func) (info->stream, " {");
00588 (* info->print_address_func) (val, info);
00589 (* info->fprintf_func) (info->stream, ", %d}", page);
00590 format &= ~M6812_OP_PAGE;
00591 pos += 1;
00592 }
00593 }
00594
00595 if (format & M6812_OP_IDX_P2)
00596 {
00597 (*info->fprintf_func) (info->stream, ", ");
00598 status = print_indexed_operand (memaddr + pos + offset, info,
00599 0, 1, pc_dst_offset,
00600 memaddr + pos + offset + 1);
00601 if (status < 0)
00602 return status;
00603 pos += status;
00604 }
00605
00606 if (format & M6812_OP_IND16_P2)
00607 {
00608 int val;
00609
00610 (*info->fprintf_func) (info->stream, ", ");
00611
00612 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info);
00613 if (status != 0)
00614 {
00615 return status;
00616 }
00617 pos += 2;
00618
00619 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
00620 val &= 0x0FFFF;
00621 (*info->print_address_func) (val, info);
00622 }
00623
00624
00625
00626
00627 if (format & M6811_OP_BITMASK)
00628 {
00629 status = read_memory (memaddr + pos, &buffer[0], 1, info);
00630 if (status != 0)
00631 {
00632 return status;
00633 }
00634 pos++;
00635 (*info->fprintf_func) (info->stream, " #$%02x%s",
00636 buffer[0] & 0x0FF,
00637 (format & M6811_OP_JUMP_REL ? " " : ""));
00638 format &= ~M6811_OP_BITMASK;
00639 }
00640 if (format & M6811_OP_JUMP_REL)
00641 {
00642 int val;
00643
00644 status = read_memory (memaddr + pos, &buffer[0], 1, info);
00645 if (status != 0)
00646 {
00647 return status;
00648 }
00649
00650 pos++;
00651 val = (buffer[0] & 0x80) ? buffer[0] | 0xFFFFFF00 : buffer[0];
00652 (*info->print_address_func) (memaddr + pos + val, info);
00653 format &= ~M6811_OP_JUMP_REL;
00654 }
00655 else if (format & M6812_OP_JUMP_REL16)
00656 {
00657 int val;
00658
00659 status = read_memory (memaddr + pos, &buffer[0], 2, info);
00660 if (status != 0)
00661 {
00662 return status;
00663 }
00664
00665 pos += 2;
00666 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF));
00667 if (val & 0x8000)
00668 val |= 0xffff0000;
00669
00670 (*info->print_address_func) (memaddr + pos + val, info);
00671 format &= ~M6812_OP_JUMP_REL16;
00672 }
00673
00674 if (format & M6812_OP_PAGE)
00675 {
00676 int val;
00677
00678 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info);
00679 if (status != 0)
00680 {
00681 return status;
00682 }
00683 pos += 1;
00684
00685 val = buffer[0] & 0x0ff;
00686 (*info->fprintf_func) (info->stream, ", %d", val);
00687 }
00688
00689 #ifdef DEBUG
00690
00691
00692
00693 if (format & ~(M6811_OP_PAGE4 | M6811_OP_PAGE3 | M6811_OP_PAGE2))
00694 {
00695 (*info->fprintf_func) (info->stream, "; Error, format: %x", format);
00696 }
00697 if (pos != opcode->size)
00698 {
00699 (*info->fprintf_func) (info->stream, "; Error, size: %d expect %d",
00700 pos, opcode->size);
00701 }
00702 #endif
00703 return pos;
00704 }
00705
00706
00707 if (format == M6811_OP_PAGE2 && arch & cpu6812
00708 && ((code >= 0x30 && code <= 0x39) || (code >= 0x40)))
00709 (*info->fprintf_func) (info->stream, "trap\t#%d", code & 0x0ff);
00710
00711 else if (format == M6811_OP_PAGE2)
00712 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
00713 M6811_OPCODE_PAGE2, code);
00714 else if (format == M6811_OP_PAGE3)
00715 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
00716 M6811_OPCODE_PAGE3, code);
00717 else if (format == M6811_OP_PAGE4)
00718 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x",
00719 M6811_OPCODE_PAGE4, code);
00720 else
00721 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", code);
00722
00723 return pos;
00724 }
00725
00726
00727
00728 int
00729 print_insn_m68hc11 (bfd_vma memaddr, struct disassemble_info* info)
00730 {
00731 return print_insn (memaddr, info, cpu6811);
00732 }
00733
00734 int
00735 print_insn_m68hc12 (bfd_vma memaddr, struct disassemble_info* info)
00736 {
00737 return print_insn (memaddr, info, cpu6812);
00738 }