--- mon/src/mon_ppc.cpp 1999/10/04 19:31:09 1.1.1.1 +++ mon/src/mon_ppc.cpp 2010/02/21 11:58:33 1.11 @@ -1,22 +1,36 @@ /* * mon_ppc.cpp - PowerPC disassembler * - * (C) 1997-1999 Christian Bauer + * cxmon (C) Christian Bauer, Marc Hellwig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#include "sysdeps.h" #include "mon.h" -#include "mon_ppc.h" +#include "mon_disass.h" // Instruction fields -static int primop, exop, ra, rb, rc, rd; +static int primop, exop, vxop, ra, rb, rc, rd; static unsigned short imm; // Codes for trap instructions -static char *to_code[32] = { +static const char *to_code[32] = { NULL, "lgt", "llt", NULL, "eq", "lge", "lle", NULL, "gt", NULL, NULL, NULL, "ge", NULL, NULL, NULL, "lt", NULL, NULL, NULL, "le", NULL, NULL, NULL, @@ -82,6 +96,11 @@ static char *to_code[32] = { #define dsform(s) fprintf(f, "%s\tr%d,$%04x(r%d)\n", s, rd, short(imm & 0xfffc), ra) +#define xform_vls(s) \ + if (ra == 0) \ + fprintf(f, "%s\tv%d,r%d\n", s, rd, rb); \ + else \ + fprintf(f, "%s\tv%d,r%d,r%d\n", s, rd, ra, rb) #define xform_ls(s) \ if (ra == 0) \ fprintf(f, "%s\tr%d,r%d\n", s, rd, rb); \ @@ -146,14 +165,29 @@ static char *to_code[32] = { #define mdsform(s) fprintf(f, "%s%s\tr%d,r%d,r%d,%d\n", s, w & 1 ? "." : "", ra, rd, rb, rc | (w & 32 ? 32 : 0)) +#define va_form(s) fprintf(f, "%s\tv%d,v%d,v%d,v%d\n", s, rd, ra, rb, rc) +#define vx_form(s) fprintf(f, "%s\tv%d,v%d,v%d\n", s, rd, ra, rb) +#define vxr_form(s) fprintf(f, "%s%s\tv%d,v%d,v%d\n", s, w & (1 << 10) ? "." : "", rd, ra, rb) +#define vxi_ra_form(s) fprintf(f, "%s\tv%d,v%d,%d\n", s, rd, rb, ra) +#define vx_raz_form(s) \ + if (ra == 0) \ + fprintf(f, "%s\tv%d,v%d\n", s, rd, rb); \ + else \ + fprintf(f, "?\n") +#define vxi_ras_rbz_form(s) \ + if (rb == 0) \ + fprintf(f, "%s\tv%d,%d\n", s, rd, ra - (ra & 0x10 ? 0x20 : 0)); \ + else \ + fprintf(f, "?\n") // Prototypes +static void disass4(FILE *f, unsigned int adr, unsigned int w); static void disass19(FILE *f, unsigned int adr, unsigned int w); static void disass31(FILE *f, unsigned int adr, unsigned int w); static void disass59(FILE *f, unsigned int adr, unsigned int w); static void disass63(FILE *f, unsigned int adr, unsigned int w); static unsigned int mbme2mask(int mb, int me); -static char *get_spr(int reg); +static const char *get_spr(int reg); /* @@ -169,6 +203,7 @@ void disass_ppc(FILE *f, unsigned int ad rb = w >> 11 & 0x1f; rc = w >> 6 & 0x1f; exop = w >> 1 & 0x3ff; + vxop = w & 0x7ff; imm = w & 0xffff; // Decode primary opcode @@ -187,7 +222,9 @@ void disass_ppc(FILE *f, unsigned int ad dform_to("twi"); break; -// case 4: // AltiVec + case 4: // AltiVec + disass4(f, adr, w); + break; case 7: dform_simm("mulli"); break; case 8: dform_simm("subfic"); break; @@ -242,7 +279,7 @@ void disass_ppc(FILE *f, unsigned int ad case 16: { int target = short(imm & 0xfffc); - char *form; + const char *form; if (w & 1) if (w & 2) form = "la"; @@ -379,6 +416,179 @@ void disass_ppc(FILE *f, unsigned int ad /* + * Disassemble instruction with primary opcode = 4 (VX-Form) + */ + +static void disass4(FILE *f, unsigned int adr, unsigned int w) +{ + switch (vxop) { + case 1540: + if (ra == 0 && rb == 0) + fprintf(f, "mfvscr\tv%d\n", rd); + else + fprintf(f, "?\n"); + break; + case 1604: + if (rd == 0 && ra == 0) + fprintf(f, "mtvscr\tv%d\n", rb); + else + fprintf(f, "?\n"); + break; + case 384: vx_form("vaddcuw"); break; + case 10: vx_form("vaddfp"); break; + case 768: vx_form("vaddsbs"); break; + case 832: vx_form("vaddshs"); break; + case 896: vx_form("vaddsws"); break; + case 0: vx_form("vaddubm"); break; + case 512: vx_form("vaddubs"); break; + case 64: vx_form("vadduhm"); break; + case 576: vx_form("vadduhs"); break; + case 128: vx_form("vadduwm"); break; + case 640: vx_form("vadduws"); break; + case 1028: vx_form("vand"); break; + case 1092: vx_form("vandc"); break; + case 1282: vx_form("vavgsb"); break; + case 1346: vx_form("vavgsh"); break; + case 1410: vx_form("vavgsw"); break; + case 1026: vx_form("vavgub"); break; + case 1090: vx_form("vavguh"); break; + case 1154: vx_form("vavguw"); break; + case 842: vxi_ra_form("vcfsx"); break; + case 778: vxi_ra_form("vcfux"); break; + case 966: case 966+1024: vxr_form("vcmpbfp"); break; + case 198: case 198+1024: vxr_form("vcmpeqfp"); break; + case 6: case 6+1024: vxr_form("vcmpequb"); break; + case 70: case 70+1024: vxr_form("vcmpequh"); break; + case 134: case 134+1024: vxr_form("vcmpequw"); break; + case 454: case 454+1024: vxr_form("vcmpgefp"); break; + case 710: case 710+1024: vxr_form("vcmpgtfp"); break; + case 774: case 774+1024: vxr_form("vcmpgtsb"); break; + case 838: case 838+1024: vxr_form("vcmpgtsh"); break; + case 902: case 902+1024: vxr_form("vcmpgtsw"); break; + case 518: case 518+1024: vxr_form("vcmpgtub"); break; + case 582: case 582+1024: vxr_form("vcmpgtuh"); break; + case 646: case 646+1024: vxr_form("vcmpgtuw"); break; + case 970: vxi_ra_form("vctsxs"); break; + case 906: vxi_ra_form("vctuxs"); break; + case 394: vx_raz_form("vexptefp"); break; + case 458: vx_raz_form("vlogefp"); break; + case 1034: vx_form("vmaxfp"); break; + case 258: vx_form("vmaxsb"); break; + case 322: vx_form("vmaxsh"); break; + case 386: vx_form("vmaxsw"); break; + case 2: vx_form("vmaxub"); break; + case 66: vx_form("vmaxuh"); break; + case 130: vx_form("vmaxuw"); break; + case 1098: vx_form("vminfp"); break; + case 770: vx_form("vminsb"); break; + case 834: vx_form("vminsh"); break; + case 898: vx_form("vminsw"); break; + case 514: vx_form("vminub"); break; + case 578: vx_form("vminuh"); break; + case 642: vx_form("vminuw"); break; + case 12: vx_form("vmrghb"); break; + case 76: vx_form("vmrghh"); break; + case 140: vx_form("vmrghw"); break; + case 268: vx_form("vmrglb"); break; + case 332: vx_form("vmrglh"); break; + case 396: vx_form("vmrglw"); break; + case 776: vx_form("vmulesb"); break; + case 840: vx_form("vmulesh"); break; + case 520: vx_form("vmuleub"); break; + case 584: vx_form("vmuleuh"); break; + case 264: vx_form("vmulosb"); break; + case 328: vx_form("vmulosh"); break; + case 8: vx_form("vmuloub"); break; + case 72: vx_form("vmulouh"); break; + case 1284: vx_form("vnor"); break; + case 1156: vx_form("vor"); break; + case 782: vx_form("vpkpx"); break; + case 398: vx_form("vpkshss"); break; + case 270: vx_form("vpkshus"); break; + case 462: vx_form("vpkswss"); break; + case 334: vx_form("vpkswus"); break; + case 14: vx_form("vpkuhum"); break; + case 142: vx_form("vpkuhus"); break; + case 78: vx_form("vpkuwum"); break; + case 206: vx_form("vpkuwus"); break; + case 266: vx_raz_form("vrefp"); break; + case 714: vx_raz_form("vrfim"); break; + case 522: vx_raz_form("vrfin"); break; + case 650: vx_raz_form("vrfip"); break; + case 586: vx_raz_form("vrfiz"); break; + case 4: vx_form("vrlb"); break; + case 68: vx_form("vrlh"); break; + case 132: vx_form("vrlw"); break; + case 330: vx_raz_form("vrsqrtefp"); break; + case 452: vx_form("vsl"); break; + case 260: vx_form("vslb"); break; + case 324: vx_form("vslh"); break; + case 1036: vx_form("vslo"); break; + case 388: vx_form("vslw"); break; + case 524: vxi_ra_form("vspltb"); break; + case 588: vxi_ra_form("vsplth"); break; + case 780: vxi_ras_rbz_form("vspltisb"); break; + case 844: vxi_ras_rbz_form("vspltish"); break; + case 908: vxi_ras_rbz_form("vspltisw"); break; + case 652: vxi_ra_form("vspltw"); break; + case 708: vx_form("vsr"); break; + case 772: vx_form("vsrab"); break; + case 836: vx_form("vsrah"); break; + case 900: vx_form("vsraw"); break; + case 516: vx_form("vsrb"); break; + case 580: vx_form("vsrh"); break; + case 1100: vx_form("vsro"); break; + case 644: vx_form("vsrw"); break; + case 1408: vx_form("vsubcuw"); break; + case 74: vx_form("vsubfp"); break; + case 1792: vx_form("vsubsbs"); break; + case 1856: vx_form("vsubshs"); break; + case 1920: vx_form("vsubsws"); break; + case 1024: vx_form("vsububm"); break; + case 1536: vx_form("vsububs"); break; + case 1088: vx_form("vsubuhm"); break; + case 1600: vx_form("vsubuhs"); break; + case 1152: vx_form("vsubuwm"); break; + case 1664: vx_form("vsubuws"); break; + case 1928: vx_form("vsumsws"); break; + case 1672: vx_form("vsum2sws"); break; + case 1800: vx_form("vsum4sbs"); break; + case 1608: vx_form("vsum4shs"); break; + case 1544: vx_form("vsum4ubs"); break; + case 846: vx_raz_form("vupkhpx"); break; + case 526: vx_raz_form("vupkhsb"); break; + case 590: vx_raz_form("vupkhsh"); break; + case 974: vx_raz_form("vupklpx"); break; + case 654: vx_raz_form("vupklsb"); break; + case 718: vx_raz_form("vupklsh"); break; + case 1220: vx_form("vxor"); break; + default: + if ((vxop & 0x43f) == 44) { // vsldoi vD,vA,vB,SHB + fprintf(f, "vsldoi\tv%d,v%d,v%d,%d\n", rd, ra, rb, rc & 15); + break; + } + switch (vxop & 0x3f) { // VA-form, must come last + case 46: va_form("vmaddfp"); break; + case 32: va_form("vmhaddshs"); break; + case 33: va_form("vmhraddshs"); break; + case 34: va_form("vmladduhm"); break; + case 37: va_form("vmsummbm"); break; + case 40: va_form("vmsumshm"); break; + case 41: va_form("vmsumshs"); break; + case 36: va_form("vmsumubm"); break; + case 38: va_form("vmsumuhm"); break; + case 39: va_form("vmsumuhs"); break; + case 47: va_form("vnmsubfp"); break; + case 43: va_form("vperm"); break; + case 42: va_form("vsel"); break; + default: fprintf(f, "?\n"); break; + } + break; + } +} + + +/* * Disassemble instruction with primary opcode = 19 (XL-Form) */ @@ -480,6 +690,8 @@ static void disass31(FILE *f, unsigned i xform_to("tw"); break; + case 6: xform_vls("lvsl"); break; + case 7: xform_vls("lvebx"); break; case 8: xoform_dab("subfc"); break; case 8+512: xoform_dab("subfco"); break; case 9: case 9+512: xoform_dab("mulhdu"); break; // 64 bit @@ -502,6 +714,8 @@ static void disass31(FILE *f, unsigned i xform_crlab("cmplw"); break; + case 38: xform_vls("lvsr"); break; + case 39: xform_vls("lvehx"); break; case 40: xoform_dab("subf"); break; case 40+512: xoform_dab("subfo"); break; case 53: xform_ls("ldux"); break; // 64 bit @@ -517,12 +731,14 @@ static void disass31(FILE *f, unsigned i xform_to("td"); break; + case 71: xform_vls("lvewx"); break; case 73: case 73+512: xoform_dab("mulhd"); break; // 64 bit case 75: case 75+512: xoform_dab("mulhw"); break; case 83: xform_d("mfmsr"); break; case 84: xform_ls("ldarx"); break; // 64 bit case 86: xform_ab("dcbf"); break; case 87: xform_ls("lbzx"); break; + case 103: xform_vls("lvx"); break; case 104: xoform_da("neg"); break; case 104+512: xoform_da("nego"); break; case 119: xform_ls("lbzux"); break; @@ -534,6 +750,7 @@ static void disass31(FILE *f, unsigned i xform_sabc("nor"); break; + case 135: xform_vls("stvebx"); break; case 136: xoform_dab("subfe"); break; case 136+512: xoform_dab("subfeo"); break; case 138: xoform_dab("adde"); break; @@ -550,8 +767,10 @@ static void disass31(FILE *f, unsigned i break; case 151: xform_ls("stwx"); break; + case 167: xform_vls("stvehx"); break; case 181: xform_ls("stdux"); break; // 64 bit case 183: xform_ls("stwux"); break; + case 199: xform_vls("stvewx"); break; case 200: xoform_da("subfze"); break; case 200+512: xoform_da("subfzeo"); break; case 202: xoform_da("addze"); break; @@ -566,6 +785,7 @@ static void disass31(FILE *f, unsigned i break; case 215: xform_ls("stbx"); break; + case 231: xform_vls("stvx"); break; case 232: xoform_da("subfme"); break; case 232+512: xoform_da("subfmeo"); break; case 233: xoform_dab("mulld"); break; // 64 bit @@ -594,8 +814,10 @@ static void disass31(FILE *f, unsigned i fprintf(f, "mflr\tr%d\n", rd); else if ((ra | (rb << 5)) == 9) fprintf(f, "mfctr\tr%d\n", rd); + else if ((ra | (rb << 5)) == 256) + fprintf(f, "mfvrsave\tr%d\n", rd); else { - char *spr = get_spr(ra | (rb << 5)); + const char *spr = get_spr(ra | (rb << 5)); if (spr) fprintf(f, "mfspr\tr%d,%s\n", rd, spr); else @@ -605,8 +827,34 @@ static void disass31(FILE *f, unsigned i case 341: xform_ls("lwax"); break; // 64 bit case 343: xform_ls("lhax"); break; + case 359: xform_vls("lvxl"); break; case 370: xform("tlbia"); break; + case 822: // AltiVec + if ((rd & 0xc) == 0 && ra == 0 && rb == 0 && (w & 1) == 0) { + if (rd & 0x10) + fprintf(f, "dssall\n"); + else + fprintf(f, "dss\t%d\n", rd & 3); + } + else + fprintf(f, "?\n"); + break; + + case 342: // AltiVec + if ((rd & 0xc) == 0 && (w & 1) == 0) + fprintf(f, "dst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); + else + fprintf(f, "?\n"); + break; + + case 374: // AltiVec + if ((rd & 0xc) == 0 && (w & 1) == 0) + fprintf(f, "dstst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); + else + fprintf(f, "?\n"); + break; + case 371: if ((ra | (rb << 5)) == 268) xfxform_tb("mftb"); @@ -643,8 +891,10 @@ static void disass31(FILE *f, unsigned i fprintf(f, "mtlr\tr%d\n", rd); else if ((ra | (rb << 5)) == 9) fprintf(f, "mtctr\tr%d\n", rd); + else if ((ra | (rb << 5)) == 256) + fprintf(f, "mtvrsave\tr%d\n", rd); else { - char *spr = get_spr(ra | (rb << 5)); + const char *spr = get_spr(ra | (rb << 5)); if (spr) fprintf(f, "mtspr\t%s,r%d\n", spr, rd); else @@ -654,6 +904,7 @@ static void disass31(FILE *f, unsigned i case 470: xform_ab("dcbi"); break; case 476: xform_sabc("nand"); break; + case 487: xform_vls("stvxl"); break; case 489: xoform_dab("divd"); break; // 64 bit case 489+512: xoform_dab("divdo"); break; // 64 bit case 491: xoform_dab("divw"); break; @@ -807,7 +1058,7 @@ static unsigned int mbme2mask(int mb, in * Convert SPR number to register name */ -char *get_spr(int reg) +const char *get_spr(int reg) { switch (reg) { case 1: return "xer";