fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1980 lines 40 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/ppc405/disasm.c * 7 * Created: 2003-11-08 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2003-2018 Hampa Hug <hampa@hampa.ch> * 9 * Copyright: (C) 2003-2006 Lukas Ruf <ruf@lpr.ch> * 10 *****************************************************************************/ 11 12/***************************************************************************** 13 * This program is free software. You can redistribute it and / or modify it * 14 * under the terms of the GNU General Public License version 2 as published * 15 * by the Free Software Foundation. * 16 * * 17 * This program is distributed in the hope that it will be useful, but * 18 * WITHOUT ANY WARRANTY, without even the implied warranty of * 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 20 * Public License for more details. * 21 *****************************************************************************/ 22 23/***************************************************************************** 24 * This software was developed at the Computer Engineering and Networks * 25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. * 26 *****************************************************************************/ 27 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32 33#include "ppc405.h" 34#include "internal.h" 35 36 37typedef void (*p405_disasm_f) (p405_disasm_t *dis); 38 39typedef struct { 40 unsigned op; 41 p405_disasm_f fct; 42} p405_disasm_list_t; 43 44 45static void p405_disasm_init (void); 46 47static p405_disasm_f p405_op13[1024]; 48static p405_disasm_f p405_op1f[1024]; 49static p405_disasm_f p405_op[64]; 50 51 52#define ARG_NONE 0 53#define ARG_RA 1 54#define ARG_RB 2 55#define ARG_RS 3 56#define ARG_RT 4 57#define ARG_RA0 5 58#define ARG_SIMM16 6 59#define ARG_UIMM16 7 60#define ARG_IMM16S 8 61#define ARG_UINT3 9 62#define ARG_UINT5 10 63#define ARG_UINT8 11 64#define ARG_UINT16 12 65#define ARG_UINT32 13 66#define ARG_CRBIT 14 67#define ARG_SPRN 15 68#define ARG_DCRN 16 69 70 71#define OPF_OE 0x0001 72#define OPF_RC 0x0002 73 74 75static char p405_disasm_inited = 0; 76 77static 78char *p405_cr_name[2][4] = { 79 { "lt", "gt", "eq", "so" }, 80 { "ge", "le", "ne", "ns" } 81}; 82 83 84static 85const char *disasm_get_spr (unsigned sprn) 86{ 87 switch (sprn) { 88 case P405_SPRN_CCR0: 89 return ("ccr0"); 90 91 case P405_SPRN_CTR: 92 return ("ctr"); 93 94 case P405_SPRN_DAC1: 95 return ("dac1"); 96 97 case P405_SPRN_DAC2: 98 return ("dac2"); 99 100 case P405_SPRN_DBCR0: 101 return ("dbcr0"); 102 103 case P405_SPRN_DBCR1: 104 return ("dbcr1"); 105 106 case P405_SPRN_DBSR: 107 return ("dbsr"); 108 109 case P405_SPRN_DCCR: 110 return ("dccr"); 111 112 case P405_SPRN_DCWR: 113 return ("dcwr"); 114 115 case P405_SPRN_DVC1: 116 return ("dvc1"); 117 118 case P405_SPRN_DVC2: 119 return ("dvc2"); 120 121 case P405_SPRN_DEAR: 122 return ("dear"); 123 124 case P405_SPRN_ESR: 125 return ("esr"); 126 127 case P405_SPRN_EVPR: 128 return ("evpr"); 129 130 case P405_SPRN_IAC1: 131 return ("iac1"); 132 133 case P405_SPRN_IAC2: 134 return ("iac2"); 135 136 case P405_SPRN_IAC3: 137 return ("iac3"); 138 139 case P405_SPRN_IAC4: 140 return ("iac4"); 141 142 case P405_SPRN_ICCR: 143 return ("iccr"); 144 145 case P405_SPRN_ICDBDR: 146 return ("icdbdr"); 147 148 case P405_SPRN_LR: 149 return ("lr"); 150 151 case P405_SPRN_PID: 152 return ("pid"); 153 154 case P405_SPRN_PIT: 155 return ("pit"); 156 157 case P405_SPRN_PVR: 158 return ("pvr"); 159 160 case P405_SPRN_SGR: 161 return ("sgr"); 162 163 case P405_SPRN_SLER: 164 return ("sler"); 165 166 case P405_SPRN_SPRG0: 167 return ("sprg0"); 168 169 case P405_SPRN_SPRG1: 170 return ("sprg1"); 171 172 case P405_SPRN_SPRG2: 173 return ("sprg2"); 174 175 case P405_SPRN_SPRG3: 176 return ("sprg3"); 177 178 case P405_SPRN_SPRG4: 179 return ("sprg4"); 180 181 case P405_SPRN_SPRG5: 182 return ("sprg5"); 183 184 case P405_SPRN_SPRG6: 185 return ("sprg6"); 186 187 case P405_SPRN_SPRG7: 188 return ("sprg7"); 189 190 case P405_SPRN_SPRG4R: 191 return ("sprg4r"); 192 193 case P405_SPRN_SPRG5R: 194 return ("sprg5r"); 195 196 case P405_SPRN_SPRG6R: 197 return ("sprg6r"); 198 199 case P405_SPRN_SPRG7R: 200 return ("sprg7r"); 201 202 case P405_SPRN_SRR0: 203 return ("srr0"); 204 205 case P405_SPRN_SRR1: 206 return ("srr1"); 207 208 case P405_SPRN_SRR2: 209 return ("srr2"); 210 211 case P405_SPRN_SRR3: 212 return ("srr3"); 213 214 case P405_SPRN_SU0R: 215 return ("su0r"); 216 217 case P405_SPRN_TBL: 218 case P405_SPRN_TBLU: 219 return ("tbl"); 220 221 case P405_SPRN_TBU: 222 case P405_SPRN_TBUU: 223 return ("tbu"); 224 225 case P405_SPRN_TCR: 226 return ("tcr"); 227 228 case P405_SPRN_TSR: 229 return ("tsr"); 230 231 case P405_SPRN_USPRG0: 232 return ("usprg0"); 233 234 case P405_SPRN_XER: 235 return ("xer"); 236 237 case P405_SPRN_ZPR: 238 return ("zpr"); 239 } 240 241 return (NULL); 242} 243 244static 245void disasm_dw (p405_disasm_t *dis, uint32_t val) 246{ 247 dis->argn = 1; 248 strcpy (dis->op, "dw"); 249 sprintf (dis->arg1, "%08lx", (unsigned long) val); 250} 251 252static 253void disasm_arg_reg (p405_disasm_t *dis, char *dst, unsigned r) 254{ 255 r &= 0x1f; 256 257 *(dst++) = 'r'; 258 259 if (r > 9) { 260 *(dst++) = '0' + (r / 10); 261 } 262 263 *(dst++) = '0' + (r % 10); 264 265 *dst = 0; 266 267 dis->reg |= 1UL << r; 268} 269 270static 271void disasm_arg_imm32 (char *dst, unsigned long val) 272{ 273 unsigned i, tmp; 274 275 dst += 8; 276 *dst = 0; 277 278 for (i = 0; i < 8; i++) { 279 tmp = val & 0x0f; 280 val = val >> 4; 281 282 if (tmp < 10) { 283 tmp += '0'; 284 } 285 else { 286 tmp = tmp - 10 + 'a'; 287 } 288 289 *(--dst) = tmp; 290 } 291} 292 293static 294void disasm_arg (p405_disasm_t *dis, char *dst, uint32_t ir, unsigned arg, uint32_t par) 295{ 296 switch (arg) { 297 case ARG_NONE: 298 dst[0] = 0; 299 break; 300 301 case ARG_RA: 302 disasm_arg_reg (dis, dst, p405_get_ir_ra (ir)); 303 break; 304 305 case ARG_RB: 306 disasm_arg_reg (dis, dst, p405_get_ir_rb (ir)); 307 break; 308 309 case ARG_RS: 310 disasm_arg_reg (dis, dst, p405_get_ir_rs (ir)); 311 break; 312 313 case ARG_RT: 314 disasm_arg_reg (dis, dst, p405_get_ir_rt (ir)); 315 break; 316 317 case ARG_RA0: 318 if (p405_get_ir_ra (ir) == 0) { 319 dst[0] = '0'; 320 dst[1] = 0; 321 } 322 else { 323 disasm_arg_reg (dis, dst, p405_get_ir_ra (ir)); 324 } 325 break; 326 327 case ARG_SIMM16: 328 disasm_arg_imm32 (dst, p405_sext (ir, 16)); 329 break; 330 331 case ARG_UIMM16: 332 disasm_arg_imm32 (dst, p405_uext (ir, 16)); 333 break; 334 335 case ARG_IMM16S: 336 disasm_arg_imm32 (dst, (ir & 0xffff) << 16); 337 break; 338 339 case ARG_UINT3: 340 sprintf (dst, "%x", (unsigned) (par & 0x07)); 341 break; 342 343 case ARG_UINT5: 344 sprintf (dst, "%02x", (unsigned) (par & 0x1f)); 345 break; 346 347 case ARG_UINT8: 348 sprintf (dst, "%02x", (unsigned) (par & 0xff)); 349 break; 350 351 case ARG_UINT16: 352 sprintf (dst, "%04x", (unsigned) (par & 0xffffU)); 353 break; 354 355 case ARG_UINT32: 356 disasm_arg_imm32 (dst, par & 0xffffffff); 357 break; 358 359 case ARG_CRBIT: 360 sprintf (dst, "%s[%u]", p405_cr_name[0][par & 0x03], (unsigned) par / 4); 361 break; 362 363 case ARG_SPRN: { 364 const char *spr = disasm_get_spr (par); 365 if (spr != NULL) { 366 strcpy (dst, spr); 367 } 368 else { 369 sprintf (dst, "%03x", par); 370 } 371 } 372 break; 373 374 case ARG_DCRN: 375 sprintf (dst, "%03x", par); 376 break; 377 } 378} 379 380static 381int disasm_op0 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res) 382{ 383 if (dis->ir & res) { 384 disasm_dw (dis, dis->ir); 385 return (1); 386 } 387 388 strcpy (dis->op, op); 389 390 if (opf & OPF_OE) { 391 if (p405_get_ir_oe (dis->ir)) { 392 strcat (dis->op, "o"); 393 } 394 } 395 396 if (opf & OPF_RC) { 397 if (p405_get_ir_rc (dis->ir)) { 398 strcat (dis->op, "."); 399 } 400 } 401 402 dis->argn = 0; 403 404 return (0); 405} 406 407static 408int disasm_op1 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res, 409 unsigned arg1, uint32_t par1) 410{ 411 if (disasm_op0 (dis, op, opf, res)) { 412 return (1); 413 } 414 415 dis->argn = 1; 416 disasm_arg (dis, dis->arg1, dis->ir, arg1, par1); 417 418 return (0); 419} 420 421static 422int disasm_op2 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res, 423 unsigned arg1, unsigned arg2, uint32_t par1, uint32_t par2) 424{ 425 if (disasm_op1 (dis, op, opf, res, arg1, par1)) { 426 return (1); 427 } 428 429 dis->argn = 2; 430 disasm_arg (dis, dis->arg2, dis->ir, arg2, par2); 431 432 return (0); 433} 434 435static 436int disasm_op3 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res, 437 unsigned arg1, unsigned arg2, unsigned arg3, 438 uint32_t par1, uint32_t par2, uint32_t par3) 439{ 440 if (disasm_op2 (dis, op, opf, res, arg1, arg2, par1, par2)) { 441 return (1); 442 } 443 444 dis->argn = 3; 445 disasm_arg (dis, dis->arg3, dis->ir, arg3, par3); 446 447 return (0); 448} 449 450static 451int disasm_op4 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res, 452 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, 453 uint32_t par1, uint32_t par2, uint32_t par3, uint32_t par4) 454{ 455 if (disasm_op3 (dis, op, opf, res, arg1, arg2, arg3, par1, par2, par3)) { 456 return (1); 457 } 458 459 dis->argn = 4; 460 disasm_arg (dis, dis->arg4, dis->ir, arg4, par4); 461 462 return (0); 463} 464 465static 466int disasm_op5 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res, 467 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5, 468 uint32_t par1, uint32_t par2, uint32_t par3, uint32_t par4, uint32_t par5) 469{ 470 if (disasm_op4 (dis, op, opf, res, arg1, arg2, arg3, arg4, par1, par2, par3, par4)) { 471 return (1); 472 } 473 474 dis->argn = 5; 475 disasm_arg (dis, dis->arg5, dis->ir, arg5, par5); 476 477 return (0); 478} 479 480static 481void disasm_u32 (char *dst, unsigned long val) 482{ 483 sprintf (dst, "%08lx", val & 0xffffffffUL); 484} 485 486static 487void disasm_undefined (p405_disasm_t *dis) 488{ 489 disasm_dw (dis, dis->ir); 490} 491 492/* crxxx bt, ba, bb */ 493static 494void disasm_crxxx (p405_disasm_t *dis, const char *op) 495{ 496 disasm_op3 (dis, op, 0, 0x01, ARG_CRBIT, ARG_CRBIT, ARG_CRBIT, 497 p405_get_ir_rt (dis->ir), p405_get_ir_ra (dis->ir), p405_get_ir_rb (dis->ir) 498 ); 499} 500 501 502/* branch conditional */ 503static 504void disasm_bc (p405_disasm_t *dis, const char *op, const char *dst, 505 unsigned bo, unsigned bi, int aa, int lk) 506{ 507 int bo0, bo1, bo2, bo3; 508 char buf[64]; 509 510 bo0 = (bo & 0x10) != 0; 511 bo1 = (bo & 0x08) != 0; 512 bo2 = (bo & 0x04) != 0; 513 bo3 = (bo & 0x02) != 0; 514 515 strcpy (dis->op, "b"); 516 517 dis->argn = 0; 518 519 if (bo2 == 0) { 520 strcat (dis->op, "d"); 521 } 522 523 if (bo0 == 0) { 524 strcat (dis->op, p405_cr_name[!bo1][bi & 0x03]); 525 526 if (bi > 3) { 527 sprintf (buf, "[%u]", bi / 4); 528 strcat (dis->op, buf); 529 } 530 } 531 532 strcat (dis->op, op); 533 534 if (lk) { 535 strcat (dis->op, "l"); 536 dis->flags |= P405_DFLAG_CALL; 537 } 538 539 if (aa) { 540 strcat (dis->op, "a"); 541 } 542 543 if (bo2 == 0) { 544 if (bo3) { 545 strcat (dis->op, "="); 546 } 547 else { 548 strcat (dis->op, ">"); 549 } 550 } 551 552 if (dst != NULL) { 553 strcpy (dis->arg1, dst); 554 dis->argn += 1; 555 } 556} 557 558 559static void opd_ud (p405_disasm_t *dis) 560{ 561 disasm_undefined (dis); 562} 563 564/* 03: twi to, ra, simm16 */ 565static 566void opd_03 (p405_disasm_t *dis) 567{ 568 disasm_op3 (dis, "twi", 0, 0, ARG_UINT5, ARG_RA, ARG_SIMM16, 569 p405_bits (dis->ir, 6, 5), 0, 0 570 ); 571} 572 573/* 07: mulli rt, ra, simm16 */ 574static 575void opd_07 (p405_disasm_t *dis) 576{ 577 disasm_op3 (dis, "mulli", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 578} 579 580/* 08: subfic rt, ra, simm16 */ 581static 582void opd_08 (p405_disasm_t *dis) 583{ 584 disasm_op3 (dis, "subfic", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 585} 586 587/* 0A: cmpli bf, ra, simm16 */ 588static 589void opd_0a (p405_disasm_t *dis) 590{ 591 disasm_op3 (dis, "cmpli", 0, 0, 592 ARG_UINT3, ARG_RA, ARG_SIMM16, (dis->ir >> 23) & 0x07, 0, 0 593 ); 594} 595 596/* 0B: cmpi bf, ra, simm16 */ 597static 598void opd_0b (p405_disasm_t *dis) 599{ 600 disasm_op3 (dis, "cmpi", 0, 0, 601 ARG_UINT3, ARG_RA, ARG_SIMM16, (dis->ir >> 23) & 0x07, 0, 0 602 ); 603} 604 605/* 0C: addic rt, ra, simm16 */ 606static 607void opd_0c (p405_disasm_t *dis) 608{ 609 disasm_op3 (dis, "addic", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 610} 611 612/* 0D: addic. rt, ra, simm16 */ 613static 614void opd_0d (p405_disasm_t *dis) 615{ 616 disasm_op3 (dis, "addic.", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 617} 618 619/* 0E: addi rt, ra0, simm16 */ 620static 621void opd_0e (p405_disasm_t *dis) 622{ 623 if (p405_get_ir_ra (dis->ir) == 0) { 624 disasm_op2 (dis, "li", 0, 0, ARG_RT, ARG_SIMM16, 0, 0); 625 } 626 else { 627 disasm_op3 (dis, "addi", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 628 } 629} 630 631/* 0F: addis rt, ra0, simm16 */ 632static 633void opd_0f (p405_disasm_t *dis) 634{ 635 if (p405_get_ir_ra (dis->ir) == 0) { 636 disasm_op2 (dis, "lis", 0, 0, ARG_RT, ARG_IMM16S, 0, 0); 637 } 638 else { 639 disasm_op3 (dis, "addis", 0, 0, ARG_RT, ARG_RA0, ARG_IMM16S, 0, 0, 0); 640 } 641} 642 643/* 10: bc/bcl/bca/bcla target */ 644static 645void opd_10 (p405_disasm_t *dis) 646{ 647 uint32_t bd; 648 char dst[256]; 649 650 bd = p405_sext (dis->ir & 0xfffcUL, 16); 651 652 if (p405_get_ir_aa (dis->ir) == 0) { 653 bd = (dis->pc + bd) & 0xffffffffUL; 654 } 655 656 if (p405_get_ir_lk (dis->ir)) { 657 dis->flags |= P405_DFLAG_CALL; 658 } 659 660 disasm_u32 (dst, bd); 661 662 disasm_bc (dis, "", dst, 663 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f, 664 (dis->ir & P405_IR_AA) != 0, (dis->ir & P405_IR_LK) != 0 665 ); 666} 667 668/* 11: sc */ 669static 670void opd_11 (p405_disasm_t *dis) 671{ 672 disasm_op0 (dis, "sc", 0, 0x03fffffdUL); 673 dis->flags |= P405_DFLAG_CALL; 674} 675 676/* 12: b/bl/ba/bla target */ 677static 678void opd_12 (p405_disasm_t *dis) 679{ 680 uint32_t li; 681 682 strcpy (dis->op, "b"); 683 684 li = p405_sext (dis->ir, 26) & 0xfffffffcUL; 685 686 if (p405_get_ir_lk (dis->ir)) { 687 strcat (dis->op, "l"); 688 dis->flags |= P405_DFLAG_CALL; 689 } 690 691 if (p405_get_ir_aa (dis->ir)) { 692 strcat (dis->op, "a"); 693 disasm_u32 (dis->arg1, li); 694 } 695 else { 696 disasm_u32 (dis->arg1, dis->pc + li); 697 } 698 699 dis->argn = 1; 700} 701 702/* 13 000: mcrf bf, bfa */ 703static 704void opd_13_000 (p405_disasm_t *dis) 705{ 706 disasm_op2 (dis, "mcrf", 0, 0x0063f801UL, ARG_UINT3, ARG_UINT3, 707 p405_get_ir_rt (dis->ir) >> 2, p405_get_ir_ra (dis->ir) >> 2 708 ); 709} 710 711/* 13 010: bclr/bclrl */ 712static 713void opd_13_010 (p405_disasm_t *dis) 714{ 715 if (p405_get_ir_lk (dis->ir)) { 716 dis->flags |= P405_DFLAG_CALL; 717 } 718 719 disasm_bc (dis, "lr", NULL, 720 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f, 721 0, (dis->ir & P405_IR_LK) != 0 722 ); 723} 724 725/* 13 021: crnor bt, ba, bb */ 726static 727void opd_13_021 (p405_disasm_t *dis) 728{ 729 disasm_crxxx (dis, "crnor"); 730} 731 732/* 13 032: rfi */ 733static 734void opd_13_032 (p405_disasm_t *dis) 735{ 736 disasm_op0 (dis, "rfi", 0, 0x03fff801UL); 737 dis->flags |= P405_DFLAG_RFI; 738} 739 740/* 13 033: rfci */ 741static 742void opd_13_033 (p405_disasm_t *dis) 743{ 744 disasm_op0 (dis, "rfci", 0, 0x03fff801UL); 745 dis->flags |= P405_DFLAG_RFI; 746} 747 748/* 13 081: crandc bt, ba, bb */ 749static 750void opd_13_081 (p405_disasm_t *dis) 751{ 752 disasm_crxxx (dis, "crandc"); 753} 754 755/* 13 096: isync */ 756static 757void opd_13_096 (p405_disasm_t *dis) 758{ 759 disasm_op0 (dis, "isync", 0, 0); 760} 761 762/* 13 0c1: crxor bt, ba, bb */ 763static 764void opd_13_0c1 (p405_disasm_t *dis) 765{ 766 disasm_crxxx (dis, "crxor"); 767} 768 769/* 13 0e1: crnand bt, ba, bb */ 770static 771void opd_13_0e1 (p405_disasm_t *dis) 772{ 773 disasm_crxxx (dis, "crnand"); 774} 775 776/* 13 101: crand bt, ba, bb */ 777static 778void opd_13_101 (p405_disasm_t *dis) 779{ 780 disasm_crxxx (dis, "crand"); 781} 782 783/* 13 121: creqv bt, ba, bb */ 784static 785void opd_13_121 (p405_disasm_t *dis) 786{ 787 disasm_crxxx (dis, "creqv"); 788} 789 790/* 13 1a1: crorc bt, ba, bb */ 791static 792void opd_13_1a1 (p405_disasm_t *dis) 793{ 794 disasm_crxxx (dis, "crorc"); 795} 796 797/* 13 1c1: cror bt, ba, bb */ 798static 799void opd_13_1c1 (p405_disasm_t *dis) 800{ 801 disasm_crxxx (dis, "cror"); 802} 803 804/* 13 210: bcctr/bcctrl */ 805static 806void opd_13_210 (p405_disasm_t *dis) 807{ 808 if (p405_get_ir_lk (dis->ir)) { 809 dis->flags |= P405_DFLAG_CALL; 810 } 811 812 disasm_bc (dis, "ctr", NULL, 813 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f, 814 0, (dis->ir & P405_IR_LK) != 0 815 ); 816} 817 818/* 13: */ 819static 820void opd_13 (p405_disasm_t *dis) 821{ 822 unsigned op2; 823 824 op2 = (dis->ir >> 1) & 0x3ff; 825 826 p405_op13[op2] (dis); 827} 828 829/* 14: rlwimi[.] ra, rs, sh, mb, me */ 830static 831void opd_14 (p405_disasm_t *dis) 832{ 833 disasm_op5 (dis, "rlwimi", OPF_RC, 0, 834 ARG_RA, ARG_RS, ARG_UINT5, ARG_UINT5, ARG_UINT5, 835 0, 0, (dis->ir >> 11) & 0x1f, (dis->ir >> 6) & 0x1f, (dis->ir >> 1) & 0x1f 836 ); 837} 838 839/* 15: rlwinm[.] ra, rs, sh, mb, me */ 840static 841void opd_15 (p405_disasm_t *dis) 842{ 843 unsigned sh, mb, me; 844 845 sh = (dis->ir >> 11) & 0x1f; 846 mb = (dis->ir >> 6) & 0x1f; 847 me = (dis->ir >> 1) & 0x1f; 848 849 if ((sh == 0) && (me == 31)) { 850 disasm_op3 (dis, "clrlwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, mb); 851 } 852 else if ((sh == 0) && (mb == 0)) { 853 disasm_op3 (dis, "clrrwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, 31 - me); 854 } 855 else if ((mb == 0) && (me == 31)) { 856 disasm_op3 (dis, "rotlwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, sh); 857 } 858 else if ((mb == 0) && (me == (31 - sh))) { 859 disasm_op3 (dis, "slwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, sh); 860 } 861 else if ((mb == (32 - sh)) && (me == 31)) { 862 disasm_op3 (dis, "srwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, 32 - sh); 863 } 864 else { 865 disasm_op5 (dis, "rlwinm", OPF_RC, 0, 866 ARG_RA, ARG_RS, ARG_UINT5, ARG_UINT5, ARG_UINT5, 0, 0, sh, mb, me 867 ); 868 } 869} 870 871/* 17: rlwnm[.] ra, rs, rb, mb, me */ 872static 873void opd_17 (p405_disasm_t *dis) 874{ 875 unsigned mb, me; 876 877 mb = (dis->ir >> 6) & 0x1f; 878 me = (dis->ir >> 1) & 0x1f; 879 880 if ((mb == 0) && (me == 31)) { 881 disasm_op3 (dis, "rotlw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 882 } 883 else { 884 disasm_op5 (dis, "rlwnm", OPF_RC, 0, 885 ARG_RA, ARG_RS, ARG_RB, ARG_UINT5, ARG_UINT5, 0, 0, 0, mb, me 886 ); 887 } 888} 889 890/* 18: ori ra, rs, uimm16 */ 891static 892void opd_18 (p405_disasm_t *dis) 893{ 894 if ((dis->ir & 0x03ffffffUL) == 0) { 895 disasm_op0 (dis, "nop", 0, 0); 896 } 897 else { 898 disasm_op3 (dis, "ori", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0); 899 } 900} 901 902/* 19: oris ra, rs, uimm16 */ 903static 904void opd_19 (p405_disasm_t *dis) 905{ 906 disasm_op3 (dis, "oris", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0); 907} 908 909/* 1A: xori ra, rs, uimm16 */ 910static 911void opd_1a (p405_disasm_t *dis) 912{ 913 disasm_op3 (dis, "xori", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0); 914} 915 916/* 1B: xoris ra, rs, uimm16 */ 917static 918void opd_1b (p405_disasm_t *dis) 919{ 920 disasm_op3 (dis, "xoris", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0); 921} 922 923/* 1C: andi. ra, rs, uimm16 */ 924static 925void opd_1c (p405_disasm_t *dis) 926{ 927 disasm_op3 (dis, "andi.", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0); 928} 929 930/* 1D: andis. ra, rs, uimm16 */ 931static 932void opd_1d (p405_disasm_t *dis) 933{ 934 disasm_op3 (dis, "andis.", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0); 935} 936 937/* 1F 000: cmpw bf, ra, rb */ 938static 939void opd_1f_000 (p405_disasm_t *dis) 940{ 941 disasm_op3 (dis, "cmpw", 0, 0, 942 ARG_UINT3, ARG_RA, ARG_RB, (dis->ir >> 23) & 0x07, 0, 0 943 ); 944} 945 946/* 1F 008: subfc[o][.] rt, ra, rb */ 947static 948void opd_1f_008 (p405_disasm_t *dis) 949{ 950 disasm_op3 (dis, "subc", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RB, ARG_RA, 0, 0, 0); 951} 952 953/* 1F 00A: addc[o][.] rt, ra, rb */ 954static 955void opd_1f_00a (p405_disasm_t *dis) 956{ 957 disasm_op3 (dis, "addc", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 958} 959 960/* 1F 00B: mulhwu[.] rt, ra, rb */ 961static 962void opd_1f_00b (p405_disasm_t *dis) 963{ 964 disasm_op3 (dis, "mulhwu", OPF_RC, 0x00000400UL, 965 ARG_RT, ARG_RA, ARG_RB, 0, 0, 0 966 ); 967} 968 969/* 1F 013: mfcr rt */ 970static 971void opd_1f_013 (p405_disasm_t *dis) 972{ 973 disasm_op1 (dis, "mfcr", 0, 0x001ff801UL, ARG_RT, 0); 974} 975 976/* 1F 014: lwarx rt, ra0, rb */ 977static 978void opd_1f_014 (p405_disasm_t *dis) 979{ 980 disasm_op3 (dis, "lwarx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 981} 982 983/* 1F 017: lwzx rt, ra0, rb */ 984static 985void opd_1f_017 (p405_disasm_t *dis) 986{ 987 disasm_op3 (dis, "lwzx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 988} 989 990/* 1F 018: slw[.] ra, rs, rb */ 991static 992void opd_1f_018 (p405_disasm_t *dis) 993{ 994 disasm_op3 (dis, "slw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 995} 996 997/* 1F 01A: cntlzw[.] ra, rs */ 998static 999void opd_1f_01a (p405_disasm_t *dis) 1000{ 1001 disasm_op2 (dis, "cntlzw", OPF_RC, 0xf800UL, ARG_RA, ARG_RS, 0, 0); 1002} 1003 1004/* 1F 01C: and[.] ra, rs, rb */ 1005static 1006void opd_1f_01c (p405_disasm_t *dis) 1007{ 1008 disasm_op3 (dis, "and", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1009} 1010 1011/* 1F 020: cmpwl bf, ra, rb */ 1012static 1013void opd_1f_020 (p405_disasm_t *dis) 1014{ 1015 disasm_op3 (dis, "cmpwl", 0, 0, 1016 ARG_UINT3, ARG_RA, ARG_RB, (dis->ir >> 23) & 0x07, 0, 0 1017 ); 1018} 1019 1020/* 1F 028: subf[o][.] rt, ra, rb */ 1021static 1022void opd_1f_028 (p405_disasm_t *dis) 1023{ 1024 disasm_op3 (dis, "sub", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RB, ARG_RA, 0, 0, 0); 1025} 1026 1027/* 1F 036: dcbst ra0, rb */ 1028static 1029void opd_1f_036 (p405_disasm_t *dis) 1030{ 1031 disasm_op2 (dis, "dcbst", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1032} 1033 1034/* 1F 037: lwzux rt, ra, rb */ 1035static 1036void opd_1f_037 (p405_disasm_t *dis) 1037{ 1038 disasm_op3 (dis, "lwzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1039} 1040 1041/* 1F 03C: andc[.] ra, rs, rb */ 1042static 1043void opd_1f_03c (p405_disasm_t *dis) 1044{ 1045 disasm_op3 (dis, "andc", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1046} 1047 1048/* 1F 04B: mulhw[.] rt, ra, rb */ 1049static 1050void opd_1f_04b (p405_disasm_t *dis) 1051{ 1052 disasm_op3 (dis, "mulhw", OPF_RC, 0x00000400UL, 1053 ARG_RT, ARG_RA, ARG_RB, 0, 0, 0 1054 ); 1055} 1056 1057/* 1F 053: mfmsr rt */ 1058static 1059void opd_1f_053 (p405_disasm_t *dis) 1060{ 1061 disasm_op1 (dis, "mfmsr", 0, 0x001ff801UL, ARG_RT, 0); 1062} 1063 1064/* 1F 056: dcbf ra0, rb */ 1065static 1066void opd_1f_056 (p405_disasm_t *dis) 1067{ 1068 disasm_op2 (dis, "dcbf", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1069} 1070 1071/* 1F 057: lbzx rt, ra0, rb */ 1072static 1073void opd_1f_057 (p405_disasm_t *dis) 1074{ 1075 disasm_op3 (dis, "lbzx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1076} 1077 1078/* 1F 068: neg[o][.] rt, ra */ 1079static 1080void opd_1f_068 (p405_disasm_t *dis) 1081{ 1082 disasm_op2 (dis, "neg", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, 0, 0); 1083} 1084 1085/* 1F 077: lbzux rt, ra, rb */ 1086static 1087void opd_1f_077 (p405_disasm_t *dis) 1088{ 1089 disasm_op3 (dis, "lbzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1090} 1091 1092/* 1F 07C: nor[.] ra, rs, rb */ 1093static 1094void opd_1f_07c (p405_disasm_t *dis) 1095{ 1096 if (p405_get_ir_rs (dis->ir) == p405_get_ir_rb (dis->ir)) { 1097 disasm_op2 (dis, "not", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0); 1098 } 1099 else { 1100 disasm_op3 (dis, "nor", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1101 } 1102} 1103 1104/* 1F 083: wrtee rs */ 1105static 1106void opd_1f_083 (p405_disasm_t *dis) 1107{ 1108 disasm_op1 (dis, "wrtee", 0, 0x001ff801UL, ARG_RS, 0); 1109} 1110 1111/* 1F 086: dcbf ra0, rb */ 1112static 1113void opd_1f_086 (p405_disasm_t *dis) 1114{ 1115 disasm_op2 (dis, "dcbf", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1116} 1117 1118/* 1F 088: subfe[o][.] rt, ra, rb */ 1119static 1120void opd_1f_088 (p405_disasm_t *dis) 1121{ 1122 disasm_op3 (dis, "subfe", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1123} 1124 1125/* 1F 08A: adde[o][.] rt, ra, rb */ 1126static 1127void opd_1f_08a (p405_disasm_t *dis) 1128{ 1129 disasm_op3 (dis, "adde", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1130} 1131 1132/* 1F 090: mtcrf fxm, rs */ 1133static 1134void opd_1f_090 (p405_disasm_t *dis) 1135{ 1136 disasm_op2 (dis, "mtcrf", 0, 0x00100801UL, 1137 ARG_UINT8, ARG_RS, (dis->ir >> 12) & 0xff, 0 1138 ); 1139} 1140 1141/* 1F 092: mtmsr rs */ 1142static 1143void opd_1f_092 (p405_disasm_t *dis) 1144{ 1145 disasm_op1 (dis, "mtmsr", 0, 0x001ff801UL, ARG_RS, 0); 1146} 1147 1148/* 1F 096: stwcx. rs, ra0, rb */ 1149static 1150void opd_1f_096 (p405_disasm_t *dis) 1151{ 1152 disasm_op3 (dis, "stwcx.", 0, 0, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1153} 1154 1155/* 1F 097: stwx rs, ra0, rb */ 1156static 1157void opd_1f_097 (p405_disasm_t *dis) 1158{ 1159 disasm_op3 (dis, "stwx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1160} 1161 1162/* 1F 0A3: wrteei e */ 1163static 1164void opd_1f_0a3 (p405_disasm_t *dis) 1165{ 1166 disasm_op1 (dis, "wrteei", 0, 0x03ff7801UL, 1167 ARG_UINT3, (dis->ir & 0x8000UL) != 0 1168 ); 1169} 1170 1171/* 1F 0B7: stwux rs, ra, rb */ 1172static 1173void opd_1f_0b7 (p405_disasm_t *dis) 1174{ 1175 disasm_op3 (dis, "stwux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0); 1176} 1177 1178/* 1F 0C8: subfze[o][.] rt, ra */ 1179static 1180void opd_1f_0c8 (p405_disasm_t *dis) 1181{ 1182 disasm_op2 (dis, "subfze", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0); 1183} 1184 1185/* 1F 0CA: addze[o][.] rt, ra */ 1186static 1187void opd_1f_0ca (p405_disasm_t *dis) 1188{ 1189 disasm_op2 (dis, "addze", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0); 1190} 1191 1192/* 1F 0D7: stbx rs, ra0, rb */ 1193static 1194void opd_1f_0d7 (p405_disasm_t *dis) 1195{ 1196 disasm_op3 (dis, "stbx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1197} 1198 1199/* 1F 0E8: subfme[o][.] rt, ra */ 1200static 1201void opd_1f_0e8 (p405_disasm_t *dis) 1202{ 1203 disasm_op2 (dis, "subfme", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0); 1204} 1205 1206/* 1F 0EA: addme[o][.] rt, ra */ 1207static 1208void opd_1f_0ea (p405_disasm_t *dis) 1209{ 1210 disasm_op2 (dis, "addme", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0); 1211} 1212 1213/* 1F 0EB: mullw[o][.] rt, ra, rb */ 1214static 1215void opd_1f_0eb (p405_disasm_t *dis) 1216{ 1217 disasm_op3 (dis, "mullw", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1218} 1219 1220/* 1F 0F6: dcbtst ra0, rb */ 1221static 1222void opd_1f_0f6 (p405_disasm_t *dis) 1223{ 1224 disasm_op2 (dis, "dcbtst", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1225} 1226 1227/* 1F 0F7: stbux rs, ra, rb */ 1228static 1229void opd_1f_0f7 (p405_disasm_t *dis) 1230{ 1231 disasm_op3 (dis, "stbux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0); 1232} 1233 1234/* 1F 106: icbt ra, rb */ 1235static 1236void opd_1f_106 (p405_disasm_t *dis) 1237{ 1238 disasm_op2 (dis, "icbt", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0); 1239} 1240 1241/* 1F 10A: add[o][.] rt, ra, rb */ 1242static 1243void opd_1f_10a (p405_disasm_t *dis) 1244{ 1245 disasm_op3 (dis, "add", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1246} 1247 1248/* 1F 116: dcbt ra0, rb */ 1249static 1250void opd_1f_116 (p405_disasm_t *dis) 1251{ 1252 disasm_op2 (dis, "dcbt", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1253} 1254 1255/* 1F 117: lhzx rt, ra0, rb */ 1256static 1257void opd_1f_117 (p405_disasm_t *dis) 1258{ 1259 disasm_op3 (dis, "lhzx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1260} 1261 1262/* 1F 11C: eqv[.] ra, rs, rb */ 1263static 1264void opd_1f_11c (p405_disasm_t *dis) 1265{ 1266 disasm_op3 (dis, "eqv", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1267} 1268 1269/* 1F 137: lhzux rt, ra, rb */ 1270static 1271void opd_1f_137 (p405_disasm_t *dis) 1272{ 1273 disasm_op3 (dis, "lhzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1274} 1275 1276/* 1F 13C: xor[.] ra, rs, rb */ 1277static 1278void opd_1f_13c (p405_disasm_t *dis) 1279{ 1280 disasm_op3 (dis, "xor", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1281} 1282 1283/* 1F 143: mfdcr rt, dcrn */ 1284static 1285void opd_1f_143 (p405_disasm_t *dis) 1286{ 1287 unsigned dcrf, dcrn; 1288 1289 dcrf = (dis->ir >> 11) & 0x3ff; 1290 dcrn = ((dcrf & 0x1f) << 5) | ((dcrf >> 5) & 0x1f); 1291 1292 disasm_op2 (dis, "mfdcr", 0, 0x01, ARG_RT, ARG_DCRN, 0, dcrn); 1293} 1294 1295/* 1F 153: mfspr rt, sprn */ 1296static 1297void opd_1f_153 (p405_disasm_t *dis) 1298{ 1299 unsigned sprf, sprn; 1300 1301 sprf = (dis->ir >> 11) & 0x3ff; 1302 sprn = ((sprf & 0x1f) << 5) | ((sprf >> 5) & 0x1f); 1303 1304 disasm_op2 (dis, "mfspr", 0, 0x01, ARG_RT, ARG_SPRN, 0, sprn); 1305} 1306 1307/* 1F 157: lhax rt, ra0, rb */ 1308static 1309void opd_1f_157 (p405_disasm_t *dis) 1310{ 1311 disasm_op3 (dis, "lhax", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1312} 1313 1314/* 1F 172: tlbia */ 1315static 1316void opd_1f_172 (p405_disasm_t *dis) 1317{ 1318 disasm_op0 (dis, "tlbia", 0, 0x03fff801UL); 1319} 1320 1321/* 1F 173: mftb rt, tbrn */ 1322static 1323void opd_1f_173 (p405_disasm_t *dis) 1324{ 1325 unsigned tbrf, tbrn; 1326 1327 tbrf = (dis->ir >> 11) & 0x3ff; 1328 tbrn = ((tbrf & 0x1f) << 5) | ((tbrf >> 5) & 0x1f); 1329 1330 switch (tbrn) { 1331 case P405_TBRN_TBL: 1332 disasm_op1 (dis, "mftb", 0, 0x01, ARG_RT, 0); 1333 break; 1334 1335 case P405_TBRN_TBU: 1336 disasm_op1 (dis, "mftbu", 0, 0x01, ARG_RT, 0); 1337 break; 1338 1339 default: 1340 disasm_op2 (dis, "mftb", 0, 0x01, ARG_RT, ARG_UINT16, 0, tbrn); 1341 break; 1342 } 1343} 1344 1345/* 1F 177: lhaux rt, ra0, rb */ 1346static 1347void opd_1f_177 (p405_disasm_t *dis) 1348{ 1349 disasm_op3 (dis, "lhaux", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1350} 1351 1352/* 1F 197: sthx rs, ra0, rb */ 1353static 1354void opd_1f_197 (p405_disasm_t *dis) 1355{ 1356 disasm_op3 (dis, "sthx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1357} 1358 1359/* 1F 19C: orc[.] ra, rs, rb */ 1360static 1361void opd_1f_19c (p405_disasm_t *dis) 1362{ 1363 disasm_op3 (dis, "orc", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1364} 1365 1366/* 1F 1B7: sthux rs, ra, rb */ 1367static 1368void opd_1f_1b7 (p405_disasm_t *dis) 1369{ 1370 disasm_op3 (dis, "sthux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0); 1371} 1372 1373/* 1F 1BC: or[.] ra, rs, rb */ 1374static 1375void opd_1f_1bc (p405_disasm_t *dis) 1376{ 1377 if (p405_get_ir_rs (dis->ir) == p405_get_ir_rb (dis->ir)) { 1378 disasm_op2 (dis, "mr", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0); 1379 } 1380 else { 1381 disasm_op3 (dis, "or", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1382 } 1383} 1384 1385/* 1F 1C3: mtdcr dcrn, rs */ 1386static 1387void opd_1f_1c3 (p405_disasm_t *dis) 1388{ 1389 unsigned dcrf, dcrn; 1390 1391 dcrf = (dis->ir >> 11) & 0x3ff; 1392 dcrn = ((dcrf & 0x1f) << 5) | ((dcrf >> 5) & 0x1f); 1393 1394 disasm_op2 (dis, "mtdcr", 0, 0x01, ARG_DCRN, ARG_RS, dcrn, 0); 1395} 1396 1397/* 1F 1C6: dccci ra0, rb */ 1398static 1399void opd_1f_1c6 (p405_disasm_t *dis) 1400{ 1401 disasm_op2 (dis, "dccci", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1402} 1403 1404/* 1F 1CB: divwu[o][.] rt, ra, rb */ 1405static 1406void opd_1f_1cb (p405_disasm_t *dis) 1407{ 1408 disasm_op3 (dis, "divwu", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1409} 1410 1411/* 1F 1D3: mtspr sprn, rs */ 1412static 1413void opd_1f_1d3 (p405_disasm_t *dis) 1414{ 1415 unsigned sprf, sprn; 1416 1417 sprf = (dis->ir >> 11) & 0x3ff; 1418 sprn = ((sprf & 0x1f) << 5) | ((sprf >> 5) & 0x1f); 1419 1420 disasm_op2 (dis, "mtspr", 0, 0x01, ARG_SPRN, ARG_RS, sprn, 0); 1421} 1422 1423/* 1F 1D6: dcbi ra0, rb */ 1424static 1425void opd_1f_1d6 (p405_disasm_t *dis) 1426{ 1427 disasm_op2 (dis, "dcbi", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1428} 1429 1430/* 1F 1DC: nand[.] ra, rs, rb */ 1431static 1432void opd_1f_1dc (p405_disasm_t *dis) 1433{ 1434 disasm_op3 (dis, "nand", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1435} 1436 1437/* 1F 1EB: divw[o][.] rt, ra, rb */ 1438static 1439void opd_1f_1eb (p405_disasm_t *dis) 1440{ 1441 disasm_op3 (dis, "divw", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0); 1442} 1443 1444/* 1F 200: mcrxr bf */ 1445static 1446void opd_1f_200 (p405_disasm_t *dis) 1447{ 1448 disasm_op1 (dis, "mcrxr", 0, 0x007ff801UL, ARG_UINT3, 1449 p405_get_ir_rt (dis->ir) >> 2 1450 ); 1451} 1452 1453/* 1F 215: lswx rt, ra0, rb */ 1454static 1455void opd_1f_215 (p405_disasm_t *dis) 1456{ 1457 disasm_op3 (dis, "lswx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1458} 1459 1460/* 1F 216: lwbrx rt, ra0, rb */ 1461static 1462void opd_1f_216 (p405_disasm_t *dis) 1463{ 1464 disasm_op3 (dis, "lwbrx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1465} 1466 1467/* 1F 218: srw[.] ra, rs, rb */ 1468static 1469void opd_1f_218 (p405_disasm_t *dis) 1470{ 1471 disasm_op3 (dis, "srw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1472} 1473 1474/* 1F 236: tlbsync */ 1475static 1476void opd_1f_236 (p405_disasm_t *dis) 1477{ 1478 disasm_op0 (dis, "tlbsync", 0, 0x03fff801UL); 1479} 1480 1481/* 1F 255: lswi rt, ra0, nb */ 1482static 1483void opd_1f_255 (p405_disasm_t *dis) 1484{ 1485 unsigned nb; 1486 1487 nb = p405_get_ir_rb (dis->ir); 1488 nb = (nb == 0) ? 32 : nb; 1489 1490 disasm_op3 (dis, "lswi", 0, 0x01, ARG_RT, ARG_RA0, ARG_UINT8, 0, 0, nb); 1491} 1492 1493/* 1F 256: sync */ 1494static 1495void opd_1f_256 (p405_disasm_t *dis) 1496{ 1497 disasm_op0 (dis, "sync", 0, 0); 1498} 1499 1500/* 1F 295: stswx rs, ra0, rb */ 1501static 1502void opd_1f_295 (p405_disasm_t *dis) 1503{ 1504 disasm_op3 (dis, "stswx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1505} 1506 1507/* 1F 296: stwbrx rs, ra0, rb */ 1508static 1509void opd_1f_296 (p405_disasm_t *dis) 1510{ 1511 disasm_op3 (dis, "stwbrx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1512} 1513 1514/* 1F 2D5: stswi rs, ra0, nb */ 1515static 1516void opd_1f_2d5 (p405_disasm_t *dis) 1517{ 1518 unsigned nb; 1519 1520 nb = p405_get_ir_rb (dis->ir); 1521 nb = (nb == 0) ? 32 : nb; 1522 1523 disasm_op3 (dis, "stswi", 0, 0x01, ARG_RS, ARG_RA0, ARG_UINT8, 0, 0, nb); 1524} 1525 1526/* 1F 2F6: dcba ra0, rb */ 1527static 1528void opd_1f_2f6 (p405_disasm_t *dis) 1529{ 1530 disasm_op2 (dis, "dcba", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1531} 1532 1533/* 1F 316: lhbrx rt, ra0, rb */ 1534static 1535void opd_1f_316 (p405_disasm_t *dis) 1536{ 1537 disasm_op3 (dis, "lhbrx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1538} 1539 1540/* 1F 318: sraw[.] ra, rs, rb */ 1541static 1542void opd_1f_318 (p405_disasm_t *dis) 1543{ 1544 disasm_op3 (dis, "sraw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0); 1545} 1546 1547/* 1F 338: srawi[.] ra, rs, sh */ 1548static 1549void opd_1f_338 (p405_disasm_t *dis) 1550{ 1551 disasm_op3 (dis, "srawi", OPF_RC, 0, 1552 ARG_RA, ARG_RS, ARG_UINT5, 0, 0, p405_get_ir_rb (dis->ir) 1553 ); 1554} 1555 1556/* 1F 356: eieio */ 1557static 1558void opd_1f_356 (p405_disasm_t *dis) 1559{ 1560 disasm_op0 (dis, "eieio", 0, 0); 1561} 1562 1563/* 1F 392: tlbsx rt, ra0, rb */ 1564static 1565void opd_1f_392 (p405_disasm_t *dis) 1566{ 1567 disasm_op3 (dis, "tlbsx", OPF_RC, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0); 1568} 1569 1570/* 1F 396: sthbrx rs, ra0, rb */ 1571static 1572void opd_1f_396 (p405_disasm_t *dis) 1573{ 1574 disasm_op3 (dis, "sthbrx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0); 1575} 1576 1577/* 1F 39A: extsh[.] ra, rs */ 1578static 1579void opd_1f_39a (p405_disasm_t *dis) 1580{ 1581 disasm_op2 (dis, "extsh", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0); 1582} 1583 1584/* 1F 3B2: tlbre rt, ra, ws */ 1585static 1586void opd_1f_3b2 (p405_disasm_t *dis) 1587{ 1588 switch (p405_get_ir_rb (dis->ir)) { 1589 case 0: 1590 disasm_op2 (dis, "tlbrehi", 0, 0x01, ARG_RT, ARG_RA, 0, 0); 1591 break; 1592 1593 case 1: 1594 disasm_op2 (dis, "tlbrelo", 0, 0x01, ARG_RT, ARG_RA, 0, 0); 1595 break; 1596 1597 default: 1598 disasm_undefined (dis); 1599 break; 1600 } 1601} 1602 1603/* 1F 3BA: extsb[.] ra, rs */ 1604static 1605void opd_1f_3ba (p405_disasm_t *dis) 1606{ 1607 disasm_op2 (dis, "extsb", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0); 1608} 1609 1610/* 1F 3C6: iccci ra, rb */ 1611static 1612void opd_1f_3c6 (p405_disasm_t *dis) 1613{ 1614 disasm_op2 (dis, "iccci", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0); 1615} 1616 1617/* 1F 3D2: tlbwe rs, ra, ws */ 1618static 1619void opd_1f_3d2 (p405_disasm_t *dis) 1620{ 1621 switch (p405_get_ir_rb (dis->ir)) { 1622 case 0: 1623 disasm_op2 (dis, "tlbwehi", 0, 0x01, ARG_RS, ARG_RA, 0, 0); 1624 break; 1625 1626 case 1: 1627 disasm_op2 (dis, "tlbwelo", 0, 0x01, ARG_RS, ARG_RA, 0, 0); 1628 break; 1629 1630 default: 1631 disasm_undefined (dis); 1632 break; 1633 } 1634} 1635 1636/* 1F 3D6: icbi ra, rb */ 1637static 1638void opd_1f_3d6 (p405_disasm_t *dis) 1639{ 1640 disasm_op2 (dis, "icbi", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0); 1641} 1642 1643/* 1F 3F6: dcbz ra0, rb */ 1644static 1645void opd_1f_3f6 (p405_disasm_t *dis) 1646{ 1647 disasm_op2 (dis, "dcbz", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0); 1648} 1649 1650/* 1F: */ 1651static 1652void opd_1f (p405_disasm_t *dis) 1653{ 1654 unsigned op2; 1655 1656 op2 = (dis->ir >> 1) & 0x3ff; 1657 1658 p405_op1f[op2] (dis); 1659} 1660 1661/* 20: lwz rt, ra0, simm16 */ 1662static 1663void opd_20 (p405_disasm_t *dis) 1664{ 1665 disasm_op3 (dis, "lwz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1666} 1667 1668/* 21: lwzu rt, ra, simm16 */ 1669static 1670void opd_21 (p405_disasm_t *dis) 1671{ 1672 disasm_op3 (dis, "lwzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 1673} 1674 1675/* 22: lbz rt, ra0, simm16 */ 1676static 1677void opd_22 (p405_disasm_t *dis) 1678{ 1679 disasm_op3 (dis, "lbz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1680} 1681 1682/* 23: lbzu rt, ra, simm16 */ 1683static 1684void opd_23 (p405_disasm_t *dis) 1685{ 1686 disasm_op3 (dis, "lbzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 1687} 1688 1689/* 24: stw rs, ra0, simm16 */ 1690static 1691void opd_24 (p405_disasm_t *dis) 1692{ 1693 disasm_op3 (dis, "stw", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1694} 1695 1696/* 25: stwu rs, ra, simm16 */ 1697static 1698void opd_25 (p405_disasm_t *dis) 1699{ 1700 disasm_op3 (dis, "stwu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0); 1701} 1702 1703/* 26: stb rs, ra0, simm16 */ 1704static 1705void opd_26 (p405_disasm_t *dis) 1706{ 1707 disasm_op3 (dis, "stb", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1708} 1709 1710/* 27: stbu rs, ra, simm16 */ 1711static 1712void opd_27 (p405_disasm_t *dis) 1713{ 1714 disasm_op3 (dis, "stbu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0); 1715} 1716 1717/* 28: lhz rt, ra0, simm16 */ 1718static 1719void opd_28 (p405_disasm_t *dis) 1720{ 1721 disasm_op3 (dis, "lhz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1722} 1723 1724/* 29: lhzu rt, ra, simm16 */ 1725static 1726void opd_29 (p405_disasm_t *dis) 1727{ 1728 disasm_op3 (dis, "lhzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 1729} 1730 1731/* 2A: lha rt, ra0, simm16 */ 1732static 1733void opd_2a (p405_disasm_t *dis) 1734{ 1735 disasm_op3 (dis, "lha", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1736} 1737 1738/* 2B: lhau rt, ra, simm16 */ 1739static 1740void opd_2b (p405_disasm_t *dis) 1741{ 1742 disasm_op3 (dis, "lhau", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0); 1743} 1744 1745/* 2C: sth rs, ra0, simm16 */ 1746static 1747void opd_2c (p405_disasm_t *dis) 1748{ 1749 disasm_op3 (dis, "sth", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1750} 1751 1752/* 2D: sthu rs, ra, simm16 */ 1753static 1754void opd_2d (p405_disasm_t *dis) 1755{ 1756 disasm_op3 (dis, "sthu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0); 1757} 1758 1759/* 2E: lmw rt, ra0, simm16 */ 1760static 1761void opd_2e (p405_disasm_t *dis) 1762{ 1763 disasm_op3 (dis, "lmw", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1764} 1765 1766/* 2F: stmw rs, ra0, simm16 */ 1767static 1768void opd_2f (p405_disasm_t *dis) 1769{ 1770 disasm_op3 (dis, "stmw", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0); 1771} 1772 1773void p405_disasm (p405_disasm_t *dis, uint32_t pc, uint32_t ir) 1774{ 1775 unsigned op; 1776 1777 if (p405_disasm_inited == 0) { 1778 p405_disasm_init(); 1779 } 1780 1781 dis->flags = 0; 1782 dis->reg = 0; 1783 1784 dis->pc = pc; 1785 dis->ir = ir; 1786 1787 op = (ir >> 26) & 0x3f; 1788 1789 p405_op[op] (dis); 1790} 1791 1792void p405_disasm_mem (p405_t *c, p405_disasm_t *dis, uint32_t pc, unsigned xlat) 1793{ 1794 uint32_t ir; 1795 1796 if (p405_disasm_inited == 0) { 1797 p405_disasm_init(); 1798 } 1799 1800 dis->flags = 0; 1801 dis->reg = 0; 1802 1803 if (p405_get_xlat32 (c, pc, xlat, &ir)) { 1804 dis->pc = pc; 1805 dis->ir = 0xffffffffUL; 1806 1807 disasm_op0 (dis, "TLB_MISS", 0, 0); 1808 1809 dis->flags |= P405_DFLAG_TLBM; 1810 } 1811 else { 1812 p405_disasm (dis, pc, ir); 1813 } 1814} 1815 1816static 1817p405_disasm_list_t p405_op13_list[] = { 1818 { 0x000, opd_13_000 }, 1819 { 0x010, opd_13_010 }, 1820 { 0x021, opd_13_021 }, 1821 { 0x032, opd_13_032 }, 1822 { 0x033, opd_13_033 }, 1823 { 0x081, opd_13_081 }, 1824 { 0x096, opd_13_096 }, 1825 { 0x0c1, opd_13_0c1 }, 1826 { 0x0e1, opd_13_0e1 }, 1827 { 0x101, opd_13_101 }, 1828 { 0x121, opd_13_121 }, 1829 { 0x1a1, opd_13_1a1 }, 1830 { 0x1c1, opd_13_1c1 }, 1831 { 0x210, opd_13_210 }, 1832 { 0x000, NULL } 1833}; 1834 1835static 1836p405_disasm_list_t p405_op1f_list[] = { 1837 { 0x000, opd_1f_000 }, 1838 { 0x008, opd_1f_008 }, 1839 { 0x00a, opd_1f_00a }, 1840 { 0x00b, opd_1f_00b }, 1841 { 0x013, opd_1f_013 }, 1842 { 0x014, opd_1f_014 }, 1843 { 0x017, opd_1f_017 }, 1844 { 0x018, opd_1f_018 }, 1845 { 0x01a, opd_1f_01a }, 1846 { 0x01c, opd_1f_01c }, 1847 { 0x020, opd_1f_020 }, 1848 { 0x028, opd_1f_028 }, 1849 { 0x036, opd_1f_036 }, 1850 { 0x037, opd_1f_037 }, 1851 { 0x03c, opd_1f_03c }, 1852 { 0x04b, opd_1f_04b }, 1853 { 0x053, opd_1f_053 }, 1854 { 0x056, opd_1f_056 }, 1855 { 0x057, opd_1f_057 }, 1856 { 0x068, opd_1f_068 }, 1857 { 0x077, opd_1f_077 }, 1858 { 0x07c, opd_1f_07c }, 1859 { 0x083, opd_1f_083 }, 1860 { 0x086, opd_1f_086 }, 1861 { 0x088, opd_1f_088 }, 1862 { 0x08a, opd_1f_08a }, 1863 { 0x090, opd_1f_090 }, 1864 { 0x092, opd_1f_092 }, 1865 { 0x096, opd_1f_096 }, 1866 { 0x097, opd_1f_097 }, 1867 { 0x0a3, opd_1f_0a3 }, 1868 { 0x0b7, opd_1f_0b7 }, 1869 { 0x0c8, opd_1f_0c8 }, 1870 { 0x0ca, opd_1f_0ca }, 1871 { 0x0d7, opd_1f_0d7 }, 1872 { 0x0e8, opd_1f_0e8 }, 1873 { 0x0ea, opd_1f_0ea }, 1874 { 0x0eb, opd_1f_0eb }, 1875 { 0x0f6, opd_1f_0f6 }, 1876 { 0x0f7, opd_1f_0f7 }, 1877 { 0x106, opd_1f_106 }, 1878 { 0x10a, opd_1f_10a }, 1879 { 0x116, opd_1f_116 }, 1880 { 0x117, opd_1f_117 }, 1881 { 0x11c, opd_1f_11c }, 1882 { 0x137, opd_1f_137 }, 1883 { 0x13c, opd_1f_13c }, 1884 { 0x143, opd_1f_143 }, 1885 { 0x153, opd_1f_153 }, 1886 { 0x157, opd_1f_157 }, 1887 { 0x172, opd_1f_172 }, 1888 { 0x173, opd_1f_173 }, 1889 { 0x177, opd_1f_177 }, 1890 { 0x197, opd_1f_197 }, 1891 { 0x19c, opd_1f_19c }, 1892 { 0x1b7, opd_1f_1b7 }, 1893 { 0x1bc, opd_1f_1bc }, 1894 { 0x1c3, opd_1f_1c3 }, 1895 { 0x1c6, opd_1f_1c6 }, 1896 { 0x1cb, opd_1f_1cb }, 1897 { 0x1d3, opd_1f_1d3 }, 1898 { 0x1d6, opd_1f_1d6 }, 1899 { 0x1dc, opd_1f_1dc }, 1900 { 0x1eb, opd_1f_1eb }, 1901 { 0x200, opd_1f_200 }, 1902 { 0x208, opd_1f_008 }, 1903 { 0x20a, opd_1f_00a }, 1904 { 0x215, opd_1f_215 }, 1905 { 0x216, opd_1f_216 }, 1906 { 0x218, opd_1f_218 }, 1907 { 0x228, opd_1f_028 }, 1908 { 0x236, opd_1f_236 }, 1909 { 0x255, opd_1f_255 }, 1910 { 0x256, opd_1f_256 }, 1911 { 0x268, opd_1f_068 }, 1912 { 0x288, opd_1f_088 }, 1913 { 0x28a, opd_1f_08a }, 1914 { 0x295, opd_1f_295 }, 1915 { 0x296, opd_1f_296 }, 1916 { 0x2c8, opd_1f_0c8 }, 1917 { 0x2ca, opd_1f_0ca }, 1918 { 0x2d5, opd_1f_2d5 }, 1919 { 0x2e8, opd_1f_0e8 }, 1920 { 0x2ea, opd_1f_0ea }, 1921 { 0x2eb, opd_1f_0eb }, 1922 { 0x2f6, opd_1f_2f6 }, 1923 { 0x30a, opd_1f_10a }, 1924 { 0x316, opd_1f_316 }, 1925 { 0x318, opd_1f_318 }, 1926 { 0x338, opd_1f_338 }, 1927 { 0x356, opd_1f_356 }, 1928 { 0x392, opd_1f_392 }, 1929 { 0x396, opd_1f_396 }, 1930 { 0x39a, opd_1f_39a }, 1931 { 0x3b2, opd_1f_3b2 }, 1932 { 0x3ba, opd_1f_3ba }, 1933 { 0x3c6, opd_1f_3c6 }, 1934 { 0x3cb, opd_1f_1cb }, 1935 { 0x3d2, opd_1f_3d2 }, 1936 { 0x3d6, opd_1f_3d6 }, 1937 { 0x3eb, opd_1f_1eb }, 1938 { 0x3f6, opd_1f_3f6 }, 1939 { 0x000, NULL } 1940}; 1941 1942static 1943p405_disasm_f p405_op[64] = { 1944 &opd_ud, &opd_ud, &opd_ud, &opd_03, &opd_ud, &opd_ud, &opd_ud, &opd_07, /* 00 */ 1945 &opd_08, &opd_ud, &opd_0a, &opd_0b, &opd_0c, &opd_0d, &opd_0e, &opd_0f, 1946 &opd_10, &opd_11, &opd_12, &opd_13, &opd_14, &opd_15, &opd_ud, &opd_17, /* 10 */ 1947 &opd_18, &opd_19, &opd_1a, &opd_1b, &opd_1c, &opd_1d, &opd_ud, &opd_1f, 1948 &opd_20, &opd_21, &opd_22, &opd_23, &opd_24, &opd_25, &opd_26, &opd_27, /* 20 */ 1949 &opd_28, &opd_29, &opd_2a, &opd_2b, &opd_2c, &opd_2d, &opd_2e, &opd_2f, 1950 &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, /* 30 */ 1951 &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud 1952}; 1953 1954static 1955void p405_disasm_init (void) 1956{ 1957 unsigned i; 1958 p405_disasm_list_t *lst; 1959 1960 for (i = 0; i < 1024; i++) { 1961 p405_op1f[i] = opd_ud; 1962 p405_op13[i] = opd_ud; 1963 } 1964 1965 lst = p405_op13_list; 1966 1967 while (lst->fct != NULL) { 1968 p405_op13[lst->op] = lst->fct; 1969 lst += 1; 1970 } 1971 1972 lst = p405_op1f_list; 1973 1974 while (lst->fct != NULL) { 1975 p405_op1f[lst->op] = lst->fct; 1976 lst += 1; 1977 } 1978 1979 p405_disasm_inited = 1; 1980}