1/* m68hc11-dis.c -- Motorola 68HC11 & 68HC12 disassembly 2 Copyright 1999, 2000, 2001, 2002, 2003, 2006, 2007 3 Free Software Foundation, Inc. 4 Written by Stephane Carrez (stcarrez@nerim.fr) 5 6 This file is part of the GNU opcodes library. 7 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. 12 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. */ 22 23#include <stdio.h> 24 25#include "ansidecl.h" 26#include "opcode/m68hc11.h" 27#include "dis-asm.h" 28 29#define PC_REGNUM 3 30 31static const char *const reg_name[] = { 32 "X", "Y", "SP", "PC" 33}; 34 35static const char *const reg_src_table[] = { 36 "A", "B", "CCR", "TMP3", "D", "X", "Y", "SP" 37}; 38 39static const char *const reg_dst_table[] = { 40 "A", "B", "CCR", "TMP2", "D", "X", "Y", "SP" 41}; 42 43#define OP_PAGE_MASK (M6811_OP_PAGE2|M6811_OP_PAGE3|M6811_OP_PAGE4) 44 45/* Prototypes for local functions. */ 46static int read_memory (bfd_vma, bfd_byte *, int, struct disassemble_info *); 47static int print_indexed_operand (bfd_vma, struct disassemble_info *, 48 int*, int, int, bfd_vma); 49static int print_insn (bfd_vma, struct disassemble_info *, int); 50 51static int 52read_memory (bfd_vma memaddr, bfd_byte* buffer, int size, 53 struct disassemble_info* info) 54{ 55 int status; 56 57 /* Get first byte. Only one at a time because we don't know the 58 size of the insn. */ 59 status = (*info->read_memory_func) (memaddr, buffer, size, info); 60 if (status != 0) 61 { 62 (*info->memory_error_func) (status, memaddr, info); 63 return -1; 64 } 65 return 0; 66} 67 68 69/* Read the 68HC12 indexed operand byte and print the corresponding mode. 70 Returns the number of bytes read or -1 if failure. */ 71static int 72print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info, 73 int* indirect, int mov_insn, int pc_offset, 74 bfd_vma endaddr) 75{ 76 bfd_byte buffer[4]; 77 int reg; 78 int status; 79 short sval; 80 int pos = 1; 81 82 if (indirect) 83 *indirect = 0; 84 85 status = read_memory (memaddr, &buffer[0], 1, info); 86 if (status != 0) 87 { 88 return status; 89 } 90 91 /* n,r with 5-bits signed constant. */ 92 if ((buffer[0] & 0x20) == 0) 93 { 94 reg = (buffer[0] >> 6) & 3; 95 sval = (buffer[0] & 0x1f); 96 if (sval & 0x10) 97 sval |= 0xfff0; 98 /* 68HC12 requires an adjustment for movb/movw pc relative modes. */ 99 if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn) 100 sval += pc_offset; 101 (*info->fprintf_func) (info->stream, "%d,%s", 102 (int) sval, reg_name[reg]); 103 104 if (reg == PC_REGNUM) 105 { 106 (* info->fprintf_func) (info->stream, " {"); 107 (* info->print_address_func) (endaddr + sval, info); 108 (* info->fprintf_func) (info->stream, "}"); 109 } 110 } 111 112 /* Auto pre/post increment/decrement. */ 113 else if ((buffer[0] & 0xc0) != 0xc0) 114 { 115 const char *mode; 116 117 reg = (buffer[0] >> 6) & 3; 118 sval = (buffer[0] & 0x0f); 119 if (sval & 0x8) 120 { 121 sval |= 0xfff0; 122 sval = -sval; 123 mode = "-"; 124 } 125 else 126 { 127 sval = sval + 1; 128 mode = "+"; 129 } 130 (*info->fprintf_func) (info->stream, "%d,%s%s%s", 131 (int) sval, 132 (buffer[0] & 0x10 ? "" : mode), 133 reg_name[reg], (buffer[0] & 0x10 ? mode : "")); 134 } 135 136 /* [n,r] 16-bits offset indexed indirect. */ 137 else if ((buffer[0] & 0x07) == 3) 138 { 139 if (mov_insn) 140 { 141 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>", 142 buffer[0] & 0x0ff); 143 return 0; 144 } 145 reg = (buffer[0] >> 3) & 0x03; 146 status = read_memory (memaddr + pos, &buffer[0], 2, info); 147 if (status != 0) 148 { 149 return status; 150 } 151 152 pos += 2; 153 sval = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); 154 (*info->fprintf_func) (info->stream, "[%u,%s]", 155 sval & 0x0ffff, reg_name[reg]); 156 if (indirect) 157 *indirect = 1; 158 } 159 160 /* n,r with 9 and 16 bit signed constant. */ 161 else if ((buffer[0] & 0x4) == 0) 162 { 163 if (mov_insn) 164 { 165 (*info->fprintf_func) (info->stream, "<invalid op: 0x%x>", 166 buffer[0] & 0x0ff); 167 return 0; 168 } 169 reg = (buffer[0] >> 3) & 0x03; 170 status = read_memory (memaddr + pos, 171 &buffer[1], (buffer[0] & 0x2 ? 2 : 1), info); 172 if (status != 0) 173 { 174 return status; 175 } 176 if (buffer[0] & 2) 177 { 178 sval = ((buffer[1] << 8) | (buffer[2] & 0x0FF)); 179 sval &= 0x0FFFF; 180 pos += 2; 181 endaddr += 2; 182 } 183 else 184 { 185 sval = buffer[1] & 0x00ff; 186 if (buffer[0] & 0x01) 187 sval |= 0xff00; 188 pos++; 189 endaddr++; 190 } 191 (*info->fprintf_func) (info->stream, "%d,%s", 192 (int) sval, reg_name[reg]); 193 if (reg == PC_REGNUM) 194 { 195 (* info->fprintf_func) (info->stream, " {"); 196 (* info->print_address_func) (endaddr + sval, info); 197 (* info->fprintf_func) (info->stream, "}"); 198 } 199 } 200 else 201 { 202 reg = (buffer[0] >> 3) & 0x03; 203 switch (buffer[0] & 3) 204 { 205 case 0: 206 (*info->fprintf_func) (info->stream, "A,%s", reg_name[reg]); 207 break; 208 case 1: 209 (*info->fprintf_func) (info->stream, "B,%s", reg_name[reg]); 210 break; 211 case 2: 212 (*info->fprintf_func) (info->stream, "D,%s", reg_name[reg]); 213 break; 214 case 3: 215 default: 216 (*info->fprintf_func) (info->stream, "[D,%s]", reg_name[reg]); 217 if (indirect) 218 *indirect = 1; 219 break; 220 } 221 } 222 223 return pos; 224} 225 226/* Disassemble one instruction at address 'memaddr'. Returns the number 227 of bytes used by that instruction. */ 228static int 229print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch) 230{ 231 int status; 232 bfd_byte buffer[4]; 233 unsigned char code; 234 long format, pos, i; 235 short sval; 236 const struct m68hc11_opcode *opcode; 237 238 /* Get first byte. Only one at a time because we don't know the 239 size of the insn. */ 240 status = read_memory (memaddr, buffer, 1, info); 241 if (status != 0) 242 { 243 return status; 244 } 245 246 format = 0; 247 code = buffer[0]; 248 pos = 0; 249 250 /* Look for page2,3,4 opcodes. */ 251 if (code == M6811_OPCODE_PAGE2) 252 { 253 pos++; 254 format = M6811_OP_PAGE2; 255 } 256 else if (code == M6811_OPCODE_PAGE3 && arch == cpu6811) 257 { 258 pos++; 259 format = M6811_OP_PAGE3; 260 } 261 else if (code == M6811_OPCODE_PAGE4 && arch == cpu6811) 262 { 263 pos++; 264 format = M6811_OP_PAGE4; 265 } 266 267 /* We are in page2,3,4; get the real opcode. */ 268 if (pos == 1) 269 { 270 status = read_memory (memaddr + pos, &buffer[1], 1, info); 271 if (status != 0) 272 { 273 return status; 274 } 275 code = buffer[1]; 276 } 277 278 279 /* Look first for a 68HC12 alias. All of them are 2-bytes long and 280 in page 1. There is no operand to print. We read the second byte 281 only when we have a possible match. */ 282 if ((arch & cpu6812) && format == 0) 283 { 284 int must_read = 1; 285 286 /* Walk the alias table to find a code1+code2 match. */ 287 for (i = 0; i < m68hc12_num_alias; i++) 288 { 289 if (m68hc12_alias[i].code1 == code) 290 { 291 if (must_read) 292 { 293 status = read_memory (memaddr + pos + 1, 294 &buffer[1], 1, info); 295 if (status != 0) 296 break; 297 298 must_read = 1; 299 } 300 if (m68hc12_alias[i].code2 == (unsigned char) buffer[1]) 301 { 302 (*info->fprintf_func) (info->stream, "%s", 303 m68hc12_alias[i].name); 304 return 2; 305 } 306 } 307 } 308 } 309 310 pos++; 311 312 /* Scan the opcode table until we find the opcode 313 with the corresponding page. */ 314 opcode = m68hc11_opcodes; 315 for (i = 0; i < m68hc11_num_opcodes; i++, opcode++) 316 { 317 int offset; 318 int pc_src_offset; 319 int pc_dst_offset = 0; 320 321 if ((opcode->arch & arch) == 0) 322 continue; 323 if (opcode->opcode != code) 324 continue; 325 if ((opcode->format & OP_PAGE_MASK) != format) 326 continue; 327 328 if (opcode->format & M6812_OP_REG) 329 { 330 int j; 331 int is_jump; 332 333 if (opcode->format & M6811_OP_JUMP_REL) 334 is_jump = 1; 335 else 336 is_jump = 0; 337 338 status = read_memory (memaddr + pos, &buffer[0], 1, info); 339 if (status != 0) 340 { 341 return status; 342 } 343 for (j = 0; i + j < m68hc11_num_opcodes; j++) 344 { 345 if ((opcode[j].arch & arch) == 0) 346 continue; 347 if (opcode[j].opcode != code) 348 continue; 349 if (is_jump) 350 { 351 if (!(opcode[j].format & M6811_OP_JUMP_REL)) 352 continue; 353 354 if ((opcode[j].format & M6812_OP_IBCC_MARKER) 355 && (buffer[0] & 0xc0) != 0x80) 356 continue; 357 if ((opcode[j].format & M6812_OP_TBCC_MARKER) 358 && (buffer[0] & 0xc0) != 0x40) 359 continue; 360 if ((opcode[j].format & M6812_OP_DBCC_MARKER) 361 && (buffer[0] & 0xc0) != 0) 362 continue; 363 if ((opcode[j].format & M6812_OP_EQ_MARKER) 364 && (buffer[0] & 0x20) == 0) 365 break; 366 if (!(opcode[j].format & M6812_OP_EQ_MARKER) 367 && (buffer[0] & 0x20) != 0) 368 break; 369 continue; 370 } 371 if (opcode[j].format & M6812_OP_EXG_MARKER && buffer[0] & 0x80) 372 break; 373 if ((opcode[j].format & M6812_OP_SEX_MARKER) 374 && (((buffer[0] & 0x07) >= 3 && (buffer[0] & 7) <= 7)) 375 && ((buffer[0] & 0x0f0) <= 0x20)) 376 break; 377 if (opcode[j].format & M6812_OP_TFR_MARKER 378 && !(buffer[0] & 0x80)) 379 break; 380 } 381 if (i + j < m68hc11_num_opcodes) 382 opcode = &opcode[j]; 383 } 384 385 /* We have found the opcode. Extract the operand and print it. */ 386 (*info->fprintf_func) (info->stream, "%s", opcode->name); 387 388 format = opcode->format; 389 if (format & (M6811_OP_MASK | M6811_OP_BITMASK 390 | M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) 391 { 392 (*info->fprintf_func) (info->stream, "\t"); 393 } 394 395 /* The movb and movw must be handled in a special way... 396 The source constant 'ii' is not always at the same place. 397 This is the same for the destination for the post-indexed byte. 398 The 'offset' is used to do the appropriate correction. 399 400 offset offset 401 for constant for destination 402 movb 18 OB ii hh ll 0 0 403 18 08 xb ii 1 -1 404 18 0C hh ll hh ll 0 0 405 18 09 xb hh ll 1 -1 406 18 0D xb hh ll 0 0 407 18 0A xb xb 0 0 408 409 movw 18 03 jj kk hh ll 0 0 410 18 00 xb jj kk 1 -1 411 18 04 hh ll hh ll 0 0 412 18 01 xb hh ll 1 -1 413 18 05 xb hh ll 0 0 414 18 02 xb xb 0 0 415 416 After the source operand is read, the position 'pos' is incremented 417 this explains the negative offset for destination. 418 419 movb/movw above are the only instructions with this matching 420 format. */ 421 offset = ((format & M6812_OP_IDX_P2) 422 && (format & (M6811_OP_IMM8 | M6811_OP_IMM16 | 423 M6811_OP_IND16))); 424 425 /* Operand with one more byte: - immediate, offset, 426 direct-low address. */ 427 if (format & 428 (M6811_OP_IMM8 | M6811_OP_IX | M6811_OP_IY | M6811_OP_DIRECT)) 429 { 430 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info); 431 if (status != 0) 432 { 433 return status; 434 } 435 436 pos++; 437 438 /* This movb/movw is special (see above). */ 439 offset = -offset; 440 441 pc_dst_offset = 2; 442 if (format & M6811_OP_IMM8) 443 { 444 (*info->fprintf_func) (info->stream, "#%d", (int) buffer[0]); 445 format &= ~M6811_OP_IMM8; 446 /* Set PC destination offset. */ 447 pc_dst_offset = 1; 448 } 449 else if (format & M6811_OP_IX) 450 { 451 /* Offsets are in range 0..255, print them unsigned. */ 452 (*info->fprintf_func) (info->stream, "%u,x", buffer[0] & 0x0FF); 453 format &= ~M6811_OP_IX; 454 } 455 else if (format & M6811_OP_IY) 456 { 457 (*info->fprintf_func) (info->stream, "%u,y", buffer[0] & 0x0FF); 458 format &= ~M6811_OP_IY; 459 } 460 else if (format & M6811_OP_DIRECT) 461 { 462 (*info->fprintf_func) (info->stream, "*"); 463 (*info->print_address_func) (buffer[0] & 0x0FF, info); 464 format &= ~M6811_OP_DIRECT; 465 } 466 } 467 468#define M6812_DST_MOVE (M6812_OP_IND16_P2 | M6812_OP_IDX_P2) 469#define M6812_INDEXED_FLAGS (M6812_OP_IDX|M6812_OP_IDX_1|M6812_OP_IDX_2) 470 /* Analyze the 68HC12 indexed byte. */ 471 if (format & M6812_INDEXED_FLAGS) 472 { 473 int indirect; 474 bfd_vma endaddr; 475 476 endaddr = memaddr + pos + 1; 477 if (format & M6811_OP_IND16) 478 endaddr += 2; 479 pc_src_offset = -1; 480 pc_dst_offset = 1; 481 status = print_indexed_operand (memaddr + pos, info, &indirect, 482 (format & M6812_DST_MOVE), 483 pc_src_offset, endaddr); 484 if (status < 0) 485 { 486 return status; 487 } 488 pos += status; 489 490 /* The indirect addressing mode of the call instruction does 491 not need the page code. */ 492 if ((format & M6812_OP_PAGE) && indirect) 493 format &= ~M6812_OP_PAGE; 494 } 495 496 /* 68HC12 dbcc/ibcc/tbcc operands. */ 497 if ((format & M6812_OP_REG) && (format & M6811_OP_JUMP_REL)) 498 { 499 status = read_memory (memaddr + pos, &buffer[0], 2, info); 500 if (status != 0) 501 { 502 return status; 503 } 504 (*info->fprintf_func) (info->stream, "%s,", 505 reg_src_table[buffer[0] & 0x07]); 506 sval = buffer[1] & 0x0ff; 507 if (buffer[0] & 0x10) 508 sval |= 0xff00; 509 510 pos += 2; 511 (*info->print_address_func) (memaddr + pos + sval, info); 512 format &= ~(M6812_OP_REG | M6811_OP_JUMP_REL); 513 } 514 else if (format & (M6812_OP_REG | M6812_OP_REG_2)) 515 { 516 status = read_memory (memaddr + pos, &buffer[0], 1, info); 517 if (status != 0) 518 { 519 return status; 520 } 521 522 pos++; 523 (*info->fprintf_func) (info->stream, "%s,%s", 524 reg_src_table[(buffer[0] >> 4) & 7], 525 reg_dst_table[(buffer[0] & 7)]); 526 } 527 528 if (format & (M6811_OP_IMM16 | M6811_OP_IND16)) 529 { 530 int val; 531 bfd_vma addr; 532 unsigned page = 0; 533 534 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info); 535 if (status != 0) 536 { 537 return status; 538 } 539 if (format & M6812_OP_IDX_P2) 540 offset = -2; 541 else 542 offset = 0; 543 pos += 2; 544 545 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); 546 val &= 0x0FFFF; 547 addr = val; 548 pc_dst_offset = 2; 549 if (format & M6812_OP_PAGE) 550 { 551 status = read_memory (memaddr + pos + offset, buffer, 1, info); 552 if (status != 0) 553 return status; 554 555 page = (unsigned) buffer[0]; 556 if (addr >= M68HC12_BANK_BASE && addr < 0x0c000) 557 addr = ((val - M68HC12_BANK_BASE) 558 | (page << M68HC12_BANK_SHIFT)) 559 + M68HC12_BANK_VIRT; 560 } 561 else if ((arch & cpu6812) 562 && addr >= M68HC12_BANK_BASE && addr < 0x0c000) 563 { 564 int cur_page; 565 bfd_vma vaddr; 566 567 if (memaddr >= M68HC12_BANK_VIRT) 568 cur_page = ((memaddr - M68HC12_BANK_VIRT) 569 >> M68HC12_BANK_SHIFT); 570 else 571 cur_page = 0; 572 573 vaddr = ((addr - M68HC12_BANK_BASE) 574 + (cur_page << M68HC12_BANK_SHIFT)) 575 + M68HC12_BANK_VIRT; 576 if (!info->symbol_at_address_func (addr, info) 577 && info->symbol_at_address_func (vaddr, info)) 578 addr = vaddr; 579 } 580 if (format & M6811_OP_IMM16) 581 { 582 format &= ~M6811_OP_IMM16; 583 (*info->fprintf_func) (info->stream, "#"); 584 } 585 else 586 format &= ~M6811_OP_IND16; 587 588 (*info->print_address_func) (addr, info); 589 if (format & M6812_OP_PAGE) 590 { 591 (* info->fprintf_func) (info->stream, " {"); 592 (* info->print_address_func) (val, info); 593 (* info->fprintf_func) (info->stream, ", %d}", page); 594 format &= ~M6812_OP_PAGE; 595 pos += 1; 596 } 597 } 598 599 if (format & M6812_OP_IDX_P2) 600 { 601 (*info->fprintf_func) (info->stream, ", "); 602 status = print_indexed_operand (memaddr + pos + offset, info, 603 0, 1, pc_dst_offset, 604 memaddr + pos + offset + 1); 605 if (status < 0) 606 return status; 607 pos += status; 608 } 609 610 if (format & M6812_OP_IND16_P2) 611 { 612 int val; 613 614 (*info->fprintf_func) (info->stream, ", "); 615 616 status = read_memory (memaddr + pos + offset, &buffer[0], 2, info); 617 if (status != 0) 618 { 619 return status; 620 } 621 pos += 2; 622 623 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); 624 val &= 0x0FFFF; 625 (*info->print_address_func) (val, info); 626 } 627 628 /* M6811_OP_BITMASK and M6811_OP_JUMP_REL must be treated separately 629 and in that order. The brset/brclr insn have a bitmask and then 630 a relative branch offset. */ 631 if (format & M6811_OP_BITMASK) 632 { 633 status = read_memory (memaddr + pos, &buffer[0], 1, info); 634 if (status != 0) 635 { 636 return status; 637 } 638 pos++; 639 (*info->fprintf_func) (info->stream, " #$%02x%s", 640 buffer[0] & 0x0FF, 641 (format & M6811_OP_JUMP_REL ? " " : "")); 642 format &= ~M6811_OP_BITMASK; 643 } 644 if (format & M6811_OP_JUMP_REL) 645 { 646 int val; 647 648 status = read_memory (memaddr + pos, &buffer[0], 1, info); 649 if (status != 0) 650 { 651 return status; 652 } 653 654 pos++; 655 val = (buffer[0] & 0x80) ? buffer[0] | 0xFFFFFF00 : buffer[0]; 656 (*info->print_address_func) (memaddr + pos + val, info); 657 format &= ~M6811_OP_JUMP_REL; 658 } 659 else if (format & M6812_OP_JUMP_REL16) 660 { 661 int val; 662 663 status = read_memory (memaddr + pos, &buffer[0], 2, info); 664 if (status != 0) 665 { 666 return status; 667 } 668 669 pos += 2; 670 val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); 671 if (val & 0x8000) 672 val |= 0xffff0000; 673 674 (*info->print_address_func) (memaddr + pos + val, info); 675 format &= ~M6812_OP_JUMP_REL16; 676 } 677 678 if (format & M6812_OP_PAGE) 679 { 680 int val; 681 682 status = read_memory (memaddr + pos + offset, &buffer[0], 1, info); 683 if (status != 0) 684 { 685 return status; 686 } 687 pos += 1; 688 689 val = buffer[0] & 0x0ff; 690 (*info->fprintf_func) (info->stream, ", %d", val); 691 } 692 693#ifdef DEBUG 694 /* Consistency check. 'format' must be 0, so that we have handled 695 all formats; and the computed size of the insn must match the 696 opcode table content. */ 697 if (format & ~(M6811_OP_PAGE4 | M6811_OP_PAGE3 | M6811_OP_PAGE2)) 698 { 699 (*info->fprintf_func) (info->stream, "; Error, format: %lx", format); 700 } 701 if (pos != opcode->size) 702 { 703 (*info->fprintf_func) (info->stream, "; Error, size: %ld expect %d", 704 pos, opcode->size); 705 } 706#endif 707 return pos; 708 } 709 710 /* Opcode not recognized. */ 711 if (format == M6811_OP_PAGE2 && arch & cpu6812 712 && ((code >= 0x30 && code <= 0x39) || (code >= 0x40))) 713 (*info->fprintf_func) (info->stream, "trap\t#%d", code & 0x0ff); 714 715 else if (format == M6811_OP_PAGE2) 716 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x", 717 M6811_OPCODE_PAGE2, code); 718 else if (format == M6811_OP_PAGE3) 719 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x", 720 M6811_OPCODE_PAGE3, code); 721 else if (format == M6811_OP_PAGE4) 722 (*info->fprintf_func) (info->stream, ".byte\t0x%02x, 0x%02x", 723 M6811_OPCODE_PAGE4, code); 724 else 725 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", code); 726 727 return pos; 728} 729 730/* Disassemble one instruction at address 'memaddr'. Returns the number 731 of bytes used by that instruction. */ 732int 733print_insn_m68hc11 (bfd_vma memaddr, struct disassemble_info* info) 734{ 735 return print_insn (memaddr, info, cpu6811); 736} 737 738int 739print_insn_m68hc12 (bfd_vma memaddr, struct disassemble_info* info) 740{ 741 return print_insn (memaddr, info, cpu6812); 742} 743