1/* $NetBSD: db_disasm.c,v 1.47 2023/09/26 14:33:55 tsutsui Exp $ */ 2 3/* 4 * Copyright (c) 1994 Christian E. Hopps 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christian E. Hopps. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32/* 33 * Notes: 34 * 35 * Much can be done with this format, with a lot of hacking even 36 * a moto emul. could be built. However things like symbol lookup 37 * and reference are needed right away. 38 * 39 * the only functions that use the "get_xxx()" notation should be 40 * ones that modify things in a dis_buffer_t besides the buffers. 41 * (namely the used field) 42 * 43 * An attempt has been made to *always* increment dbuf->used++ immediately 44 * after referencing a value beyond the current "short *" address. 45 * this meant either only referencing the value once or placing it in 46 * a local var. If you play with this keep this style. Its very useful 47 * in eliminating a very easy to make hard to find logic error. 48 * 49 * I broke style in 2 ways with one macro ``addchar()'' 50 * However it makes sense, consider that it is called *a lot* and 51 * commonly with things like ","'s 52 * 53 * *dbuf->casm++ = ','; || ADDCHAR(dbuf,','); || addchar(dbuf,','); 54 * I chose: 55 * addchar(','); 56 * 57 * If this is not enough to convince you, please load up you emacs or 58 * vi and do a fancy regex-replace, and compare for yourself. 59 * (The 2 rules of style I broke if you failed to notice are: 60 * 1: lower case macro name 2: implicit reference to local var name.) 61 * 62 * (chopps - March 1, 1994) 63 */ 64 65#include <sys/cdefs.h> 66__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.47 2023/09/26 14:33:55 tsutsui Exp $"); 67 68#include <sys/param.h> 69#ifdef _KERNEL 70#include <sys/systm.h> 71#endif 72 73#include <machine/db_machdep.h> 74 75#include <ddb/db_interface.h> 76#include <ddb/db_output.h> 77#include <ddb/db_sym.h> 78#include <m68k/m68k/db_disasm.h> 79 80static void get_modregstr(dis_buffer_t *, int, int, int, int); 81static void get_modregstr_moto(dis_buffer_t *, int, int, int, int); 82static void get_modregstr_mit(dis_buffer_t *, int, int, int, int); 83#if 0 84static u_long get_areg_val(int reg); 85#endif 86static void get_immed(dis_buffer_t *, int); 87static void get_fpustdGEN(dis_buffer_t *, u_short, const char *); 88static void addstr(dis_buffer_t *, const char *s); 89static void prints(dis_buffer_t *, int, int); 90static void printu(dis_buffer_t *, u_int, int); 91static void prints_wb(dis_buffer_t *, int, int, int); 92static void printu_wb(dis_buffer_t *, u_int, int, int); 93static void prints_bf(dis_buffer_t *, int, int, int); 94static void printu_bf(dis_buffer_t *, u_int, int, int); 95static void iaddstr(dis_buffer_t *, const char *s); 96#if 0 97static void iprints(dis_buffer_t *, int, int); 98#endif 99static void iprintu(dis_buffer_t *, u_int, int); 100#if 0 101static void iprints_wb(dis_buffer_t *, int, int, int); 102#endif 103static void iprintu_wb(dis_buffer_t *, u_int, int, int); 104static void make_cond(dis_buffer_t *, int , const char *); 105static void print_fcond(dis_buffer_t *, char); 106static void print_mcond(dis_buffer_t *, char); 107static void print_disp(dis_buffer_t *, int, int, int); 108static void print_addr(dis_buffer_t *, u_long); 109static void print_reglist(dis_buffer_t *, int, u_short); 110static void print_freglist(dis_buffer_t *, int, u_short, int); 111static void print_fcode(dis_buffer_t *, u_short); 112 113/* groups */ 114static void opcode_bitmanip(dis_buffer_t *, u_short); 115static void opcode_move(dis_buffer_t *, u_short); 116static void opcode_misc(dis_buffer_t *, u_short); 117static void opcode_branch(dis_buffer_t *, u_short); 118static void opcode_coproc(dis_buffer_t *, u_short); 119static void opcode_0101(dis_buffer_t *, u_short); 120static void opcode_1000(dis_buffer_t *, u_short); 121static void opcode_addsub(dis_buffer_t *, u_short); 122static void opcode_1010(dis_buffer_t *, u_short); 123static void opcode_1011(dis_buffer_t *, u_short); 124static void opcode_1100(dis_buffer_t *, u_short); 125static void opcode_1110(dis_buffer_t *, u_short); 126static void opcode_fpu(dis_buffer_t *, u_short); 127static void opcode_mmu(dis_buffer_t *, u_short); 128static void opcode_mmu040(dis_buffer_t *, u_short); 129static void opcode_move16(dis_buffer_t *, u_short); 130 131/* subs of groups */ 132static void opcode_movec(dis_buffer_t *, u_short); 133static void opcode_divmul(dis_buffer_t *, u_short); 134static void opcode_movem(dis_buffer_t *, u_short); 135static void opcode_fmove_ext(dis_buffer_t *, u_short, u_short); 136static void opcode_pmove(dis_buffer_t *, u_short, u_short); 137static void opcode_pflush(dis_buffer_t *, u_short, u_short); 138 139#define addchar(ch) (*dbuf->casm++ = ch) 140#define iaddchar(ch) (*dbuf->cinfo++ = ch) 141 142typedef void dis_func_t(dis_buffer_t *, u_short); 143 144static dis_func_t *const opcode_map[16] = { 145 opcode_bitmanip, opcode_move, opcode_move, opcode_move, 146 opcode_misc, opcode_0101, opcode_branch, opcode_move, 147 opcode_1000, opcode_addsub, opcode_1010, opcode_1011, 148 opcode_1100, opcode_addsub, opcode_1110, opcode_coproc 149}; 150 151static const char *const cc_table[16] = { 152 "t", "f", "hi", "ls", 153 "cc", "cs", "ne", "eq", 154 "vc", "vs", "pl", "mi", 155 "ge", "lt", "gt", "le" 156}; 157 158static const char *const fpcc_table[32] = { 159 "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", 160 "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", 161 "sf", "seq", "gt", "ge", "lt", "le", "gl", "gle", 162 "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st" }; 163 164static const char *const mmcc_table[16] = { 165 "bs", "bc", "ls", "lc", "ss", "sc", "as", "sc", 166 "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" }; 167 168 169static const char *const aregs[8] = {"a0","a1","a2","a3","a4","a5","a6","sp"}; 170static const char *const dregs[8] = {"d0","d1","d2","d3","d4","d5","d6","d7"}; 171static const char *const fpregs[8] = { 172 "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7" }; 173static const char *const fpcregs[3] = { "fpiar", "fpsr", "fpcr" }; 174#ifndef _KERNEL 175static const char hexdigits[] = "0123456789abcdef"; 176#endif 177 178/* 179 * Disassemble instruction at location ``loc''. 180 * Returns location of next instruction. 181 */ 182 183static char asm_buffer[256]; 184static char info_buffer[256]; 185 186db_addr_t 187db_disasm(db_addr_t loc, bool moto_syntax) 188{ 189 u_short opc; 190 dis_func_t *func; 191 dis_buffer_t dbuf; 192 193 dbuf.casm = dbuf.dasm = asm_buffer; 194 dbuf.cinfo = dbuf.info = info_buffer; 195 dbuf.used = 0; 196 dbuf.val = (short *)loc; 197 dbuf.mit = moto_syntax ? 0 : 1; 198 199 dbuf.dasm[0] = 0; 200 dbuf.info[0] = 0; 201 202 opc = *dbuf.val; 203 dbuf.used++; 204 205 func = opcode_map[OPCODE_MAP(opc)]; 206 func(&dbuf, opc); 207 208 db_printf("%s",asm_buffer); 209 if (info_buffer[0]) 210 db_printf("\t[%s]\n",info_buffer); 211 else 212 db_printf("\n"); 213 return loc + sizeof(short) * dbuf.used; 214} 215/* 216 * Bit manipulation/MOVEP/Immediate. 217 */ 218static void 219opcode_bitmanip(dis_buffer_t *dbuf, u_short opc) 220{ 221 const char *tmp; 222 u_short ext; 223 int sz; 224 225 tmp = NULL; 226 227 switch (opc) { 228 case ANDITOCCR_INST: 229 tmp = "andib\t"; 230 break; 231 case ANDIROSR_INST: 232 tmp = "andiw\t"; 233 break; 234 case EORITOCCR_INST: 235 tmp = "eorib\t"; 236 break; 237 case EORITOSR_INST: 238 tmp = "eoriw\t"; 239 break; 240 case ORITOCCR_INST: 241 tmp = "orib\t"; 242 break; 243 case ORITOSR_INST: 244 tmp = "oriw\t"; 245 break; 246 } 247 if (tmp) { 248 addstr(dbuf, tmp); 249 if (ISBITSET(opc,6)) { 250 get_immed(dbuf, SIZE_WORD); 251 addstr(dbuf, ",sr"); 252 } else { 253 get_immed(dbuf, SIZE_BYTE); 254 addstr(dbuf, ",ccr"); 255 } 256 return; 257 } 258 259 if (IS_INST(RTM,opc)) { 260 addstr(dbuf, "rtm\t"); 261 if (ISBITSET(opc,3)) 262 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 263 else 264 PRINT_DREG(dbuf, BITFIELD(opc,2,0)); 265 return; 266 } 267 268 if (IS_INST(MOVEP,opc)) { 269 addstr(dbuf, "movp"); 270 if (ISBITSET(opc,6)) 271 addchar('l'); 272 else 273 addchar('w'); 274 addchar('\t'); 275 if (ISBITSET(opc,7)) { 276 PRINT_DREG(dbuf, BITFIELD(opc, 11, 9)); 277 addchar(','); 278 } 279 PRINT_AREG(dbuf, BITFIELD(opc, 2, 0)); 280 addchar('@'); 281 addchar('('); 282 print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD, 283 BITFIELD(opc, 2, 0)); 284 dbuf->used++; 285 addchar(')'); 286 if (!ISBITSET(opc,7)) { 287 addchar(','); 288 PRINT_DREG(dbuf, BITFIELD(opc, 11, 9)); 289 } 290 return; 291 } 292 293 switch (opc & BCHGD_MASK) { 294 case BCHGD_INST: 295 tmp = "bchg\t"; 296 break; 297 case BCLRD_INST: 298 tmp = "bclr\t"; 299 break; 300 case BSETD_INST: 301 tmp = "bset\t"; 302 break; 303 case BTSTD_INST: 304 tmp = "btst\t"; 305 break; 306 } 307 if (tmp) { 308 addstr(dbuf, tmp); 309 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 310 addchar(','); 311 get_modregstr(dbuf,5,GETMOD_BEFORE,0,0); 312 return; 313 } 314 315 switch (opc & BCHGS_MASK) { 316 case BCHGS_INST: 317 tmp = "bchg\t"; 318 break; 319 case BCLRS_INST: 320 tmp = "bclr\t"; 321 break; 322 case BSETS_INST: 323 tmp = "bset\t"; 324 break; 325 case BTSTS_INST: 326 tmp = "btst\t"; 327 break; 328 } 329 if (tmp) { 330 addstr(dbuf, tmp); 331 get_immed(dbuf, SIZE_BYTE); 332 addchar(','); 333 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); 334 return; 335 } 336 337 if (IS_INST(CAS2,opc)) { 338 u_short ext2; 339 340 ext = *(dbuf->val + 1); 341 ext2 = *(dbuf->val + 2); 342 dbuf->used += 2; 343 344 if (ISBITSET(opc,9)) 345 addstr(dbuf, "cas2l\t"); 346 else 347 addstr(dbuf, "cas2w\t"); 348 349 PRINT_DREG(dbuf, BITFIELD(ext,2,0)); 350 addchar(':'); 351 PRINT_DREG(dbuf, BITFIELD(ext2,2,0)); 352 addchar(','); 353 354 PRINT_DREG(dbuf, BITFIELD(ext,8,6)); 355 addchar(':'); 356 PRINT_DREG(dbuf, BITFIELD(ext2,8,6)); 357 addchar(','); 358 359 if (ISBITSET(ext,15)) 360 PRINT_AREG(dbuf, BITFIELD(ext,14,12)); 361 else 362 PRINT_DREG(dbuf, BITFIELD(ext,14,12)); 363 addchar('@'); 364 addchar(':'); 365 if (ISBITSET(ext2,15)) 366 PRINT_AREG(dbuf, BITFIELD(ext2,14,12)); 367 else 368 PRINT_DREG(dbuf, BITFIELD(ext2,14,12)); 369 addchar('@'); 370 return; 371 } 372 373 switch (opc & CAS_MASK) { 374 case CAS_INST: 375 ext = *(dbuf->val + 1); 376 dbuf->used++; 377 378 addstr(dbuf,"cas"); 379 sz = BITFIELD(opc,10,9); 380 if (sz == 0) { 381 sz = SIZE_BYTE; 382 addchar('b'); 383 } else if (sz == 1) { 384 sz = SIZE_WORD; 385 addchar('w'); 386 } else { 387 sz = SIZE_LONG; 388 addchar('l'); 389 } 390 addchar('\t'); 391 PRINT_DREG(dbuf, BITFIELD(ext, 2, 0)); 392 addchar(','); 393 PRINT_DREG(dbuf, BITFIELD(ext, 8, 6)); 394 addchar(','); 395 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 396 return; 397 case CHK2_INST: 398 /* case CMP2_INST: */ 399 ext = *(dbuf->val + 1); 400 dbuf->used++; 401 402 if (ISBITSET(ext,11)) 403 addstr(dbuf,"chk2"); 404 else 405 addstr(dbuf,"cmp2"); 406 407 sz = BITFIELD(opc,10,9); 408 if (sz == 0) { 409 sz = SIZE_BYTE; 410 addchar('b'); 411 } else if (sz == 1) { 412 sz = SIZE_WORD; 413 addchar('w'); 414 } else { 415 sz = SIZE_LONG; 416 addchar('l'); 417 } 418 addchar('\t'); 419 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 420 421 addchar(','); 422 if(ISBITSET(ext,15)) 423 PRINT_AREG(dbuf, BITFIELD(ext, 14, 12)); 424 else 425 PRINT_DREG(dbuf, BITFIELD(ext, 14, 12)); 426 return; 427 } 428 429 switch (ADDI_MASK & opc) { 430 case MOVES_INST: 431 addstr(dbuf, "movs"); 432 sz = BITFIELD(opc,7,6); 433 if (sz == 0) { 434 addchar('b'); 435 sz = SIZE_BYTE; 436 } else if (sz == 1) { 437 addchar('w'); 438 sz = SIZE_WORD; 439 } else { 440 addchar ('l'); 441 sz = SIZE_LONG; 442 } 443 addchar('\t'); 444 445 ext = *(dbuf->val + 1); 446 dbuf->used++; 447 448 if (ISBITSET(ext,11)) { 449 if (ISBITSET(ext,15)) 450 PRINT_AREG(dbuf,BITFIELD(ext,14,12)); 451 else 452 PRINT_DREG(dbuf,BITFIELD(ext,14,12)); 453 addchar(','); 454 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 455 } else { 456 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 457 addchar(','); 458 if (ISBITSET(ext,15)) 459 PRINT_AREG(dbuf,BITFIELD(ext,14,12)); 460 else 461 PRINT_DREG(dbuf,BITFIELD(ext,14,12)); 462 } 463 return; 464 case ADDI_INST: 465 tmp = "addi"; 466 break; 467 case ANDI_INST: 468 tmp = "andi"; 469 break; 470 case CMPI_INST: 471 tmp = "cmpi"; 472 break; 473 case EORI_INST: 474 tmp = "eori"; 475 break; 476 case ORI_INST: 477 tmp = "ori"; 478 break; 479 case SUBI_INST: 480 tmp = "subi"; 481 break; 482 } 483 if (tmp) { 484 addstr(dbuf, tmp); 485 sz = BITFIELD(opc,7,6); 486 switch (sz) { 487 case 0: 488 addchar('b'); 489 addchar('\t'); 490 sz = SIZE_BYTE; 491 break; 492 case 1: 493 addchar('w'); 494 addchar('\t'); 495 sz = SIZE_WORD; 496 break; 497 case 2: 498 addchar ('l'); 499 addchar('\t'); 500 get_immed(dbuf,SIZE_LONG); 501 addchar(','); 502 get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,2); 503 return; 504 } 505 get_immed(dbuf,sz); 506 addchar(','); 507 get_modregstr(dbuf,5,GETMOD_BEFORE,sz,1); 508 return; 509 } 510} 511 512/* 513 * move byte/word/long and q 514 * 00xx (01==.b 10==.l 11==.w) and 0111(Q) 515 */ 516static void 517opcode_move(dis_buffer_t *dbuf, u_short opc) 518{ 519 int sz, lused; 520 521 sz = 0; 522 switch (OPCODE_MAP(opc)) { 523 case 0x1: /* move.b */ 524 sz = SIZE_BYTE; 525 break; 526 case 0x3: /* move.w */ 527 sz = SIZE_WORD; 528 break; 529 case 0x2: /* move.l */ 530 sz = SIZE_LONG; 531 break; 532 case 0x7: /* moveq */ 533 addstr(dbuf, "movq\t#"); 534 prints_bf(dbuf, opc, 7, 0); 535 addchar(','); 536 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 537 return; 538 } 539 addstr(dbuf, "mov"); 540 541 if (BITFIELD(opc,8,6) == AR_DIR) 542 addchar('a'); 543 544 if (sz == SIZE_BYTE) 545 addchar('b'); 546 else if (sz == SIZE_WORD) 547 addchar('w'); 548 else 549 addchar('l'); 550 551 addchar('\t'); 552 lused = dbuf->used; 553 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 554 addchar(','); 555 get_modregstr(dbuf, 11, GETMOD_AFTER, sz, dbuf->used - lused); 556} 557 558/* 559 * misc opcodes. 560 */ 561static void 562opcode_misc(dis_buffer_t *dbuf, u_short opc) 563{ 564 const char *tmp; 565 int sz; 566 567 tmp = NULL; 568 569 /* Check against no option instructions */ 570 switch (opc) { 571 case BGND_INST: 572 tmp = "bgnd"; 573 break; 574 case ILLEGAL_INST: 575 tmp = "illegal"; 576 break; 577 case MOVEFRC_INST: 578 case MOVETOC_INST: 579 opcode_movec(dbuf, opc); 580 return; 581 case NOP_INST: 582 tmp = "nop"; 583 break; 584 case RESET_INST: 585 tmp = "reset"; 586 break; 587 case RTD_INST: 588 addstr(dbuf, "rtd\t"); 589 get_immed(dbuf, SIZE_WORD); 590 return; 591 case RTE_INST: 592 tmp = "rte"; 593 break; 594 case RTR_INST: 595 tmp = "rtr"; 596 break; 597 case RTS_INST: 598 tmp = "rts"; 599 break; 600 case STOP_INST: 601 addstr(dbuf, "stop\t"); 602 get_immed(dbuf, SIZE_WORD); 603 return; 604 case TRAPV_INST: 605 tmp = "trapv"; 606 break; 607 default: 608 break; 609 } 610 if (tmp) { 611 addstr(dbuf, tmp); 612 return; 613 } 614 615 switch (opc & BKPT_MASK) { 616 case BKPT_INST: 617 addstr(dbuf, "bkpt\t#"); 618 printu_bf(dbuf, opc, 2, 0); 619 return; 620 case EXTBW_INST: 621 addstr(dbuf, "extw\t"); 622 get_modregstr(dbuf,2,DR_DIR,0,0); 623 return; 624 case EXTWL_INST: 625 addstr(dbuf, "extl\t"); 626 get_modregstr(dbuf,2,DR_DIR,0,0); 627 return; 628 case EXTBL_INST: 629 addstr(dbuf, "extbl\t"); 630 get_modregstr(dbuf,2,DR_DIR,0,0); 631 return; 632 case LINKW_INST: 633 case LINKL_INST: 634 if ((LINKW_MASK & opc) == LINKW_INST) { 635 addstr(dbuf, "linkw\t"); 636 get_modregstr(dbuf, 2, AR_DIR, 0, 1); 637 } else { 638 addstr(dbuf, "linkl\t"); 639 get_modregstr(dbuf, 2, AR_DIR, 0, 2); 640 } 641 addchar(','); 642 if ((LINKW_MASK & opc) == LINKW_INST) 643 get_immed(dbuf, SIZE_WORD); 644 else 645 get_immed(dbuf,SIZE_LONG); 646 return; 647 case MOVETOUSP_INST: 648 case MOVEFRUSP_INST: 649 addstr(dbuf, "movl\t"); 650 if (!ISBITSET(opc,3)) { 651 get_modregstr(dbuf, 2, AR_DIR, 0, 0); 652 addchar(','); 653 } 654 addstr(dbuf, "usp"); 655 if (ISBITSET(opc,3)) { 656 addchar(','); 657 get_modregstr(dbuf, 2, AR_DIR, 0, 0); 658 } 659 return; 660 case SWAP_INST: 661 addstr(dbuf, "swap\t"); 662 get_modregstr(dbuf, 2, DR_DIR, 0, 0); 663 return; 664 case UNLK_INST: 665 addstr(dbuf, "unlk\t"); 666 get_modregstr(dbuf, 2, AR_DIR, 0, 0); 667 return; 668 } 669 670 if ((opc & TRAP_MASK) == TRAP_INST) { 671 addstr(dbuf, "trap\t#"); 672 printu_bf(dbuf, opc, 3, 0); 673 return; 674 } 675 676 sz = 0; 677 switch (DIVSL_MASK & opc) { 678 case DIVSL_INST: 679 case MULSL_INST: 680 opcode_divmul(dbuf, opc); 681 return; 682 case JMP_INST: 683 tmp = "jmp\t"; 684 break; 685 case JSR_INST: 686 tmp = "jsr\t"; 687 break; 688 case MOVEFRCCR_INST: 689 tmp = "mov\tccr,"; 690 break; 691 case MOVEFRSR_INST: 692 tmp = "mov\tsr,"; 693 break; 694 case NBCD_INST: 695 tmp = "nbcd\t"; 696 break; 697 case PEA_INST: 698 tmp = "pea\t"; 699 break; 700 case TAS_INST: 701 tmp = "tas\t"; 702 break; 703 case MOVETOCCR_INST: 704 case MOVETOSR_INST: 705 tmp = "mov\t"; 706 sz = SIZE_WORD; 707 break; 708 } 709 if (tmp) { 710 addstr(dbuf, tmp); 711 get_modregstr(dbuf,5, GETMOD_BEFORE, sz, 0); 712 if(IS_INST(MOVETOSR,opc)) 713 addstr(dbuf, ",sr"); 714 else if(IS_INST(MOVETOCCR,opc)) 715 addstr(dbuf, ",ccr"); 716 return; 717 } 718 719 if ((opc & MOVEM_MASK) == MOVEM_INST) { 720 opcode_movem(dbuf, opc); 721 return; 722 } 723 724 switch (opc & CLR_MASK) { 725 case CLR_INST: 726 tmp = "clr"; 727 break; 728 case NEG_INST: 729 tmp = "neg"; 730 break; 731 case NEGX_INST: 732 tmp = "negx"; 733 break; 734 case NOT_INST: 735 tmp = "not"; 736 break; 737 case TST_INST: 738 tmp = "tst"; 739 break; 740 } 741 if (tmp) { 742 int msz; 743 744 addstr(dbuf, tmp); 745 746 msz = BITFIELD(opc,7,6); 747 if (msz == 0) { 748 tmp = "b\t"; 749 sz = SIZE_BYTE; 750 } else if (msz == 1) { 751 tmp = "w\t"; 752 sz = SIZE_WORD; 753 } else { 754 tmp = "l\t"; 755 sz = SIZE_LONG; 756 } 757 addstr(dbuf, tmp); 758 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 759 return; 760 } 761 762 if ((opc & LEA_MASK) == LEA_INST) { 763 addstr(dbuf, "lea\t"); 764 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0); 765 addchar(','); 766 get_modregstr(dbuf, 11, AR_DIR, 0, 0); 767 return; 768 } else if ((opc & CHK_MASK) == CHK_INST) { 769 if (BITFIELD(opc,8,7) == 0x3) { 770 addstr(dbuf, "chkw\t"); 771 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); 772 } else { 773 addstr(dbuf, "chkl\t"); 774 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0); 775 } 776 addchar(','); 777 get_modregstr(dbuf, 11, DR_DIR, 0, 0); 778 return; 779 } 780} 781 782/* 783 * ADDQ/SUBQ/Scc/DBcc/TRAPcc 784 */ 785static void 786opcode_0101(dis_buffer_t *dbuf, u_short opc) 787{ 788 int data; 789 790 if (IS_INST(TRAPcc, opc) && BITFIELD(opc,2,0) > 1) { 791 int opmode; 792 793 opmode = BITFIELD(opc,2,0); 794 make_cond(dbuf,11,"trap"); 795 796 if (opmode == 0x2) { 797 addchar('w'); 798 addchar('\t'); 799 get_immed(dbuf, SIZE_WORD); 800 } else if (opmode == 0x3) { 801 addchar('l'); 802 addchar('\t'); 803 get_immed(dbuf, SIZE_LONG); 804 } 805 return; 806 } else if (IS_INST(DBcc, opc)) { 807 make_cond(dbuf,11,"db"); 808 addchar('\t'); 809 PRINT_DREG(dbuf, BITFIELD(opc,2,0)); 810 addchar(','); 811 print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD, -1); 812 dbuf->used++; 813 return; 814 } else if (IS_INST(Scc,opc)) { 815 make_cond(dbuf,11,"s"); 816 addchar('\t'); 817 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 0); 818 return; 819 } else if (IS_INST(ADDQ, opc) || IS_INST(SUBQ, opc)) { 820 int size = BITFIELD(opc,7,6); 821 822 if (IS_INST(SUBQ, opc)) 823 addstr(dbuf, "subq"); 824 else 825 addstr(dbuf, "addq"); 826 827 if (size == 0x1) 828 addchar('w'); 829 else if (size == 0x2) 830 addchar('l'); 831 else 832 addchar('b'); 833 834 addchar('\t'); 835 addchar('#'); 836 data = BITFIELD(opc,11,9); 837 if (data == 0) 838 data = 8; 839 printu(dbuf, data, SIZE_BYTE); 840 addchar(','); 841 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); 842 843 return; 844 } 845} 846 847/* 848 * Bcc/BSR/BRA 849 */ 850static void 851opcode_branch(dis_buffer_t *dbuf, u_short opc) 852{ 853 int disp; 854 855 if (IS_INST(BRA,opc)) 856 addstr(dbuf, "bra"); 857 else if (IS_INST(BSR,opc)) 858 addstr(dbuf, "bsr"); 859 else 860 make_cond(dbuf,11,"b"); 861 862 disp = BITFIELD(opc,7,0); 863 if (disp == 0) { 864 /* 16-bit signed displacement */ 865 disp = *(dbuf->val + 1); 866 dbuf->used++; 867 addchar('w'); 868 } else if (disp == 0xff) { 869 /* 32-bit signed displacement */ 870 disp = *(long *)(dbuf->val + 1); 871 dbuf->used += 2; 872 addchar('l'); 873 } else { 874 /* 8-bit signed displacement in opcode. */ 875 /* Needs to be sign-extended... */ 876 if (ISBITSET(disp,7)) 877 disp -= 256; 878 addchar('b'); 879 } 880 addchar('\t'); 881 print_addr(dbuf, disp + (u_long)dbuf->val + 2); 882} 883 884/* 885 * ADD/ADDA/ADDX/SUB/SUBA/SUBX 886 */ 887static void 888opcode_addsub(dis_buffer_t *dbuf, u_short opc) 889{ 890 int sz, ch, amode; 891 892 sz = BITFIELD(opc,7,6); 893 amode = 0; 894 895 if (sz == 0) { 896 ch = 'b'; 897 sz = SIZE_BYTE; 898 } else if (sz == 1) { 899 ch = 'w'; 900 sz = SIZE_WORD; 901 } else if (sz == 2) { 902 ch = 'l'; 903 sz = SIZE_LONG; 904 } else { 905 amode = 1; 906 if (!ISBITSET(opc,8)) { 907 sz = SIZE_WORD; 908 ch = 'w'; 909 } else { 910 sz = SIZE_LONG; 911 ch = 'l'; 912 } 913 } 914 915 if (!amode && (IS_INST(ADDX,opc) || IS_INST(SUBX,opc))) { 916 if (IS_INST(ADDX,opc)) 917 addstr(dbuf,"addx"); 918 else 919 addstr(dbuf,"subx"); 920 921 addchar(ch); 922 addchar('\t'); 923 924 if (ISBITSET(opc,3)) { 925 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 926 addchar('@'); 927 addchar('-'); 928 addchar(','); 929 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 930 addchar('@'); 931 addchar('-'); 932 } else { 933 PRINT_DREG(dbuf,BITFIELD(opc,2,0)); 934 addchar(','); 935 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 936 } 937 } else { 938 if (IS_INST(ADD,opc)) 939 addstr(dbuf, "add"); 940 else 941 addstr(dbuf, "sub"); 942 943 if (amode) 944 addchar('a'); 945 addchar(ch); 946 addchar('\t'); 947 948 if (ISBITSET(opc,8) && amode == 0) { 949 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 950 addchar(','); 951 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 952 } else { 953 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 954 addchar(','); 955 if (amode) 956 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 957 else 958 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 959 } 960 } 961 return; 962} 963 964/* 965 * Shift/Rotate/Bit Field 966 */ 967static void 968opcode_1110(dis_buffer_t *dbuf, u_short opc) 969{ 970 const char *tmp; 971 u_short ext; 972 int type, sz; 973 974 tmp = NULL; 975 976 switch (opc & BFCHG_MASK) { 977 case BFCHG_INST: 978 tmp = "bfchg"; 979 break; 980 case BFCLR_INST: 981 tmp = "bfclr"; 982 break; 983 case BFEXTS_INST: 984 tmp = "bfexts"; 985 break; 986 case BFEXTU_INST: 987 tmp = "bfextu"; 988 break; 989 case BFFFO_INST: 990 tmp = "bfffo"; 991 break; 992 case BFINS_INST: 993 tmp = "bfins"; 994 break; 995 case BFSET_INST: 996 tmp = "bfset"; 997 break; 998 case BFTST_INST: 999 tmp = "bftst"; 1000 break; 1001 } 1002 if (tmp) { 1003 short bf; 1004 1005 addstr(dbuf, tmp); 1006 addchar('\t'); 1007 1008 ext = *(dbuf->val + 1); 1009 dbuf->used++; 1010 1011 if (IS_INST(BFINS,opc)) { 1012 PRINT_DREG(dbuf, BITFIELD(ext,14,12)); 1013 addchar(','); 1014 } 1015 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); 1016 addchar('{'); 1017 1018 bf = BITFIELD(ext,10,6); 1019 if (ISBITSET(ext, 11)) 1020 PRINT_DREG(dbuf, bf); 1021 else 1022 printu_wb(dbuf, bf, SIZE_BYTE, 10); 1023 1024 addchar(':'); 1025 1026 bf = BITFIELD(ext, 4, 0); 1027 if (ISBITSET(ext, 5)) 1028 PRINT_DREG(dbuf, bf); 1029 else { 1030 if (bf == 0) 1031 bf = 32; 1032 printu_wb(dbuf, bf, SIZE_BYTE, 10); 1033 } 1034 addchar('}'); 1035 if (ISBITSET(opc,8) && !IS_INST(BFINS,opc)) { 1036 addchar(','); 1037 PRINT_DREG(dbuf, BITFIELD(ext,14,12)); 1038 } else 1039 *dbuf->casm = 0; 1040 return; 1041 } 1042 sz = BITFIELD(opc,7,6); 1043 if (sz == 0x3) 1044 type = BITFIELD(opc, 10, 9); 1045 else 1046 type = BITFIELD(opc, 4, 3); 1047 1048 switch (type) { 1049 case AS_TYPE: 1050 addchar('a'); 1051 addchar('s'); 1052 break; 1053 case LS_TYPE: 1054 addchar('l'); 1055 addchar('s'); 1056 break; 1057 case RO_TYPE: 1058 addchar('r'); 1059 addchar('o'); 1060 break; 1061 case ROX_TYPE: 1062 addchar('r'); 1063 addchar('o'); 1064 addchar('x'); 1065 break; 1066 } 1067 1068 if (ISBITSET(opc,8)) 1069 addchar('l'); 1070 else 1071 addchar('r'); 1072 1073 switch (sz) { 1074 case 0: 1075 sz = SIZE_BYTE; 1076 addchar('b'); 1077 break; 1078 case 3: 1079 case 1: 1080 sz = SIZE_WORD; 1081 addchar('w'); 1082 break; 1083 case 2: 1084 sz = SIZE_LONG; 1085 addchar('l'); 1086 break; 1087 1088 } 1089 addchar('\t'); 1090 if(BITFIELD(opc,7,6) == 0x3) { 1091 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 1092 return; 1093 } else if (ISBITSET(opc,5)) 1094 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1095 else { 1096 addchar('#'); 1097 sz = BITFIELD(opc,11,9); 1098 if (sz == 0) 1099 sz = 8; 1100 printu_wb(dbuf, sz, SIZE_BYTE, 10); 1101 } 1102 addchar(','); 1103 PRINT_DREG(dbuf, BITFIELD(opc,2,0)); 1104 return; 1105} 1106 1107/* 1108 * CMP/CMPA/EOR 1109 */ 1110static void 1111opcode_1011(dis_buffer_t *dbuf, u_short opc) 1112{ 1113 int sz; 1114 1115 if (IS_INST(CMPA,opc)) { 1116 addstr(dbuf, "cmpa"); 1117 1118 if (ISBITSET(opc, 8)) { 1119 addchar('l'); 1120 sz = SIZE_LONG; 1121 } else { 1122 addchar('w'); 1123 sz = SIZE_WORD; 1124 } 1125 addchar('\t'); 1126 } else { 1127 if (IS_INST(CMP, opc)) 1128 addstr(dbuf, "cmp"); 1129 else 1130 addstr(dbuf, "eor"); 1131 1132 sz = BITFIELD(opc,7,6); 1133 switch (sz) { 1134 case 0: 1135 addchar('b'); 1136 sz = SIZE_BYTE; 1137 break; 1138 case 1: 1139 addchar('w'); 1140 sz = SIZE_WORD; 1141 break; 1142 case 2: 1143 addchar('l'); 1144 sz = SIZE_LONG; 1145 break; 1146 } 1147 addchar('\t'); 1148 if (IS_INST(EOR,opc)) { 1149 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1150 addchar(','); 1151 } 1152 } 1153 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 1154 1155 if (IS_INST(CMPA,opc)) { 1156 addchar(','); 1157 PRINT_AREG(dbuf, BITFIELD(opc,11,9)); 1158 } else if (IS_INST(CMP,opc)) { 1159 addchar(','); 1160 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1161 } 1162 return; 1163} 1164 1165/* 1166 * OR/DIV/SBCD 1167 */ 1168static void 1169opcode_1000(dis_buffer_t *dbuf, u_short opc) 1170{ 1171 int sz; 1172 1173 if (IS_INST(UNPKA,opc)) { 1174 addstr(dbuf, "unpk\t"); 1175 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 1176 addstr(dbuf, "@-,"); 1177 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 1178 addstr(dbuf, "@-,"); 1179 get_immed(dbuf,SIZE_WORD); 1180 } else if (IS_INST(UNPKD,opc)) { 1181 addstr(dbuf, "unpk\t"); 1182 PRINT_DREG(dbuf,BITFIELD(opc,2,0)); 1183 addchar(','); 1184 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 1185 addchar(','); 1186 get_immed(dbuf,SIZE_WORD); 1187 } else if (IS_INST(SBCDA,opc)) { 1188 addstr(dbuf, "sbcd\t"); 1189 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 1190 addstr(dbuf, "@-,"); 1191 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 1192 addstr(dbuf, "@-"); 1193 } else if (IS_INST(SBCDD,opc)) { 1194 addstr(dbuf, "sbcd\t"); 1195 PRINT_DREG(dbuf,BITFIELD(opc,2,0)); 1196 addchar(','); 1197 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 1198 } else if (IS_INST(DIVSW,opc) || IS_INST(DIVUW,opc)) { 1199 if (IS_INST(DIVSW,opc)) 1200 addstr(dbuf, "divsw\t"); 1201 else 1202 addstr(dbuf, "divuw\t"); 1203 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); 1204 addchar(','); 1205 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1206 } else { 1207 addstr(dbuf, "or"); 1208 1209 sz = BITFIELD(opc,7,6); 1210 switch (sz) { 1211 case 0: 1212 addchar('b'); 1213 sz = SIZE_BYTE; 1214 break; 1215 case 1: 1216 addchar('w'); 1217 sz = SIZE_WORD; 1218 break; 1219 case 2: 1220 addchar('l'); 1221 sz = SIZE_LONG; 1222 break; 1223 } 1224 addchar('\t'); 1225 if (ISBITSET(opc,8)) { 1226 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1227 addchar(','); 1228 } 1229 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 1230 if (!ISBITSET(opc,8)) { 1231 addchar(','); 1232 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1233 } 1234 } 1235} 1236 1237/* 1238 * AND/MUL/ABCD/EXG (1100) 1239 */ 1240static void 1241opcode_1100(dis_buffer_t *dbuf, u_short opc) 1242{ 1243 int sz; 1244 1245 if (IS_INST(ABCDA,opc)) { 1246 addstr(dbuf, "abcd\t"); 1247 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 1248 addstr(dbuf, "@-,"); 1249 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 1250 addstr(dbuf, "@-"); 1251 } else if (IS_INST(ABCDD,opc)) { 1252 addstr(dbuf, "abcd\t"); 1253 PRINT_DREG(dbuf,BITFIELD(opc,2,0)); 1254 addchar(','); 1255 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 1256 } else if (IS_INST(MULSW,opc) || IS_INST(MULUW,opc)) { 1257 if (IS_INST(MULSW,opc)) 1258 addstr(dbuf, "mulsw\t"); 1259 else 1260 addstr(dbuf, "muluw\t"); 1261 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); 1262 addchar(','); 1263 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1264 } else if (IS_INST(EXG,opc)) { 1265 addstr(dbuf, "exg\t"); 1266 if (ISBITSET(opc,7)) { 1267 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 1268 addchar(','); 1269 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 1270 } else if (ISBITSET(opc,3)) { 1271 PRINT_AREG(dbuf,BITFIELD(opc,11,9)); 1272 addchar(','); 1273 PRINT_AREG(dbuf,BITFIELD(opc,2,0)); 1274 } else { 1275 PRINT_DREG(dbuf,BITFIELD(opc,11,9)); 1276 addchar(','); 1277 PRINT_DREG(dbuf,BITFIELD(opc,2,0)); 1278 } 1279 } else { 1280 addstr(dbuf, "and"); 1281 1282 sz = BITFIELD(opc,7,6); 1283 switch (sz) { 1284 case 0: 1285 addchar('b'); 1286 sz = SIZE_BYTE; 1287 break; 1288 case 1: 1289 addchar('w'); 1290 sz = SIZE_WORD; 1291 break; 1292 case 2: 1293 addchar('l'); 1294 sz = SIZE_LONG; 1295 break; 1296 } 1297 addchar('\t'); 1298 1299 if (ISBITSET(opc,8)) { 1300 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1301 addchar(','); 1302 } 1303 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); 1304 if (!ISBITSET(opc,8)) { 1305 addchar(','); 1306 PRINT_DREG(dbuf, BITFIELD(opc,11,9)); 1307 } 1308 } 1309} 1310 1311/* 1312 * Coprocessor instruction 1313 */ 1314static void 1315opcode_coproc(dis_buffer_t *dbuf, u_short opc) 1316{ 1317 switch (BITFIELD(*dbuf->val,11,9)) { 1318 case 1: 1319 opcode_fpu(dbuf, opc); 1320 return; 1321 case 0: 1322 opcode_mmu(dbuf, opc); 1323 return; 1324 case 2: 1325 opcode_mmu040(dbuf, opc); 1326 return; 1327 case 3: 1328 opcode_move16(dbuf, opc); 1329 return; 1330 } 1331 switch (BITFIELD(opc,8,6)) { 1332 case 0: 1333 dbuf->used++; 1334 break; 1335 case 3: 1336 dbuf->used++; 1337 /*FALLTHROUGH*/ 1338 case 2: 1339 dbuf->used++; 1340 break; 1341 case 1: 1342 dbuf->used++; 1343 case 4: 1344 case 5: 1345 default: 1346 /* Nothing */ ; 1347 } 1348 addstr(dbuf, "UNKNOWN COPROC OPCODE"); 1349 return; 1350} 1351 1352/* 1353 * Resvd 1354 */ 1355static void 1356opcode_1010(dis_buffer_t *dbuf, u_short opc) 1357{ 1358 addstr(dbuf, "RSVD"); 1359 dbuf->used++; 1360} 1361 1362static void 1363opcode_fpu(dis_buffer_t *dbuf, u_short opc) 1364{ 1365 u_short ext; 1366 int type, opmode; 1367 1368 type = BITFIELD(opc,8,6); 1369 switch (type) { 1370 /* cpGEN */ 1371 case 0: 1372 ext = *(dbuf->val + 1); 1373 dbuf->used++; 1374 opmode = BITFIELD(ext,5,0); 1375 1376 if (BITFIELD(opc,5,0) == 0 && BITFIELD(ext,15,10) == 0x17) { 1377 addstr(dbuf,"fmovcrx #"); 1378 printu(dbuf,BITFIELD(ext,6,0),SIZE_BYTE); 1379 return; 1380 } 1381 if (ISBITSET(ext,15) || ISBITSET(ext,13)) { 1382 opcode_fmove_ext(dbuf, opc, ext); 1383 return; 1384 } 1385 1386 switch(opmode) { 1387 case FMOVE: 1388 get_fpustdGEN(dbuf,ext,"fmov"); 1389 return; 1390 case FABS: 1391 get_fpustdGEN(dbuf,ext,"fabs"); 1392 return; 1393 case FACOS: 1394 get_fpustdGEN(dbuf,ext,"facos"); 1395 return; 1396 case FADD: 1397 get_fpustdGEN(dbuf,ext,"fadd"); 1398 return; 1399 case FASIN: 1400 get_fpustdGEN(dbuf,ext,"fasin"); 1401 return; 1402 case FATAN: 1403 get_fpustdGEN(dbuf,ext,"fatan"); 1404 return; 1405 case FATANH: 1406 get_fpustdGEN(dbuf,ext,"fatanh"); 1407 return; 1408 case FCMP: 1409 get_fpustdGEN(dbuf,ext,"fcmp"); 1410 return; 1411 case FCOS: 1412 get_fpustdGEN(dbuf,ext,"fcos"); 1413 return; 1414 case FCOSH: 1415 get_fpustdGEN(dbuf,ext,"fcosh"); 1416 return; 1417 case FDIV: 1418 get_fpustdGEN(dbuf,ext,"fdiv"); 1419 return; 1420 case FETOX: 1421 get_fpustdGEN(dbuf,ext,"fetox"); 1422 return; 1423 case FGETEXP: 1424 get_fpustdGEN(dbuf,ext,"fgetexp"); 1425 return; 1426 case FGETMAN: 1427 get_fpustdGEN(dbuf,ext,"fgetman"); 1428 return; 1429 case FINT: 1430 get_fpustdGEN(dbuf,ext,"fint"); 1431 return; 1432 case FINTRZ: 1433 get_fpustdGEN(dbuf,ext,"fintrz"); 1434 return; 1435 case FLOG10: 1436 get_fpustdGEN(dbuf,ext,"flog10"); 1437 return; 1438 case FLOG2: 1439 get_fpustdGEN(dbuf,ext,"flog2"); 1440 return; 1441 case FLOGN: 1442 get_fpustdGEN(dbuf,ext,"flogn"); 1443 return; 1444 case FLOGNP1: 1445 get_fpustdGEN(dbuf,ext,"flognp1"); 1446 return; 1447 case FMOD: 1448 get_fpustdGEN(dbuf,ext,"fmod"); 1449 return; 1450 case FMUL: 1451 get_fpustdGEN(dbuf,ext,"fmul"); 1452 return; 1453 case FNEG: 1454 get_fpustdGEN(dbuf,ext,"fneg"); 1455 return; 1456 case FREM: 1457 get_fpustdGEN(dbuf,ext,"frem"); 1458 return; 1459 case FSCALE: 1460 get_fpustdGEN(dbuf,ext,"fscale"); 1461 return; 1462 case FSGLDIV: 1463 get_fpustdGEN(dbuf,ext,"fsgldiv"); 1464 return; 1465 case FSGLMUL: 1466 get_fpustdGEN(dbuf,ext,"fsglmul"); 1467 return; 1468 case FSIN: 1469 get_fpustdGEN(dbuf,ext,"fsin"); 1470 return; 1471 case FSINH: 1472 get_fpustdGEN(dbuf,ext,"fsinh"); 1473 return; 1474 case FSQRT: 1475 get_fpustdGEN(dbuf,ext,"fsqrt"); 1476 return; 1477 case FSUB: 1478 get_fpustdGEN(dbuf,ext,"fsub"); 1479 return; 1480 case FTAN: 1481 get_fpustdGEN(dbuf,ext,"ftan"); 1482 return; 1483 case FTANH: 1484 get_fpustdGEN(dbuf,ext,"ftanh"); 1485 return; 1486 case FTENTOX: 1487 get_fpustdGEN(dbuf,ext,"ftentox"); 1488 return; 1489 case FTST: 1490 get_fpustdGEN(dbuf,ext,"ftst"); 1491 return; 1492 case FTWOTOX: 1493 get_fpustdGEN(dbuf,ext,"ftwotox"); 1494 return; 1495 1496 } 1497 /* FALLTHROUGH */ 1498 /* cpBcc */ 1499 case 2: 1500 if (BITFIELD(opc,5,0) == 0 && *(dbuf->val + 1) == 0) { 1501 dbuf->used++; 1502 addstr (dbuf, "fnop"); 1503 return; 1504 } 1505 /* FALLTHROUGH */ 1506 case 3: 1507 addstr(dbuf, "fb"); 1508 print_fcond(dbuf, BITFIELD(opc,5,0)); 1509 if (type == 2) { 1510 addchar('w'); 1511 addchar('\t'); 1512 print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1); 1513 dbuf->used++; 1514 } else { 1515 addchar('l'); 1516 addchar('\t'); 1517 print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG, 1518 -1); 1519 dbuf->used += 2; 1520 } 1521 return; 1522 /* cpDBcc/cpScc/cpTrap */ 1523 case 1: 1524 ext = *(dbuf->val + 1); 1525 dbuf->used++; 1526 1527 if (BITFIELD(opc,5,3) == 0x1) { 1528 /* fdbcc */ 1529 addstr(dbuf,"fdb"); 1530 print_fcond(dbuf,BITFIELD(ext,5,0)); 1531 addchar('\t'); 1532 PRINT_DREG(dbuf, BITFIELD(opc,2,0)); 1533 addchar(','); 1534 print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1); 1535 dbuf->used++; 1536 } else if (BITFIELD(opc,5,3) == 0x7 && 1537 BITFIELD(opc,2,0) > 1) { 1538 addstr(dbuf,"ftrap"); 1539 print_fcond(dbuf,BITFIELD(ext,5,0)); 1540 1541 if (BITFIELD(opc,2,0) == 0x2) { 1542 addchar('w'); 1543 addchar('\t'); 1544 dbuf->val++; 1545 get_immed(dbuf, SIZE_WORD); 1546 dbuf->val--; 1547 } else if (BITFIELD(opc,2,0) == 0x3) { 1548 addchar('l'); 1549 addchar('\t'); 1550 dbuf->val++; 1551 get_immed(dbuf, SIZE_LONG); 1552 dbuf->val--; 1553 } 1554 } else { 1555 addstr(dbuf,"fs"); 1556 print_fcond(dbuf,BITFIELD(ext,5,0)); 1557 addchar('\t'); 1558 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1); 1559 } 1560 return; 1561 case 4: 1562 addstr(dbuf,"fsave\t"); 1563 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); 1564 return; 1565 case 5: 1566 addstr(dbuf,"frestor\t"); 1567 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); 1568 return; 1569 } 1570} 1571 1572/* 1573 * XXX - This screws up on: fmovem a0@(312),fpcr/fpsr/fpi 1574 */ 1575static void 1576opcode_fmove_ext(dis_buffer_t *dbuf, u_short opc, u_short ext) 1577{ 1578 int sz; 1579 1580 sz = 0; 1581 if (BITFIELD(ext,15,13) == 3) { 1582 /* fmove r ==> m */ 1583 addstr(dbuf, "fmov"); 1584 switch (BITFIELD(ext,12,10)) { 1585 case 0: 1586 addchar('l'); 1587 sz = SIZE_LONG; 1588 break; 1589 case 1: 1590 addchar('s'); 1591 sz = SIZE_SINGLE; 1592 break; 1593 case 2: 1594 addchar('x'); 1595 sz = SIZE_EXTENDED; 1596 break; 1597 case 7: 1598 case 3: 1599 addchar('p'); 1600 sz = SIZE_PACKED; 1601 break; 1602 case 4: 1603 addchar('w'); 1604 sz = SIZE_WORD; 1605 break; 1606 case 5: 1607 addchar('d'); 1608 sz = SIZE_DOUBLE; 1609 break; 1610 case 6: 1611 addchar('b'); 1612 sz = SIZE_BYTE; 1613 break; 1614 } 1615 addchar('\t'); 1616 PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); 1617 addchar(','); 1618 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 1619 if (sz == SIZE_PACKED) { 1620 addchar('{'); 1621 if (ISBITSET(ext,12)) { 1622 PRINT_DREG(dbuf,BITFIELD(ext,6,4)); 1623 } else { 1624 addchar('#'); 1625 prints_bf(dbuf, ext, 6, 4); 1626 } 1627 addchar('}'); 1628 } 1629 return; 1630 } 1631 addstr(dbuf,"fmovm"); 1632 1633 if (!ISBITSET(ext,14)) { 1634 /* fmove[m] control reg */ 1635 addchar('l'); 1636 addchar('\t'); 1637 1638 if (ISBITSET(ext,13)) { 1639 print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1); 1640 addchar(','); 1641 } 1642 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); 1643 if (!ISBITSET(ext,13)) { 1644 addchar(','); 1645 print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1); 1646 } 1647 return; 1648 } 1649 addchar('x'); 1650 addchar('\t'); 1651 1652 if (ISBITSET(ext,11)) { 1653 if (ISBITSET(ext,13)) { 1654 PRINT_DREG(dbuf,BITFIELD(ext,6,4)); 1655 addchar(','); 1656 } 1657 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1); 1658 if (!ISBITSET(ext,13)) { 1659 addchar(','); 1660 PRINT_DREG(dbuf,BITFIELD(ext,6,4)); 1661 } 1662 } else { 1663 if (ISBITSET(ext,13)) { 1664 print_freglist(dbuf, BITFIELD(opc,5,3), 1665 BITFIELD(ext,7,0), 0); 1666 addchar(','); 1667 } 1668 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1); 1669 if (!ISBITSET(ext,13)) { 1670 addchar(','); 1671 print_freglist(dbuf, BITFIELD(opc,5,3), 1672 BITFIELD(ext,7,0), 0); 1673 } 1674 } 1675} 1676 1677static void 1678opcode_mmu(dis_buffer_t *dbuf, u_short opc) 1679{ 1680 u_short ext; 1681 int type; 1682 1683 type = BITFIELD(opc,8,6); 1684 switch (type) { 1685 /* cpGEN? */ 1686 case 0: 1687 ext = *(dbuf->val + 1); 1688 dbuf->used++; 1689 1690 switch(BITFIELD(ext,15,13)) { 1691 case 5: 1692 case 1: 1693 opcode_pflush(dbuf, opc, ext); 1694 return; 1695 case 0: 1696 case 3: 1697 case 2: 1698 opcode_pmove(dbuf, opc, ext); 1699 return; 1700 case 4: 1701 addstr(dbuf, "ptest"); 1702 if (ISBITSET(ext,9)) 1703 addchar('r'); 1704 else 1705 addchar('w'); 1706 addchar('\t'); 1707 print_fcode(dbuf, BITFIELD(ext, 5, 0)); 1708 addchar(','); 1709 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); 1710 addchar(','); 1711 addchar('#'); 1712 printu_bf(dbuf, ext, 12, 10); 1713 if (ISBITSET(ext, 8)) { 1714 addchar(','); 1715 PRINT_AREG(dbuf, BITFIELD(ext, 7, 5)); 1716 } 1717 } 1718 return; 1719 case 2: 1720 case 3: 1721 addstr(dbuf, "pb"); 1722 print_mcond(dbuf, BITFIELD(opc,5,0)); 1723 if (type == 2) { 1724 addchar('w'); 1725 addchar('\t'); 1726 print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1); 1727 dbuf->used++; 1728 } else { 1729 addchar('l'); 1730 addchar('\t'); 1731 print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG, 1732 -1); 1733 dbuf->used += 2; 1734 } 1735 return; 1736 case 1: 1737 ext = *(dbuf->val + 1); 1738 dbuf->used++; 1739 1740 if (BITFIELD(opc,5,3) == 0x1) { 1741 /* fdbcc */ 1742 addstr(dbuf,"pdb"); 1743 print_fcond(dbuf,BITFIELD(ext,5,0)); 1744 addchar('\t'); 1745 PRINT_DREG(dbuf, BITFIELD(opc,2,0)); 1746 addchar(','); 1747 print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1); 1748 dbuf->used++; 1749 } else if (BITFIELD(opc,5,3) == 0x7 && 1750 BITFIELD(opc,2,0) > 1) { 1751 addstr(dbuf,"ptrap"); 1752 print_fcond(dbuf,BITFIELD(ext,5,0)); 1753 1754 if (BITFIELD(opc,2,0) == 0x2) { 1755 addchar('w'); 1756 addchar('\t'); 1757 dbuf->val++; 1758 get_immed(dbuf, SIZE_WORD); 1759 dbuf->val--; 1760 } else if (BITFIELD(opc,2,0) == 0x3) { 1761 addchar('l'); 1762 addchar('\t'); 1763 dbuf->val++; 1764 get_immed(dbuf, SIZE_LONG); 1765 dbuf->val--; 1766 } 1767 } else { 1768 addstr(dbuf,"ps"); 1769 print_fcond(dbuf,BITFIELD(ext,5,0)); 1770 addchar('\t'); 1771 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1); 1772 } 1773 return; 1774 case 4: 1775 addstr(dbuf,"psave\t"); 1776 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); 1777 return; 1778 case 5: 1779 addstr(dbuf,"prestore\t"); 1780 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); 1781 return; 1782 } 1783} 1784 1785static void 1786opcode_pflush(dis_buffer_t *dbuf, u_short opc, u_short ext) 1787{ 1788 u_short mode, mask, fc; 1789 1790 mode = BITFIELD(ext,12,10); 1791 mask = BITFIELD(ext,8,5); 1792 fc = BITFIELD(ext, 5, 0); 1793 1794 if (ext == 0xa000) { 1795 addstr(dbuf,"pflushr\t"); 1796 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); 1797 return; 1798 } 1799 1800 if (mode == 0) { 1801 addstr(dbuf,"pload"); 1802 if (ISBITSET(ext,9)) 1803 addchar('r'); 1804 else 1805 addchar('w'); 1806 addchar(' '); 1807 print_fcode(dbuf, fc); 1808 } 1809 1810 addstr(dbuf,"pflush"); 1811 switch (mode) { 1812 case 1: 1813 addchar('a'); 1814 *dbuf->casm = 0; 1815 break; 1816 case 7: 1817 case 5: 1818 addchar('s'); 1819 /*FALLTHROUGH*/ 1820 case 6: 1821 case 4: 1822 addchar('\t'); 1823 print_fcode(dbuf, fc); 1824 addchar(','); 1825 addchar('#'); 1826 printu(dbuf, mask, SIZE_BYTE); 1827 if (!ISBITSET(mode,1)) 1828 break; 1829 addchar(','); 1830 get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); 1831 } 1832} 1833 1834static void 1835opcode_pmove(dis_buffer_t *dbuf, u_short opc, u_short ext) 1836{ 1837 const char *reg; 1838 int rtom, sz, preg; 1839 1840 reg = "???"; 1841 sz = 0; 1842 rtom = ISBITSET(ext, 9); 1843 preg = BITFIELD(ext, 12, 10); 1844 1845 addstr(dbuf,"pmov"); 1846 if (ISBITSET(ext,8)) { 1847 addchar('f'); 1848 addchar('d'); 1849 } 1850 switch (BITFIELD(ext, 15, 13)) { 1851 case 0: /* tt regs 030o */ 1852 switch (preg) { 1853 case 2: 1854 reg = "tt0"; 1855 break; 1856 case 3: 1857 reg = "tt1"; 1858 break; 1859 } 1860 sz = SIZE_LONG; 1861 break; 1862 case 2: 1863 switch (preg) { 1864 case 0: 1865 reg = "tc"; 1866 sz = SIZE_LONG; 1867 break; 1868 case 1: 1869 reg = "drp"; 1870 sz = SIZE_QUAD; 1871 break; 1872 case 2: 1873 reg = "srp"; 1874 sz = SIZE_QUAD; 1875 break; 1876 case 3: 1877 reg = "crp"; 1878 sz = SIZE_QUAD; 1879 break; 1880 case 4: 1881 reg = "cal"; 1882 sz = SIZE_BYTE; 1883 break; 1884 case 5: 1885 reg = "val"; 1886 sz = SIZE_BYTE; 1887 break; 1888 case 6: 1889 reg = "scc"; 1890 sz = SIZE_BYTE; 1891 break; 1892 case 7: 1893 reg = "ac"; 1894 sz = SIZE_WORD; 1895 } 1896 break; 1897 case 3: 1898 switch (preg) { 1899 case 0: 1900 reg = "mmusr"; 1901 break; 1902 case 1: 1903 reg = "pcsr"; 1904 break; 1905 case 4: 1906 reg = "bad"; 1907 break; 1908 case 5: 1909 reg = "bac"; 1910 break; 1911 } 1912 sz = SIZE_WORD; 1913 break; 1914 } 1915 switch (sz) { 1916 case SIZE_BYTE: 1917 addchar ('b'); 1918 break; 1919 case SIZE_WORD: 1920 addchar ('w'); 1921 break; 1922 case SIZE_LONG: 1923 addchar ('l'); 1924 break; 1925 case SIZE_QUAD: 1926 addchar ('d'); 1927 break; 1928 } 1929 addchar('\t'); 1930 1931 if (!rtom) { 1932 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 1933 addchar(','); 1934 } 1935 addstr(dbuf, reg); 1936 if (BITFIELD(ext, 15, 13) == 3 && preg > 1) 1937 printu_bf(dbuf, ext, 4, 2); 1938 if (rtom) { 1939 addchar(','); 1940 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 1941 } 1942 return; 1943} 1944 1945static void 1946print_fcode(dis_buffer_t *dbuf, u_short fc) 1947{ 1948 if (ISBITSET(fc, 4)) 1949 printu_bf(dbuf, fc, 3, 0); 1950 else if (ISBITSET(fc, 3)) 1951 PRINT_DREG(dbuf, BITFIELD(fc, 2, 0)); 1952 else if (fc == 1) 1953 addstr(dbuf, "sfc"); 1954 else 1955 addstr(dbuf, "dfc"); 1956} 1957 1958static void 1959opcode_mmu040(dis_buffer_t *dbuf, u_short opc) 1960{ 1961 if (ISBITSET(opc, 6)) { 1962 addstr(dbuf, "ptest"); 1963 if (ISBITSET(opc, 5)) 1964 addchar('r'); 1965 else 1966 addchar('w'); 1967 addchar('\t'); 1968 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 1969 addchar('@'); 1970 } else { 1971 addstr(dbuf, "pflush"); 1972 switch (BITFIELD(opc, 4, 3)) { 1973 case 3: 1974 addchar('a'); 1975 break; 1976 case 2: 1977 addchar('a'); 1978 addchar('n'); 1979 break; 1980 case 0: 1981 addchar('n'); 1982 /*FALLTHROUGH*/ 1983 case 1: 1984 addchar('\t'); 1985 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 1986 addchar('@'); 1987 break; 1988 } 1989 } 1990 *dbuf->casm = 0; 1991} 1992 1993/* 1994 * disassemble long format (64b) divs/muls divu/mulu opcode. 1995 * Note: opcode's dbuf->used already accounted for. 1996 */ 1997static void 1998opcode_divmul(dis_buffer_t *dbuf, u_short opc) 1999{ 2000 u_short ext; 2001 int iq, hr; 2002 2003 ext = *(dbuf->val + 1); 2004 dbuf->used++; 2005 2006 iq = BITFIELD(ext,14,12); 2007 hr = BITFIELD(ext,2,0); 2008 2009 if (IS_INST(DIVSL,opc)) 2010 addstr(dbuf, "div"); 2011 else 2012 addstr(dbuf, "mul"); 2013 if (ISBITSET(ext,11)) 2014 addchar('s'); 2015 else 2016 addchar('u'); 2017 addchar('l'); 2018 if (IS_INST(DIVSL,opc) && !ISBITSET(ext,10) && iq != hr) 2019 addchar('l'); 2020 addchar('\t'); 2021 2022 get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,1); 2023 addchar(','); 2024 2025 if (ISBITSET(ext,10) || 2026 (iq != hr && IS_INST(DIVSL,opc))) { 2027 /* 64 bit version */ 2028 PRINT_DREG(dbuf, hr); 2029 if (dbuf->mit) 2030 addchar(','); 2031 else 2032 addchar(':'); 2033 } 2034 PRINT_DREG(dbuf, iq); 2035} 2036 2037static void 2038print_reglist(dis_buffer_t *dbuf, int mod, u_short rl) 2039{ 2040 static const char *const regs[16] = { 2041 "d0","d1","d2","d3","d4","d5","d6","d7", 2042 "a0","a1","a2","a3","a4","a5","a6","a7" }; 2043 int bit, list; 2044 2045 if (mod == AR_DEC) { 2046 list = rl; 2047 rl = 0; 2048 /* I am sure there is some trick... */ 2049 for (bit = 0; bit < 16; bit++) 2050 if (list & (1 << bit)) 2051 rl |= (0x8000 >> bit); 2052 } 2053 for (bit = 0, list = 0; bit < 16; bit++) { 2054 if (ISBITSET(rl,bit) && bit != 8) { 2055 if (list == 0) { 2056 list = 1; 2057 addstr(dbuf, regs[bit]); 2058 } else if (list == 1) { 2059 list++; 2060 addchar('-'); 2061 } 2062 } else { 2063 if (list) { 2064 if (list > 1) 2065 addstr(dbuf, regs[bit-1]); 2066 addchar('/'); 2067 list = 0; 2068 } 2069 if (ISBITSET(rl,bit)) { 2070 addstr(dbuf, regs[bit]); 2071 list = 1; 2072 } 2073 } 2074 } 2075 if (list > 1) 2076 addstr(dbuf, regs[15]); 2077 2078 if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-') 2079 dbuf->casm--; 2080 *dbuf->casm = 0; 2081} 2082 2083static void 2084print_freglist(dis_buffer_t *dbuf, int mod, u_short rl, int cntl) 2085{ 2086 const char *const * regs; 2087 int bit, list, upper; 2088 2089 regs = cntl ? fpcregs : fpregs; 2090 upper = cntl ? 3 : 8; 2091 2092 if (!cntl && mod != AR_DEC) { 2093 list = rl; 2094 rl = 0; 2095 /* I am sure there is some trick... */ 2096 for (bit = 0; bit < upper; bit++) 2097 if (list & (1 << bit)) 2098 rl |= (0x80 >> bit); 2099 } 2100 for (bit = 0, list = 0; bit < upper; bit++) { 2101 if (ISBITSET(rl,bit)) { 2102 if (list == 0) { 2103 addstr(dbuf, regs[bit]); 2104 if (cntl) 2105 addchar('/'); 2106 else 2107 list = 1; 2108 } else if (list == 1) { 2109 list++; 2110 addchar('-'); 2111 } 2112 } else { 2113 if (list) { 2114 if (list > 1) 2115 addstr(dbuf, regs[bit-1]); 2116 addchar('/'); 2117 list = 0; 2118 } 2119 } 2120 } 2121 if (list > 1) 2122 addstr(dbuf, regs[upper-1]); 2123 2124 if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-') 2125 dbuf->casm--; 2126 *dbuf->casm = 0; 2127} 2128 2129/* 2130 * disassemble movem opcode. 2131 */ 2132static void 2133opcode_movem(dis_buffer_t *dbuf, u_short opc) 2134{ 2135 u_short rl; 2136 2137 rl = *(dbuf->val + 1); 2138 dbuf->used++; 2139 2140 if (ISBITSET(opc,6)) 2141 addstr(dbuf, "movml\t"); 2142 else 2143 addstr(dbuf, "movmw\t"); 2144 if (ISBITSET(opc,10)) { 2145 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); 2146 addchar(','); 2147 print_reglist(dbuf, BITFIELD(opc,5,3), rl); 2148 } else { 2149 print_reglist(dbuf, BITFIELD(opc,5,3), rl); 2150 addchar(','); 2151 get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); 2152 } 2153} 2154 2155/* 2156 * disassemble movec opcode. 2157 */ 2158static void 2159opcode_movec(dis_buffer_t *dbuf, u_short opc) 2160{ 2161 const char *tmp; 2162 u_short ext; 2163 2164 ext = *(dbuf->val + 1); 2165 dbuf->used++; 2166 2167 addstr(dbuf, "movc\t"); 2168 if (ISBITSET(opc,0)) { 2169 dbuf->val++; 2170 if (ISBITSET(ext,15)) 2171 get_modregstr(dbuf,14,AR_DIR,0,0); 2172 else 2173 get_modregstr(dbuf,14,DR_DIR,0,0); 2174 dbuf->val--; 2175 addchar(','); 2176 } 2177 switch (BITFIELD(ext,11,0)) { 2178 /* 010/020/030/040/CPU32/060 */ 2179 case 0x000: 2180 tmp = "sfc"; 2181 break; 2182 case 0x001: 2183 tmp = "dfc"; 2184 break; 2185 case 0x800: 2186 tmp = "usp"; 2187 break; 2188 case 0x801: 2189 tmp = "vbr"; 2190 break; 2191 /* 020/030 */ 2192 case 0x802: 2193 tmp = "caar"; 2194 break; 2195 /* 020/030/040/060 */ 2196 case 0x002: 2197 tmp = "cacr"; 2198 break; 2199 /* 020/030/040 */ 2200 case 0x803: 2201 tmp = "msp"; 2202 break; 2203 case 0x804: 2204 tmp = "isp"; 2205 break; 2206 /* 040/060 */ 2207 case 0x003: 2208 tmp = "tc"; 2209 break; 2210 case 0x004: 2211 tmp = "itt0"; 2212 break; 2213 case 0x005: 2214 tmp = "itt1"; 2215 break; 2216 case 0x006: 2217 tmp = "dtt0"; 2218 break; 2219 case 0x007: 2220 tmp = "dtt1"; 2221 break; 2222 /* 040 */ 2223 case 0x805: 2224 tmp = "mmusr"; 2225 break; 2226 /* 040/060 */ 2227 case 0x806: 2228 tmp = "urp"; 2229 break; 2230 case 0x807: 2231 tmp = "srp"; 2232 break; 2233 /* 060 */ 2234 case 0x008: 2235 tmp = "buscr"; 2236 break; 2237 case 0x808: 2238 tmp = "pcr"; 2239 break; 2240 default: 2241 tmp = "INVALID"; 2242 break; 2243 } 2244 addstr(dbuf, tmp); 2245 if (!ISBITSET(opc,0)) { 2246 dbuf->val++; 2247 addchar(','); 2248 if (ISBITSET(ext,15)) 2249 get_modregstr(dbuf,14,AR_DIR,0,0); 2250 else 2251 get_modregstr(dbuf,14,DR_DIR,0,0); 2252 dbuf->val--; 2253 } 2254} 2255 2256/* 2257 * disassemble move16 opcode. 2258 */ 2259static void 2260opcode_move16(dis_buffer_t *dbuf, u_short opc) 2261{ 2262 u_short ext; 2263 2264 addstr(dbuf, "move16\t"); 2265 2266 if (ISBITSET(opc, 5)) { 2267 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 2268 addstr(dbuf, "@+,"); 2269 ext = *(dbuf->val + 1); 2270 PRINT_AREG(dbuf, BITFIELD(ext,14,12)); 2271 addstr(dbuf, "@+"); 2272 dbuf->used++; 2273 } else { 2274 switch (BITFIELD(opc,4,3)) { 2275 case 0: 2276 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 2277 addstr(dbuf, "@+,"); 2278 get_immed(dbuf, SIZE_LONG); 2279 break; 2280 case 1: 2281 get_immed(dbuf, SIZE_LONG); 2282 addchar(','); 2283 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 2284 addstr(dbuf, "@+"); 2285 break; 2286 case 2: 2287 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 2288 addstr(dbuf, "@,"); 2289 get_immed(dbuf, SIZE_LONG); 2290 break; 2291 case 3: 2292 get_immed(dbuf, SIZE_LONG); 2293 addchar(','); 2294 PRINT_AREG(dbuf, BITFIELD(opc,2,0)); 2295 addchar('@'); 2296 break; 2297 } 2298 } 2299} 2300 2301/* 2302 * copy const string 's' into ``dbuf''->casm 2303 */ 2304static void 2305addstr(dis_buffer_t *dbuf, const char *s) 2306{ 2307 while ((*dbuf->casm++ = *s++)) 2308 ; 2309 dbuf->casm--; 2310} 2311 2312/* 2313 * copy const string 's' into ``dbuf''->cinfo 2314 */ 2315static void 2316iaddstr(dis_buffer_t *dbuf, const char *s) 2317{ 2318 while ((*dbuf->cinfo++ = *s++)) 2319 ; 2320 dbuf->cinfo--; 2321} 2322 2323static void 2324get_modregstr_moto(dis_buffer_t *dbuf, int bit, int mod, int sz, int dd) 2325{ 2326 u_char scale, idx; 2327 const short *nval; 2328 u_short ext; 2329 int disp, odisp, bd, od, reg; 2330 2331 odisp = 0; 2332 2333 /* check to see if we have been given the mod */ 2334 if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER) 2335 reg = BITFIELD(*dbuf->val, bit, bit-2); 2336 else if (mod == GETMOD_BEFORE) { 2337 mod = BITFIELD(*dbuf->val, bit, bit-2); 2338 reg = BITFIELD(*dbuf->val, bit-3, bit-5); 2339 } else { 2340 reg = BITFIELD(*dbuf->val, bit, bit-2); 2341 mod = BITFIELD(*dbuf->val, bit-3, bit-5); 2342 } 2343 switch (mod) { 2344 case DR_DIR: 2345 case AR_DIR: 2346 if (mod == DR_DIR) 2347 PRINT_DREG(dbuf, reg); 2348 else 2349 PRINT_AREG(dbuf, reg); 2350 break; 2351 case AR_DIS: 2352 print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD,reg); 2353 dbuf->used++; 2354 /*FALLTHROUGH*/ 2355 case AR_IND: 2356 case AR_INC: 2357 case AR_DEC: 2358 if (mod == AR_DEC) 2359 addchar('-'); 2360 addchar('('); 2361 PRINT_AREG(dbuf, reg); 2362 addchar(')'); 2363 if (mod == AR_INC) 2364 addchar('+'); 2365 break; 2366 /* mod 6 & 7 are the biggies. */ 2367 case MOD_SPECIAL: 2368 if (reg == 0) { 2369 /* abs short addr */ 2370 print_addr(dbuf, *(dbuf->val + 1 + dd)); 2371 dbuf->used++; 2372 addchar('.'); 2373 addchar('w'); 2374 break; 2375 } else if (reg == 1) { 2376 /* abs long addr */ 2377 print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd)); 2378 dbuf->used += 2; 2379 addchar('.'); 2380 addchar('l'); 2381 break; 2382 } else if (reg == 2) { 2383 /* pc ind displ. xxx(PC) */ 2384 dbuf->used++; 2385 print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD, 2386 -1); 2387 addstr(dbuf,"(pc)"); 2388 break; 2389 } else if (reg == 4) { 2390 /* uses ``sz'' to figure immediate data. */ 2391 if (sz == SIZE_BYTE) { 2392 addchar('#'); 2393 prints(dbuf, 2394 *((char *)dbuf->val + 3+ (dd * 2)), sz); 2395 dbuf->used++; 2396 } else if (sz == SIZE_WORD) { 2397 addchar('#'); 2398 prints(dbuf, *(dbuf->val + 1 + dd), sz); 2399 dbuf->used++; 2400 } else if (sz == SIZE_LONG) { 2401 addchar('#'); 2402 prints(dbuf, *(long *)(dbuf->val + 1 + dd), 2403 sz); 2404 dbuf->used += 2; 2405 } else if (sz == SIZE_QUAD) { 2406 dbuf->used += 4; 2407 addstr(dbuf,"#<quad>"); 2408 } else if (sz == SIZE_SINGLE) { 2409 dbuf->used += 2; 2410 addstr(dbuf,"#<single>"); 2411 } else if (sz == SIZE_DOUBLE) { 2412 dbuf->used += 4; 2413 addstr(dbuf,"#<double>"); 2414 } else if (sz == SIZE_PACKED) { 2415 dbuf->used += 6; 2416 addstr(dbuf,"#<packed>"); 2417 } else if (sz == SIZE_EXTENDED) { 2418 dbuf->used += 6; 2419 addstr(dbuf,"#<extended>"); 2420 } 2421 break; 2422 } 2423 /* standrd PC stuff. */ 2424 /*FALLTHROUGH*/ 2425 case AR_IDX: 2426 ext = *(dbuf->val + 1 + dd); 2427 dbuf->used++; 2428 nval = dbuf->val + 2 + dd; /* set to possible displacements */ 2429 scale = BITFIELD(ext,10,9); 2430 idx = BITFIELD(ext,14,12); 2431 2432 if (ISBITSET(ext,8)) { 2433 /* either base disp, or memory indirect */ 2434 bd = BITFIELD(ext,5,4); 2435 od = BITFIELD(ext,1,0); 2436 if (bd == 1) 2437 disp = 0; 2438 else if (bd == 2) { 2439 dbuf->used++; 2440 disp = *nval++; 2441 } else { 2442 dbuf->used += 2; 2443 disp = *(const long *)nval; 2444 nval += 2; 2445 } 2446 2447 if (od == 1) 2448 odisp = 0; 2449 else if (od == 2) { 2450 dbuf->used++; 2451 odisp = *nval++; 2452 } else if (od == 3) { 2453 dbuf->used += 2; 2454 odisp = *(const long *)nval; 2455 nval += 2; 2456 } 2457 } else { 2458 /* 2459 * We set od and bd to zero, these values are 2460 * not allowed in opcodes that use base and 2461 * outer displacement, e.g. we can tell if we 2462 * are using on of those modes by checking 2463 * `bd' and `od'. 2464 */ 2465 od = 0; 2466 bd = 0; 2467 disp = (char)BITFIELD(ext,7,0); 2468 } 2469 /* 2470 * write everything into buf 2471 */ 2472 addchar('('); 2473 if (od) 2474 addchar('['); /* begin memory indirect xxx-indexed */ 2475 prints(dbuf, disp, 2476 bd == 2 ? SIZE_WORD : 2477 bd == 3 ? SIZE_LONG : 2478 SIZE_BYTE); 2479 addchar(','); 2480 if (bd && ISBITSET(ext,7)) { 2481 addchar('z'); 2482 if (mod != MOD_SPECIAL) 2483 PRINT_AREG(dbuf,reg); 2484 else { 2485 addchar('p'); 2486 addchar('c'); 2487 } 2488 } else if (mod == AR_IDX) 2489 PRINT_AREG(dbuf, reg); 2490 else { 2491 addchar('p'); 2492 addchar('c'); 2493 } 2494 2495 if (od && ISBITSET(ext,2)) 2496 addchar(']'); /* post-indexed. */ 2497 addchar(','); 2498 if (bd && ISBITSET(ext,6)) 2499 addchar('0'); 2500 else { 2501 if (0x8000 & ext) 2502 PRINT_AREG(dbuf, idx); 2503 else 2504 PRINT_DREG(dbuf, idx); 2505 addchar('.'); 2506 addchar(0x800 & ext ? 'l' : 'w'); 2507 if (scale) { 2508 addchar('*'); 2509 addchar('0' + (1 << scale)); 2510 } 2511 } 2512 if (od) { 2513 if (!ISBITSET(ext,2)) 2514 addchar(']'); /* pre-indexed */ 2515 addchar(','); 2516 prints(dbuf, odisp, 2517 od == 2 ? SIZE_WORD : 2518 od == 3 ? SIZE_LONG : 2519 SIZE_BYTE); 2520 } 2521 addchar(')'); 2522 break; 2523 } 2524 *dbuf->casm = 0; 2525} 2526 2527/* mit syntax makes for spaghetti parses */ 2528static void 2529get_modregstr_mit(dis_buffer_t *dbuf, int bit, int mod, int sz, int dd) 2530{ 2531 u_char scale, idx; 2532 const short *nval; 2533 u_short ext; 2534 int disp, odisp, bd, od, reg; 2535 2536 disp = odisp = 0; 2537 /* check to see if we have been given the mod */ 2538 if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER) 2539 reg = BITFIELD(*dbuf->val, bit, bit-2); 2540 else if (mod == GETMOD_BEFORE) { 2541 mod = BITFIELD(*dbuf->val, bit, bit-2); 2542 reg = BITFIELD(*dbuf->val, bit-3, bit-5); 2543 } else { 2544 reg = BITFIELD(*dbuf->val, bit, bit-2); 2545 mod = BITFIELD(*dbuf->val, bit-3, bit-5); 2546 } 2547 switch (mod) { 2548 case DR_DIR: 2549 case AR_DIR: 2550 if (mod == DR_DIR) 2551 PRINT_DREG(dbuf, reg); 2552 else 2553 PRINT_AREG(dbuf, reg); 2554 break; 2555 case AR_DIS: 2556 dbuf->used++; /* tell caller we used an ext word. */ 2557 disp = *(dbuf->val + 1 + dd); 2558 /*FALLTHROUGH*/ 2559 case AR_IND: 2560 case AR_INC: 2561 case AR_DEC: 2562 PRINT_AREG(dbuf, reg); 2563 addchar('@' ); 2564 if (mod == AR_DEC) 2565 addchar('-'); 2566 else if (mod == AR_INC) 2567 addchar('+'); 2568 else if (mod == AR_DIS) { 2569 addchar('('); 2570 print_disp(dbuf, disp, SIZE_WORD, reg); 2571 addchar(')'); 2572 } 2573 break; 2574 /* mod 6 & 7 are the biggies. */ 2575 case MOD_SPECIAL: 2576 if (reg == 0) { 2577 /* abs short addr */ 2578 print_addr(dbuf, *(dbuf->val + 1 + dd)); 2579 dbuf->used++; 2580 break; 2581 } else if (reg == 1) { 2582 /* abs long addr */ 2583 print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd)); 2584 dbuf->used += 2; 2585 break; 2586 } else if (reg == 2) { 2587 /* pc ind displ. pc@(xxx) */ 2588 addstr(dbuf,"pc@("); 2589 print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD, -1); 2590 dbuf->used++; 2591 addchar(')'); 2592 break; 2593 } else if (reg == 4) { 2594 /* uses ``sz'' to figure immediate data. */ 2595 if (sz == SIZE_BYTE) { 2596 addchar('#'); 2597 prints(dbuf, 2598 *((char *)dbuf->val + 3 + (dd * 2)), sz); 2599 dbuf->used++; 2600 } else if (sz == SIZE_WORD) { 2601 addchar('#'); 2602 prints(dbuf, *(dbuf->val + 1 + dd), sz); 2603 dbuf->used++; 2604 } else if (sz == SIZE_LONG) { 2605 addchar('#'); 2606 prints(dbuf, *(long *)(dbuf->val + 1 + dd), 2607 sz); 2608 dbuf->used += 2; 2609 } else if (sz == SIZE_QUAD) { 2610 dbuf->used += 4; 2611 addstr(dbuf,"#<quad>"); 2612 } else if (sz == SIZE_SINGLE) { 2613 dbuf->used += 2; 2614 addstr(dbuf,"#<single>"); 2615 } else if (sz == SIZE_DOUBLE) { 2616 dbuf->used += 4; 2617 addstr(dbuf,"#<double>"); 2618 } else if (sz == SIZE_PACKED) { 2619 dbuf->used += 6; 2620 addstr(dbuf,"#<packed>"); 2621 } else if (sz == SIZE_EXTENDED) { 2622 dbuf->used += 6; 2623 addstr(dbuf,"#<extended>"); 2624 } 2625 break; 2626 } 2627 /* standrd PC stuff. */ 2628 /*FALLTHROUGH*/ 2629 case AR_IDX: 2630 dbuf->used++; /* indicate use of ext word. */ 2631 ext = *(dbuf->val + 1 + dd); 2632 nval = dbuf->val + 2 + dd; /* set to possible displacements */ 2633 scale = BITFIELD(ext,10,9); 2634 idx = BITFIELD(ext,14,12); 2635 2636 if (ISBITSET(ext,8)) { 2637 /* either base disp, or memory indirect */ 2638 bd = BITFIELD(ext,5,4); 2639 od = BITFIELD(ext,1,0); 2640 if (bd == 1) 2641 disp = 0; 2642 else if (bd == 2) { 2643 dbuf->used++; 2644 disp = *nval++; 2645 } else { 2646 dbuf->used += 2; 2647 disp = *(const long *)nval; 2648 nval += 2; 2649 } 2650 2651 if (od == 1) 2652 odisp = 0; 2653 else if (od == 2) { 2654 dbuf->used++; 2655 odisp = *nval++; 2656 } else if (od == 3) { 2657 dbuf->used += 2; 2658 odisp = *(const long *)nval; 2659 nval += 2; 2660 } 2661 } else { 2662 /* 2663 * We set od and bd to zero, these values are 2664 * not allowed in opcodes that use base and 2665 * outer displacement, e.g. we can tell if we 2666 * are using on of those modes by checking 2667 * `bd' and `od'. 2668 */ 2669 od = 0; 2670 bd = 0; 2671 disp = (char)BITFIELD(ext,7,0); 2672 } 2673 /* 2674 * write everything into buf 2675 */ 2676 /* if base register not suppresed */ 2677 if (mod == AR_IDX && (!bd || !ISBITSET(ext,7))) 2678 PRINT_AREG(dbuf, reg); 2679 else if (mod == MOD_SPECIAL && ISBITSET(ext,7)) { 2680 addchar('z'); 2681 addchar('p'); 2682 addchar('c'); 2683 } else if (mod == MOD_SPECIAL) { 2684 addchar('p'); 2685 addchar('c'); 2686 } 2687 addchar('@'); 2688 addchar('('); 2689 2690 if (bd && bd != 1) { 2691 prints(dbuf, disp, 2692 bd == 2 ? SIZE_WORD : 2693 bd == 3 ? SIZE_LONG : 2694 SIZE_BYTE); 2695 if (od && !ISBITSET(ext,6) && !ISBITSET(ext,2)) 2696 /* Pre-indexed and not suppressing index */ 2697 addchar(','); 2698 else if (od && ISBITSET(ext,2)) { 2699 /* Post-indexed */ 2700 addchar(')'); 2701 addchar('@'); 2702 addchar('('); 2703 } else if (!od) 2704 addchar(','); 2705 } else if (!bd) { 2706 /* don't forget simple 8 bit displacement. */ 2707 prints(dbuf, disp, 2708 bd == 2 ? SIZE_WORD : 2709 bd == 3 ? SIZE_LONG : 2710 SIZE_BYTE); 2711 addchar(','); 2712 } 2713 2714 /* Post-indexed? */ 2715 if (od && ISBITSET(ext,2)) { 2716 /* have displacement? */ 2717 if (od != 1) { 2718 prints(dbuf, odisp, 2719 od == 2 ? SIZE_WORD : 2720 od == 3 ? SIZE_LONG : 2721 SIZE_BYTE); 2722 addchar(','); 2723 } 2724 } 2725 2726 if (!bd || !ISBITSET(ext,6)) { 2727 if (ISBITSET(ext,15)) 2728 PRINT_AREG(dbuf,idx); 2729 else 2730 PRINT_DREG(dbuf,idx); 2731 addchar(':'); 2732 addchar(ISBITSET(ext,11) ? 'l' : 'w'); 2733 if (scale) { 2734 addchar(':'); 2735 addchar('0' + (1 << scale)); 2736 } 2737 } 2738 /* pre-indexed? */ 2739 if (od && !ISBITSET(ext,2)) { 2740 if (od != 1) { 2741 addchar(')'); 2742 addchar('@'); 2743 addchar('('); 2744 prints(dbuf, odisp, 2745 od == 2 ? SIZE_WORD : 2746 od == 3 ? SIZE_LONG : 2747 SIZE_BYTE); 2748 } 2749 } 2750 addchar(')'); 2751 break; 2752 } 2753 *dbuf->casm = 0; 2754} 2755 2756/* 2757 * Given a disassembly buffer ``dbuf'' and a starting bit of the 2758 * mod|reg field ``bit'' (or just a reg field if ``mod'' is not 2759 * GETMOD_BEFORE or GETMOD_AFTER), disassemble and write into ``dbuf'' 2760 * the mod|reg pair. 2761 */ 2762static void 2763get_modregstr(dis_buffer_t *dbuf, int bit, int mod, int sz, int dispdisp) 2764{ 2765 if (dbuf->mit) 2766 get_modregstr_mit(dbuf,bit,mod,sz,dispdisp); 2767 else 2768 get_modregstr_moto(dbuf,bit,mod,sz,dispdisp); 2769} 2770 2771/* 2772 * given a bit position ``bit'' in the current ``dbuf''->val 2773 * and the ``base'' string of the opcode, append the full 2774 * opcode name including condition found at ``bit''. 2775 */ 2776static void 2777make_cond(dis_buffer_t *dbuf, int bit, const char *base) 2778{ 2779 int cc; 2780 const char *ccs; 2781 2782 cc = BITFIELD(*dbuf->val,bit,bit-3); 2783 ccs = cc_table[cc&15]; 2784 2785 addstr(dbuf, base); 2786 addstr(dbuf, ccs); 2787} 2788 2789static void 2790print_fcond(dis_buffer_t *dbuf, char cp) 2791{ 2792 addstr(dbuf,fpcc_table[cp&31]); /* XXX - not 63 ?*/ 2793} 2794 2795static void 2796print_mcond(dis_buffer_t *dbuf, char cp) 2797{ 2798 addstr(dbuf,mmcc_table[cp&15]); 2799} 2800 2801/* 2802 * given dis_buffer_t ``dbuf'' get the immediate value from the 2803 * extension words following current instruction, output a 2804 * hash (``#'') sign and the value. Increment the ``dbuf''->used 2805 * field accordingly. 2806 */ 2807static void 2808get_immed(dis_buffer_t *dbuf,int sz) 2809{ 2810 addchar('#'); 2811 switch (sz) { 2812 case SIZE_BYTE: 2813 prints(dbuf, BITFIELD(*(dbuf->val + 1),7,0), SIZE_BYTE); 2814 dbuf->used++; 2815 break; 2816 case SIZE_WORD: 2817 prints(dbuf, *(dbuf->val + 1), SIZE_WORD); 2818 dbuf->used++; 2819 break; 2820 case SIZE_LONG: 2821 prints(dbuf, *(long *)(dbuf->val + 1), SIZE_LONG); 2822 dbuf->used += 2; 2823 break; 2824 } 2825 return; 2826} 2827 2828static void 2829get_fpustdGEN(dis_buffer_t *dbuf, u_short ext, const char *name) 2830{ 2831 int sz; 2832 2833 /* 2834 * If bit seven is set, its a 040 s/d opcode, then if bit 2 is 2835 * set its "d". This is not documented, however thats the way 2836 * it is. 2837 */ 2838 2839 sz = 0; 2840 addchar(*name++); 2841 if (ISBITSET(ext,7)) { 2842 if(ISBITSET(ext,2)) 2843 addchar('d'); 2844 else 2845 addchar('s'); 2846 } 2847 addstr(dbuf,name); 2848 2849 if (ISBITSET(ext,14)) { 2850 switch (BITFIELD(ext,12,10)) { 2851 case 0: 2852 addchar('l'); 2853 sz = SIZE_LONG; 2854 break; 2855 case 1: 2856 addchar('s'); 2857 sz = SIZE_SINGLE; 2858 break; 2859 case 2: 2860 addchar('x'); 2861 sz = SIZE_EXTENDED; 2862 break; 2863 case 3: 2864 addchar('p'); 2865 sz = SIZE_PACKED; 2866 break; 2867 case 4: 2868 addchar('w'); 2869 sz = SIZE_WORD; 2870 break; 2871 case 5: 2872 addchar('d'); 2873 sz = SIZE_DOUBLE; 2874 break; 2875 case 6: 2876 addchar('b'); 2877 sz = SIZE_BYTE; 2878 break; 2879 } 2880 addchar('\t'); 2881 get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); 2882 if (BITFIELD(ext,6,3) == 6) { 2883 addchar(','); 2884 PRINT_FPREG(dbuf, BITFIELD(ext,2,0)); 2885 addchar(':'); 2886 PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); 2887 } else if (BITFIELD(ext,5,0) != FTST) { 2888 addchar(','); 2889 PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); 2890 } 2891 } else { 2892 addchar('x'); 2893 addchar('\t'); 2894 PRINT_FPREG(dbuf, BITFIELD(ext,12,10)); 2895 if (BITFIELD(ext,6,3) == 6) { 2896 addchar(','); 2897 PRINT_FPREG(dbuf, BITFIELD(ext,2,0)); 2898 addchar(':'); 2899 PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); 2900 } else if (BITFIELD(ext,5,0) != FTST) { 2901 addchar(','); 2902 PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); 2903 } 2904 } 2905} 2906 2907#if 0 2908static u_long 2909get_areg_val(int reg) 2910{ 2911 return 0; 2912} 2913#endif 2914 2915/* 2916 * given value ``disp'' print it to ``dbuf''->buf. ``rel'' is a 2917 * register number 0-7 (a0-a7), or -1 (pc). Thus possible extra info 2918 * could be output to the ``dbuf''->info buffer. 2919 */ 2920static void 2921print_disp(dis_buffer_t *dbuf, int disp, int sz, int rel) 2922{ 2923 db_expr_t diff; 2924 db_sym_t sym; 2925 const char *symname; 2926 u_long nv; 2927 2928 prints(dbuf, disp, sz); 2929 2930 if (rel == -1) 2931 /* XXX This may be wrong for a couple inst. */ 2932 nv = disp + (u_int)dbuf->val + 2; 2933 else 2934 return; /* nv = get_areg_val(rel); */ 2935 2936 diff = INT_MAX; 2937 symname = NULL; 2938 sym = db_search_symbol(nv, DB_STGY_PROC, &diff); 2939 db_symbol_values(sym, &symname, 0); 2940 2941 if (symname) { 2942 iaddstr(dbuf, "disp:"); 2943 iaddstr(dbuf, symname); 2944 iaddchar('+'); 2945 iprintu(dbuf, diff, SIZE_LONG); 2946 iaddchar(' '); 2947 *dbuf->cinfo = 0; 2948 } 2949} 2950 2951static void 2952print_addr(dis_buffer_t *dbuf, u_long addr) 2953{ 2954 db_expr_t diff; 2955 db_sym_t sym; 2956 const char *symname; 2957 2958 diff = INT_MAX; 2959 symname = NULL; 2960 sym = db_search_symbol(addr, DB_STGY_ANY, &diff); 2961 db_symbol_values(sym, &symname, 0); 2962 2963 if (symname) { 2964 if (diff == 0) 2965 addstr(dbuf,symname); 2966 else { 2967 addchar('<'); 2968 addstr(dbuf,symname); 2969 addchar('+'); 2970 printu(dbuf, diff, SIZE_LONG); 2971 addchar('>'); 2972 *dbuf->casm = 0; 2973 } 2974 iaddstr(dbuf,"addr:"); 2975 iprintu(dbuf, addr, SIZE_LONG); 2976 iaddchar(' '); 2977 *dbuf->cinfo = 0; 2978 } else { 2979 printu(dbuf, addr, SIZE_LONG); 2980 } 2981} 2982 2983static void 2984prints(dis_buffer_t *dbuf, int val, int sz) 2985{ 2986 extern int db_radix; 2987 2988 if (val == 0) { 2989 dbuf->casm[0] = '0'; 2990 dbuf->casm[1] = 0; 2991 } else if (sz == SIZE_BYTE) 2992 prints_wb(dbuf, (char)val, sz, db_radix); 2993 else if (sz == SIZE_WORD) 2994 prints_wb(dbuf, (short)val, sz, db_radix); 2995 else 2996 prints_wb(dbuf, (long)val, sz, db_radix); 2997 2998 dbuf->casm = &dbuf->casm[strlen(dbuf->casm)]; 2999} 3000 3001#if 0 3002static void 3003iprints(dis_buffer_t *dbuf, int val, int sz) 3004{ 3005 extern int db_radix; 3006 3007 if (val == 0) { 3008 dbuf->cinfo[0] = '0'; 3009 dbuf->cinfo[1] = 0; 3010 } else if (sz == SIZE_BYTE) 3011 iprints_wb(dbuf, (char)val, sz, db_radix); 3012 else if (sz == SIZE_WORD) 3013 iprints_wb(dbuf, (short)val, sz, db_radix); 3014 else 3015 iprints_wb(dbuf, (long)val, sz, db_radix); 3016 3017 dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)]; 3018} 3019#endif 3020 3021static void 3022printu(dis_buffer_t *dbuf, u_int val, int sz) 3023{ 3024 extern int db_radix; 3025 3026 if (val == 0) { 3027 dbuf->casm[0] = '0'; 3028 dbuf->casm[1] = 0; 3029 } else if (sz == SIZE_BYTE) 3030 printu_wb(dbuf, (u_char)val, sz, db_radix); 3031 else if (sz == SIZE_WORD) 3032 printu_wb(dbuf, (u_short)val, sz, db_radix); 3033 else 3034 printu_wb(dbuf, (u_long)val, sz, db_radix); 3035 dbuf->casm = &dbuf->casm[strlen(dbuf->casm)]; 3036} 3037 3038static void 3039iprintu(dis_buffer_t *dbuf, u_int val, int sz) 3040{ 3041 extern int db_radix; 3042 3043 if (val == 0) { 3044 dbuf->cinfo[0] = '0'; 3045 dbuf->cinfo[1] = 0; 3046 } else if (sz == SIZE_BYTE) 3047 iprintu_wb(dbuf, (u_char)val, sz, db_radix); 3048 else if (sz == SIZE_WORD) 3049 iprintu_wb(dbuf, (u_short)val, sz, db_radix); 3050 else 3051 iprintu_wb(dbuf, (u_long)val, sz, db_radix); 3052 dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)]; 3053} 3054 3055static void 3056printu_wb(dis_buffer_t *dbuf, u_int val, int sz, int base) 3057{ 3058 static char buf[sizeof(long) * NBBY / 3 + 2]; 3059 char *p, ch; 3060 3061 if (base != 10) { 3062 addchar('0'); 3063 if (base != 8) { 3064 base = 16; 3065 addchar('x'); 3066 } 3067 } 3068 3069 p = buf; 3070 do { 3071 *++p = hexdigits[val % base]; 3072 } while (val /= base); 3073 3074 while ((ch = *p--)) 3075 addchar(ch); 3076 3077 *dbuf->casm = 0; 3078} 3079 3080static void 3081prints_wb(dis_buffer_t *dbuf, int val, int sz, int base) 3082{ 3083 if (val < 0) { 3084 addchar('-'); 3085 val = -val; 3086 } 3087 printu_wb(dbuf, val, sz, base); 3088} 3089 3090static void 3091iprintu_wb(dis_buffer_t *dbuf, u_int val, int sz, int base) 3092{ 3093 static char buf[sizeof(long) * NBBY / 3 + 2]; 3094 char *p, ch; 3095 3096 if (base != 10) { 3097 iaddchar('0'); 3098 if (base != 8) { 3099 base = 16; 3100 iaddchar('x'); 3101 } 3102 } 3103 3104 p = buf; 3105 do { 3106 *++p = hexdigits[val % base]; 3107 } while (val /= base); 3108 3109 while ((ch = *p--)) 3110 iaddchar(ch); 3111 3112 *dbuf->cinfo = 0; 3113} 3114 3115#if 0 3116static void 3117iprints_wb(dis_buffer_t *dbuf, int val, int sz, int base) 3118{ 3119 if (val < 0) { 3120 iaddchar('-'); 3121 val = -val; 3122 } 3123 iprintu_wb(dbuf, val, sz, base); 3124} 3125#endif 3126 3127static void 3128prints_bf(dis_buffer_t *dbuf, int val, int sb, int eb) 3129{ 3130 if (ISBITSET(val,sb)) 3131 val = (~0 & ~BITFIELD(~0, sb, eb)) | BITFIELD(val, sb, eb); 3132 else 3133 val = BITFIELD(val,sb,eb); 3134 3135 prints(dbuf, val, SIZE_LONG); 3136} 3137 3138static void 3139printu_bf(dis_buffer_t *dbuf, u_int val, int sb, int eb) 3140{ 3141 printu(dbuf,BITFIELD(val,sb,eb),SIZE_LONG); 3142} 3143