rizin/librz/arch/p/parse/parse_ppc_pseudo.c
Khairul Azhar Kasmiran c8878d3139
Convert %ll format specifiers to PFMT64 (#6267)
* Convert `%ll` format specifiers to PFMT64
* Remove ` ""` at end of some PFMT64
2026-04-22 05:57:04 +08:00

1751 lines
61 KiB
C

// SPDX-FileCopyrightText: 2015-2017 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rz_lib.h>
#include <rz_util.h>
#include <rz_flag.h>
#include <rz_analysis.h>
#include <rz_parse.h>
#ifndef PFMT32x
#define PFMT32x "lx"
#endif
#define SPR_MQ 0x0
#define SPR_XER 0x1
#define SPR_RTCU 0x4
#define SPR_RTCL 0x5
#define SPR_LR 0x8
#define SPR_CTR 0x9
#define SPR_DSISR 0x12
#define SPR_DAR 0x13
#define SPR_DEC 0x16
#define SPR_SDR1 0x19
#define SPR_SRR0 0x1a
#define SPR_SRR1 0x1b
#define SPR_VRSAVE 0x100
#define SPR_TBRL 0x10c
#define SPR_TBRU 0x10d
#define SPR_SPRG0 0x110
#define SPR_SPRG1 0x111
#define SPR_SPRG2 0x112
#define SPR_SPRG3 0x113
#define SPR_EAR 0x11a
#define SPR_TBL 0x11c
#define SPR_TBU 0x11d
#define SPR_PVR 0x11f
#define SPR_SPEFSCR 0x200
#define SPR_IBAT0U 0x210
#define SPR_IBAT0L 0x211
#define SPR_IBAT1U 0x212
#define SPR_IBAT1L 0x213
#define SPR_IBAT2U 0x214
#define SPR_IBAT2L 0x215
#define SPR_IBAT3U 0x216
#define SPR_IBAT3L 0x217
#define SPR_DBAT0U 0x218
#define SPR_DBAT0L 0x219
#define SPR_DBAT1U 0x21a
#define SPR_DBAT1L 0x21b
#define SPR_DBAT2U 0x21c
#define SPR_DBAT2L 0x21d
#define SPR_DBAT3U 0x21e
#define SPR_DBAT3L 0x21f
#define SPR_UMMCR0 0x3a8
#define SPR_UMMCR1 0x3ac
#define SPR_UPMC1 0x3a9
#define SPR_UPMC2 0x3aa
#define SPR_USIA 0x3ab
#define SPR_UPMC3 0x3ad
#define SPR_UPMC4 0x3ae
#define SPR_MMCR0 0x3b8
#define SPR_PMC1 0x3b9
#define SPR_PMC2 0x3ba
#define SPR_SIA 0x3bb
#define SPR_MMCR1 0x3bc
#define SPR_PMC3 0x3bd
#define SPR_PMC4 0x3be
#define SPR_SDA 0x3bf
#define SPR_DMISS 0x3d0
#define SPR_DCMP 0x3d1
#define SPR_HASH1 0x3d2
#define SPR_HASH2 0x3d3
#define SPR_IMISS 0x3d4
#define SPR_ICMP 0x3d5
#define SPR_RPA 0x3d6
#define SPR_HID0 0x3f0 /* Hardware Implementation Register 0 */
#define SPR_HID1 0x3f1 /* Hardware Implementation Register 1 */
#define SPR_IABR 0x3f2
#define SPR_HID2 0x3f3 /* Hardware Implementation Register 2 */
#define SPR_HID4 0x3f4 /* Hardware Implementation Register 4 */
#define SPR_DABR 0x3f5
#define SPR_HID5 0x3f6 /* Hardware Implementation Register 5 */
#define SPR_HID6 0x3f9 /* Hardware Implementation Register 6 */
// #define SPR_L2CR 0x3f9
#define SPR_ICTC 0x3fb
#define SPR_THRM1 0x3fc
#define SPR_THRM2 0x3fd
#define SPR_THRM3 0x3fe
#define SPR_PIR 0x3ff
#define PPC_UT64(x) (strtol(x, NULL, 16))
#define PPC_UT32(x) ((ut32)PPC_UT64(x))
static int can_replace(const char *str, int idx, int max_operands) {
if (str[idx] < 'A' || str[idx] > 'J') {
return false;
}
if (str[idx + 1] != '\x00' && str[idx + 1] <= 'J' && str[idx + 1] >= 'A') {
return false;
}
if ((int)((int)str[idx] - 0x41) > max_operands) {
return false;
}
return true;
}
#define SPR_CONST(o, x) \
strcpy((o), (x)); \
return (strlen((x)) - 1)
static int getspr_pseudo(const char *reg, char *output) {
char cspr[32];
ut32 spr = 0;
if (!reg) {
return 0;
}
spr = strtol(reg, NULL, 16);
if (spr > 9999) {
return 0; // just to avoid overflows..
}
switch (spr) {
case SPR_MQ:
SPR_CONST(output, "mq");
case SPR_XER:
SPR_CONST(output, "xer");
case SPR_RTCU:
SPR_CONST(output, "rtcu");
case SPR_RTCL:
SPR_CONST(output, "rtcl");
case SPR_LR:
SPR_CONST(output, "lr");
case SPR_CTR:
SPR_CONST(output, "ctr");
case SPR_DSISR:
SPR_CONST(output, "dsisr");
case SPR_DAR:
SPR_CONST(output, "dar");
case SPR_DEC:
SPR_CONST(output, "dec");
case SPR_SDR1:
SPR_CONST(output, "sdr1");
case SPR_SRR0:
SPR_CONST(output, "srr0");
case SPR_SRR1:
SPR_CONST(output, "srr1");
case SPR_VRSAVE:
SPR_CONST(output, "vrsave");
case SPR_TBRL:
SPR_CONST(output, "tbrl");
case SPR_TBRU:
SPR_CONST(output, "tbru");
case SPR_SPRG0:
SPR_CONST(output, "sprg0");
case SPR_SPRG1:
SPR_CONST(output, "sprg1");
case SPR_SPRG2:
SPR_CONST(output, "sprg2");
case SPR_SPRG3:
SPR_CONST(output, "sprg3");
case SPR_EAR:
SPR_CONST(output, "ear");
case SPR_TBL:
SPR_CONST(output, "tbl");
case SPR_TBU:
SPR_CONST(output, "tbu");
case SPR_PVR:
SPR_CONST(output, "pvr");
case SPR_SPEFSCR:
SPR_CONST(output, "spefscr");
case SPR_IBAT0U:
SPR_CONST(output, "ibat0u");
case SPR_IBAT0L:
SPR_CONST(output, "ibat0l");
case SPR_IBAT1U:
SPR_CONST(output, "ibat1u");
case SPR_IBAT1L:
SPR_CONST(output, "ibat1l");
case SPR_IBAT2U:
SPR_CONST(output, "ibat2u");
case SPR_IBAT2L:
SPR_CONST(output, "ibat2l");
case SPR_IBAT3U:
SPR_CONST(output, "ibat3u");
case SPR_IBAT3L:
SPR_CONST(output, "ibat3l");
case SPR_DBAT0U:
SPR_CONST(output, "dbat0u");
case SPR_DBAT0L:
SPR_CONST(output, "dbat0l");
case SPR_DBAT1U:
SPR_CONST(output, "dbat1u");
case SPR_DBAT1L:
SPR_CONST(output, "dbat1l");
case SPR_DBAT2U:
SPR_CONST(output, "dbat2u");
case SPR_DBAT2L:
SPR_CONST(output, "dbat2l");
case SPR_DBAT3U:
SPR_CONST(output, "dbat3u");
case SPR_DBAT3L:
SPR_CONST(output, "dbat3l");
case SPR_UMMCR0:
SPR_CONST(output, "ummcr0");
case SPR_UMMCR1:
SPR_CONST(output, "ummcr1");
case SPR_UPMC1:
SPR_CONST(output, "upmc1");
case SPR_UPMC2:
SPR_CONST(output, "upmc2");
case SPR_USIA:
SPR_CONST(output, "usia");
case SPR_UPMC3:
SPR_CONST(output, "upmc3");
case SPR_UPMC4:
SPR_CONST(output, "upmc4");
case SPR_MMCR0:
SPR_CONST(output, "mmcr0");
case SPR_PMC1:
SPR_CONST(output, "pmc1");
case SPR_PMC2:
SPR_CONST(output, "pmc2");
case SPR_SIA:
SPR_CONST(output, "sia");
case SPR_MMCR1:
SPR_CONST(output, "mmcr1");
case SPR_PMC3:
SPR_CONST(output, "pmc3");
case SPR_PMC4:
SPR_CONST(output, "pmc4");
case SPR_SDA:
SPR_CONST(output, "sda");
case SPR_DMISS:
SPR_CONST(output, "dmiss");
case SPR_DCMP:
SPR_CONST(output, "dcmp");
case SPR_HASH1:
SPR_CONST(output, "hash1");
case SPR_HASH2:
SPR_CONST(output, "hash2");
case SPR_IMISS:
SPR_CONST(output, "imiss");
case SPR_ICMP:
SPR_CONST(output, "icmp");
case SPR_RPA:
SPR_CONST(output, "rpa");
case SPR_HID0:
SPR_CONST(output, "hid0");
case SPR_HID1:
SPR_CONST(output, "hid1");
case SPR_IABR:
SPR_CONST(output, "iabr");
case SPR_HID2:
SPR_CONST(output, "hid2");
case SPR_HID4:
SPR_CONST(output, "hid4");
case SPR_DABR:
SPR_CONST(output, "dabr");
case SPR_HID5:
SPR_CONST(output, "hid5");
case SPR_HID6:
SPR_CONST(output, "hid6");
// case SPR_L2CR:
// return SPR_CONST(output, "l2cr");
case SPR_ICTC:
SPR_CONST(output, "ictc");
case SPR_THRM1:
SPR_CONST(output, "thrm1");
case SPR_THRM2:
SPR_CONST(output, "thrm2");
case SPR_THRM3:
SPR_CONST(output, "thrm3");
case SPR_PIR:
SPR_CONST(output, "pir");
default:
snprintf(cspr, sizeof(cspr), "spr_%u", spr);
break;
}
strcpy(output, cspr);
int len = strlen(cspr);
return len > 1 ? len - 1 : 0;
}
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
int max_operands;
} ops[] = {
{ "cmpb", "A = ((byte) B == (byte) C)", 3 }, // 0
{ "cmpd", "A = (B == C)", 3 },
{ "cmpdi", "A = (B == C)", 3 },
{ "cmpld", "A = ((unsigned) B == (unsigned) C)", 3 },
{ "cmpldi", "A = ((unsigned) B == (unsigned) C)", 3 },
{ "cmplw", "A = ((unsigned) B == (unsigned) C)", 3 },
{ "cmplwi", "A = ((unsigned) B == (unsigned) C)", 3 },
{ "cmpw", "A = (B == C)", 3 },
{ "cmpwi", "A = (B == C)", 3 },
{ "beq", "if (A & FLG_EQ) goto B", 2 },
{ "beq-", "if (A & FLG_EQ) goto B", 2 },
{ "beq+", "if (A & FLG_EQ) goto B", 2 },
{ "bge", "if (A & FLG_GE) goto B", 2 },
{ "bge-", "if (A & FLG_GE) goto B", 2 },
{ "bge+", "if (A & FLG_GE) goto B", 2 },
{ "bgt", "if (A & FLG_GT) goto B", 2 },
{ "bgt-", "if (A & FLG_GT) goto B", 2 },
{ "bgt+", "if (A & FLG_GT) goto B", 2 },
{ "ble", "if (A & FLG_LE) goto B", 2 },
{ "ble-", "if (A & FLG_LE) goto B", 2 },
{ "ble+", "if (A & FLG_LE) goto B", 2 },
{ "blt", "if (A & FLG_LT) goto B", 2 },
{ "blt-", "if (A & FLG_LT) goto B", 2 },
{ "blt+", "if (A & FLG_LT) goto B", 2 },
{ "bne", "if (A & FLG_NE) goto B", 2 },
{ "bne-", "if (A & FLG_NE) goto B", 2 },
{ "bne+", "if (A & FLG_NE) goto B", 2 }, // 26
{ "rldic", "A = rol64(B, C) & D", 4 }, // 27
{ "rldcl", "A = rol64(B, C) & D", 4 }, // 28
{ "rldicl", "A = rol64(B, C) & D", 4 }, // 29
{ "rldcr", "A = rol64(B, C) & D", 4 }, // 30
{ "rldicr", "A = rol64(B, C) & D", 4 }, // 31
{ "rldimi", "A = (rol64(B, C) & D) | (A & E)", 5 }, // 32
{ "rlwimi", "A = (rol32(B, C) & D) | (A & E)", 5 }, // 33
{ "rlwimi.", "A = (rol32(B, C) & D) | (A & E)", 5 }, // 33
{ "rlwinm", "A = rol32(B, C) & D", 5 }, // 34
{ "rlwinm.", "A = rol32(B, C) & D", 5 }, // 34
{ "rlwnm", "A = rol32(B, C) & D", 5 }, // 35
{ "rlwnm.", "A = rol32(B, C) & D", 5 }, // 35
{ "td", "if (B A C) trap", 3 }, // 36
{ "tdi", "if (B A C) trap", 3 },
{ "tdu", "if (B A C) trap", 3 },
{ "tdui", "if (B A C) trap", 3 },
{ "tw", "if ((word) B A (word) C) trap", 3 },
{ "twi", "if ((word) B A (word) C) trap", 3 },
{ "twu", "if ((word) B A (word) C) trap", 3 },
{ "twui", "if ((word) B A (word) C) trap", 3 }, // 43
{ "mfspr", "A = B", 2 }, // 44
{ "mtspr", "A = B", 2 }, // 45
{ "add", "A = B + C", 3 },
{ "addc", "A = B + C", 3 },
{ "adde", "A = B + C", 3 },
{ "addi", "A = B + C", 3 },
{ "addic", "A = B + C", 3 },
{ "addis", "A = B + (C << 16)", 3 },
{ "addme", "A = B - A", 2 },
{ "addze", "A = zero extended(B)", 2 },
{ "and", "A = B & C", 3 },
{ "andc", "A = B & C", 3 },
{ "andi", "A = B & C", 3 },
{ "andis", "A = B & (C << 16)", 3 },
{ "attn", "attention A", 1 },
{ "b", "goto A", 1 },
{ "ba", "goto A", 1 },
//{ "bc", "if (a ?? b) goto C", 3},
//{ "bca", "if (a ?? b) goto C", 3},
//{ "bcctr", "if (a ?? b) goto ctr", 2},
//{ "bcctrl", "if (a ?? b) goto ctr", 2},
//{ "bcl", "if (a ?? b) call C", 3},
//{ "bcla", "if (a ?? b) call C", 3},
//{ "bclr", "if (a ?? b) goto C", 3},
//{ "bclrl", "if (a ?? b) call C", 3},
{ "bct", "goto ct", 0 },
{ "bctr", "goto ctr", 3 },
{ "bctrl", "call ctr", 3 },
{ "bdnz", "if (ctr != 0) goto A", 1 },
{ "bdnza", "if (ctr != 0) goto A", 1 },
{ "bdnzf", "if (ctr != 0 && !cond) goto A", 1 },
{ "bdnzfa", "if (ctr != 0 && !cond) goto A", 1 },
{ "bdnzfl", "if (ctr != 0 && !cond) call A", 1 },
{ "bdnzfla", "if (ctr != 0 && !cond) call A", 1 },
{ "bdnzflrl", "if (ctr != 0 && !cond) call A", 1 },
{ "bdnzl", "if (ctr != 0) call A", 1 },
{ "bdnzla", "if (ctr != 0) call A", 1 },
{ "bdnzlr", "if (ctr != 0) return", 1 },
{ "bdnzlrl", "if (ctr != 0) return", 1 },
{ "bdnzt", "if (ctr != 0 && cond) goto A", 1 },
{ "bdnzta", "if (ctr != 0 && cond) goto A", 1 },
{ "bdnztl", "if (ctr != 0 && cond) call A", 1 },
{ "bdnztla", "if (ctr != 0 && cond) call A", 1 },
{ "bdnztlr", "if (ctr != 0 && cond) return", 1 },
{ "bdnztlrl", "if (ctr != 0 && cond) return", 1 },
{ "bdz", "if (ctr == 0) goto A", 1 },
{ "bdza", "if (ctr == 0) goto A", 1 },
{ "bdzf", "if (ctr == 0 && !cond) goto A", 1 },
{ "bdzfa", "if (ctr == 0 && !cond) goto A", 1 },
{ "bdzfl", "if (ctr == 0 && !cond) call A", 1 },
{ "bdzfla", "if (ctr == 0 && !cond) call A", 1 },
{ "bdzflr", "if (ctr == 0 && !cond) return", 1 },
{ "bdzflrl", "if (ctr == 0 && !cond) returnA", 1 },
{ "bdzl", "if (ctr == 0) call A", 1 },
{ "bdzla", "if (ctr == 0) call A", 1 },
{ "bdzlr", "if (ctr == 0) return", 1 },
{ "bdzlrl", "if (ctr == 0) return", 1 },
{ "bdzt", "if (ctr == 0 && cond) goto A", 1 },
{ "bdzta", "if (ctr == 0 && cond) goto A", 1 },
{ "bdztl", "if (ctr == 0 && cond) call A", 1 },
{ "bdztla", "if (ctr == 0 && cond) call A", 1 },
{ "bdztlr", "if (ctr == 0 && cond) return", 1 },
{ "bdztlrl", "if (ctr == 0 && cond) return", 1 },
{ "bf", "if (!A) goto B", 1 },
{ "bfa", "if (!cond) goto A", 1 },
{ "bfctr", "if (!cond) goto ctr", 0 },
{ "bfctrl", "if (!cond) call ctr", 0 },
{ "bfl", "if (!A) call B", 1 },
{ "bfla", "if (!cond) call A", 1 },
{ "bflr", "if (!A) return", 1 },
{ "bflrl", "if (!A) return", 1 },
{ "bl", "call A", 1 },
{ "bla", "call A", 1 },
{ "blr", "return", 0 },
{ "blrl", "return", 0 },
{ "bltlr", "if (A & FLG_LT) return", 1 },
{ "blelr", "if (A & FLG_LE) return", 1 },
{ "bgtlr", "if (A & FLG_GT) return", 1 },
{ "bgelr", "if (A & FLG_GE) return", 1 },
{ "bnelr", "if (A & FLG_NE) return", 1 },
{ "beqlr", "if (A & FLG_EQ) return", 1 },
{ "brinc", "A = bit_revese(B, C)", 3 },
{ "bt", "if (A) goto B", 1 },
{ "bta", "if (cond) goto A", 1 },
{ "btctr", "if (cond) goto ctr", 1 },
{ "btctrl", "if (cond) call ctr", 1 },
{ "btl", "if (A) call B", 1 },
{ "btla", "if (cond) call A", 1 },
{ "btlr", "if (A) return", 1 },
{ "btlrl", "if (A) return", 1 },
{ "clrldi", "A = B & mask(0, C)", 2 },
{ "clrlwi", "A = B & mask(0, C)", 2 },
{ "cntlzd", "A = cnt_leading_zeros(B)", 2 },
{ "cntlzw", "A = cnt_leading_zeros(B)", 2 },
{ "crand", "A = B & C", 3 },
{ "crandc", "A = B & C", 3 },
{ "crclr", "A = A ^ A", 1 },
{ "creqv", "A = B == C", 3 },
{ "crmove", "A = B", 2 },
{ "crnand", "A = B & !C", 3 },
{ "crnor", "A = B | !C", 3 },
{ "crnot", "A = !B", 2 },
{ "cror", "A = B | C", 3 },
{ "crorc", "A = B | C", 3 },
{ "crset", "A = B", 2 },
{ "crxor", "A = B ^ C", 3 },
{ "dcba", "dcb_alloc(A,B)", 2 },
{ "dcbf", "dcb_flush(A,B)", 2 },
{ "dcbi", "dcb_inval(A,B)", 2 },
{ "dcbst", "dcb_store(A,B)", 2 },
{ "dcbt", "dcb_touch(A,B)", 2 },
{ "dcbtst", "dcb_touch_store(A, B)", 2 },
{ "dcbz", "dcb_zero(A,B)", 2 },
{ "dcbzl", "dcb_zero_line(A, B)", 2 },
{ "dccci", "dcc_inval(A, B)", 3 }, // Data Cache Congruence Class Invalidate
{ "divd", "A = B / C", 3 },
{ "divdu", "A = (unsigned) B / C", 3 },
{ "divw", "A = (word) B / C", 3 },
{ "divwu", "A = (word unsigned) B / C", 3 },
{ "dss", "altivec_ds_stop(A)", 1 },
{ "dssall", "altivec_ds_stop_all", 0 },
{ "dst", "altivec_ds_touch(A,B,C)", 3 },
{ "dstst", "altivec_ds_touch_store(A, B, C)", 3 },
{ "dststt", "altivec_ds_touch_store_tran(A, B, C)", 3 },
{ "dstt", "altivec_ds_touch_tran(A, B, C)", 3 },
{ "eieio", "enforce_in_order_exec_io", 0 },
{ "eqv", "A = B ^ C", 3 },
{ "evabs", "A = (vector) abs(B)", 2 },
{ "evaddiw", "A = (vector) B + C", 3 },
{ "evaddsmiaaw", "A = (vector) B + C", 3 },
{ "evaddssiaaw", "A = (vector) B + C", 3 },
{ "evaddumiaaw", "A = (vector) B + C", 3 },
{ "evaddusiaaw", "A = (vector) B + C", 3 },
{ "evaddw", "A = (vector) B + C", 3 },
{ "evand", "A = (vector) B + C", 3 },
{ "evandc", "A = (vector) B + C", 3 },
{ "evcmpeq", "A = (vector) B == C", 3 },
{ "evcmpgts", "A = (vector) B > C", 3 },
{ "evcmpgtu", "A = (unsigned vector) B > C", 3 },
{ "evcmplts", "A = (vector) B < C", 3 },
{ "evcmpltu", "A = (unsigned vector) B <> C", 3 },
{ "evcntlsw", "A = (vector) cnt_sign_bits(B)", 2 },
{ "evcntlzw", "A = (vector) cnt_zero_bits(B)", 2 },
{ "evdivws", "A = (vector) B / C", 3 },
{ "evdivwu", "A = (unsigned vector) B + C", 3 },
{ "eveqv", "A = (vector) B ^ C", 3 },
//{ "evextsb", "", 0}, //extend sign byte
//{ "evextsh", "", 0}, //extend sign half
{ "evldd", "A = vector[C + B]", 3 },
{ "evlddx", "A = vector[C + B]", 3 },
{ "evldh", "A = vector[C + B]", 3 },
{ "evldhx", "A = vector[C + B]", 3 },
{ "evldw", "A = vector[C + B]", 3 },
{ "evldwx", "A = vector[C + B]", 3 },
// Vector Load Half Word into Half Words Even and Splat ??
/*
{ "evlhhesplat", "A = B + C", 3},
{ "evlhhesplatx", "A = B + C", 3},
{ "evlhhossplat", "A = B + C", 3},
{ "evlhhossplatx", "A = B + C", 3},
{ "evlhhousplat", "A = B + C", 3},
{ "evlhhousplatx", "A = B + C", 3},
*/
{ "evlwhe", "A = vector[C + B]", 3 },
{ "evlwhex", "A = vector[C + B]", 3 },
{ "evlwhos", "A = vector[C + B]", 3 },
{ "evlwhosx", "A = vector[C + B]", 3 },
{ "evlwhou", "A = vector[C + B]", 3 },
{ "evlwhoux", "A = vector[C + B]", 3 },
/*
{ "evlwhsplat", "A = vector[C + B]", 3},
{ "evlwhsplatx", "A = vector[C + B]", 3},
{ "evlwwsplat", "A = vector[C + B]", 3},
{ "evlwwsplatx", "A = vector[C + B]", 3},
{ "evmergehi", "A = lo | hi", 3},
{ "evmergehilo", "A = B + C", 3},
{ "evmergelo", "A = B + C", 3},
{ "evmergelohi", "A = B + C", 3},
{ "evmhegsmfaa", "A = B + C", 3},
{ "evmhegsmfan", "A = B + C", 3},
{ "evmhegsmiaa", "A = B + C", 3},
{ "evmhegsmian", "A = B + C", 3},
{ "evmhegumiaa", "A = B + C", 3},
{ "evmhegumian", "A = B + C", 3},
{ "evmhesmf", "A = B + C", 3},
{ "evmhesmfa", "A = B + C", 3},
{ "evmhesmfaaw", "A = B + C", 3},
{ "evmhesmfanw", "A = B + C", 3},
{ "evmhesmi", "A = B + C", 3},
{ "evmhesmia", "A = B + C", 3},
{ "evmhesmiaaw", "A = B + C", 3},
{ "evmhesmianw", "A = B + C", 3},
{ "evmhessf", "A = B + C", 3},
{ "evmhessfa", "A = B + C", 3},
{ "evmhessfaaw", "A = B + C", 3},
{ "evmhessfanw", "A = B + C", 3},
{ "evmhessiaaw", "A = B + C", 3},
{ "evmhessianw", "A = B + C", 3},
{ "evmheumi", "A = B + C", 3},
{ "evmheumia", "A = B + C", 3},
{ "evmheumiaaw", "A = B + C", 3},
{ "evmheumianw", "A = B + C", 3},
{ "evmheusiaaw", "A = B + C", 3},
{ "evmheusianw", "A = B + C", 3},
{ "evmhogsmfaa", "A = B + C", 3},
{ "evmhogsmfan", "A = B + C", 3},
{ "evmhogsmiaa", "A = B + C", 3},
{ "evmhogsmian", "A = B + C", 3},
{ "evmhogumiaa", "A = B + C", 3},
{ "evmhogumian", "A = B + C", 3},
{ "evmhosmf", "A = B + C", 3},
{ "evmhosmfa", "A = B + C", 3},
{ "evmhosmfaaw", "A = B + C", 3},
{ "evmhosmfanw", "A = B + C", 3},
{ "evmhosmi", "A = B + C", 3},
{ "evmhosmia", "A = B + C", 3},
{ "evmhosmiaaw", "A = B + C", 3},
{ "evmhosmianw", "A = B + C", 3},
{ "evmhossf", "A = B + C", 3},
{ "evmhossfa", "A = B + C", 3},
{ "evmhossfaaw", "A = B + C", 3},
{ "evmhossfanw", "A = B + C", 3},
{ "evmhossiaaw", "A = B + C", 3},
{ "evmhossianw", "A = B + C", 3},
{ "evmhoumi", "A = B + C", 3},
{ "evmhoumia", "A = B + C", 3},
{ "evmhoumiaaw", "A = B + C", 3},
{ "evmhoumianw", "A = B + C", 3},
{ "evmhousiaaw", "A = B + C", 3},
{ "evmhousianw", "A = B + C", 3},
{ "evmra", "A = B + C", 3},
{ "evmwhsmf", "A = B + C", 3},
{ "evmwhsmfa", "A = B + C", 3},
{ "evmwhsmi", "A = B + C", 3},
{ "evmwhsmia", "A = B + C", 3},
{ "evmwhssf", "A = B + C", 3},
{ "evmwhssfa", "A = B + C", 3},
{ "evmwhumi", "A = B + C", 3},
{ "evmwhumia", "A = B + C", 3},
{ "evmwlsmiaaw", "A = B + C", 3},
{ "evmwlsmianw", "A = B + C", 3},
{ "evmwlssiaaw", "A = B + C", 3},
{ "evmwlssianw", "A = B + C", 3},
{ "evmwlumi", "A = B + C", 3},
{ "evmwlumia", "A = B + C", 3},
{ "evmwlumiaaw", "A = B + C", 3},
{ "evmwlumianw", "A = B + C", 3},
{ "evmwlusiaaw", "A = B + C", 3},
{ "evmwlusianw", "A = B + C", 3},
{ "evmwsmf", "A = B + C", 3},
{ "evmwsmfa", "A = B + C", 3},
{ "evmwsmfaa", "A = B + C", 3},
{ "evmwsmfan", "A = B + C", 3},
{ "evmwsmi", "A = B + C", 3},
{ "evmwsmia", "A = B + C", 3},
{ "evmwsmiaa", "A = B + C", 3},
{ "evmwsmian", "A = B + C", 3},
{ "evmwssf", "A = B + C", 3},
{ "evmwssfa", "A = B + C", 3},
{ "evmwssfaa", "A = B + C", 3},
{ "evmwssfan", "A = B + C", 3},
{ "evmwumi", "A = B + C", 3},
{ "evmwumia", "A = B + C", 3},
{ "evmwumiaa", "A = B + C", 3},
{ "evmwumian", "A = B + C", 3},
{ "evnand", "A = B + C", 3},
{ "evneg", "A = B + C", 3},
{ "evnor", "A = B + C", 3},
{ "evor", "A = B + C", 3},
{ "evorc", "A = B + C", 3},
{ "evrlw", "A = B + C", 3},
{ "evrlwi", "A = B + C", 3},
{ "evrndw", "A = B + C", 3},
{ "evslw", "A = B + C", 3},
{ "evslwi", "A = B + C", 3},
{ "evsplatfi", "A = B + C", 3},
{ "evsplati", "A = B + C", 3},
{ "evsrwis", "A = B + C", 3},
{ "evsrwiu", "A = B + C", 3},
{ "evsrws", "A = B + C", 3},
{ "evsrwu", "A = B + C", 3},
{ "evstdd", "A = B + C", 3},
{ "evstddx", "A = B + C", 3},
{ "evstdh", "A = B + C", 3},
{ "evstdhx", "A = B + C", 3},
{ "evstdw", "A = B + C", 3},
{ "evstdwx", "A = B + C", 3},
{ "evstwhe", "A = B + C", 3},
{ "evstwhex", "A = B + C", 3},
{ "evstwho", "A = B + C", 3},
{ "evstwhox", "A = B + C", 3},
{ "evstwwe", "A = B + C", 3},
{ "evstwwex", "A = B + C", 3},
{ "evstwwo", "A = B + C", 3},
{ "evstwwox", "A = B + C", 3},
{ "evsubfsmiaaw", "A = B + C", 3},
{ "evsubfssiaaw", "A = B + C", 3},
{ "evsubfumiaaw", "A = B + C", 3},
{ "evsubfusiaaw", "A = B + C", 3},
{ "evsubfw", "A = B + C", 3},
{ "evsubifw", "A = B + C", 3},
{ "evxor", "A = B + C", 3},
*/
{ "extsb", "A = extend_sign(B)", 2 },
{ "extsh", "A = extend_sign(B)", 2 },
{ "extsw", "A = extend_sign(B)", 2 },
{ "fabs", "A = abs(B)", 2 },
{ "fadd", "A = B + C", 3 },
{ "fadds", "A = (float) B + C", 3 },
{ "fcfid", "A = (double) B", 2 },
{ "fcfids", "A = (float) B", 2 },
{ "fcfidu", "A = (double) B", 2 },
{ "fcfidus", "A = (float) B", 2 },
{ "fcmpu", "A = B == C", 3 },
// This should copy the sign of bit 0 of reg B & c
{ "fcpsgn", "A = flt_copy_sign(B,C)", 3 },
{ "fctid", "A = (int64) B", 2 },
{ "fctiduz", "A = (uint64) B + C", 3 },
{ "fctidz", "A = (int64) B + C", 3 },
{ "fctiw", "A = (int32) B + C", 3 },
{ "fctiwuz", "A = (uint32) B + C", 3 },
{ "fctiwz", "A = (int32) B + C", 3 },
{ "fdiv", "A = B / C", 3 },
{ "fdivs", "A = (float) B / C", 3 },
{ "fmadd", "A = (B * C) + D", 4 },
{ "fmadds", "A = (float) (B * C) + D", 3 },
{ "fmr", "A = B", 2 },
{ "fmsub", "A = (B * C) - d", 4 },
{ "fmsubs", "A = (float) (B * C) - D", 4 },
{ "fmul", "A = B * C", 3 },
{ "fmuls", "A = (float) B * C", 3 },
{ "fnabs", "A = - abs(B)", 2 },
{ "fneg", "A = - B", 2 },
{ "fnmadd", "A = -((B * C) + D)", 4 },
{ "fnmadds", "A = (float) -((B * C) + D)", 4 },
{ "fnmsub", "A = -((B * C) - D)", 4 },
{ "fnmsubs", "A = (float) -((B * C) - D)", 4 },
{ "fre", "A = 1/B", 2 },
{ "fres", "A = (float) 1/B", 2 },
{ "frim", "A = trunc(B)", 2 },
{ "frin", "A = floor(B)", 2 },
{ "frip", "A = ceil(B)", 2 },
{ "friz", "A = trunc(B)", 2 },
{ "frsp", "A = (float) B", 3 },
{ "frsqrte", "A = 1/sqrt(B)", 2 },
{ "frsqrtes", "A = (float) 1/sqrt(B)", 2 },
{ "fsel", "if (B >= 0.0) A = C; else A = D", 4 },
{ "fsqrt", "A = sqrt(B)", 2 },
{ "fsqrts", "A = (float) sqrt(B)", 3 },
{ "fsub", "A = B - C", 3 },
{ "fsubs", "A = (float) B - C", 3 },
{ "icbi", "inst_cache_block_inval", 0 },
{ "icbt", "inst_cache_block_touch", 3 },
{ "iccci", "inst_cache_inval(A,B)", 2 },
// isel lt Rx,Ry,Rz (equivalent to: isel Rx,Ry,Rz,0)
// isel gt Rx,Ry,Rz (equivalent to: isel Rx,Ry,Rz,1)
// isel eq Rx,Ry,Rz (equivalent to: isel Rx,Ry,Rz,2)
// { "isel", "", 4},
{ "isync", "sync_instr_cache", 0 },
{ "la", "A = C + B", 3 },
{ "lbz", "A = byte[C + B]", 3 },
{ "lbzcix", "A = byte[C + B]", 3 },
{ "lbzu", "A = byte[C + B]", 3 },
{ "lbzux", "A = Byte[C + B]", 3 },
{ "lbzx", "A = byte[C + B]", 3 },
{ "ld", "A = [C + B]", 3 },
// No clue how to represent them since they are kinda complex..
// { "ldarx", "A = [C + B]", 3},
// { "ldbrx", "A = [C + B]", 3},
// { "ldcix", "A = B + C", 3},
{ "ldu", "A = [C + B]", 3 },
{ "ldux", "A = [C + B]", 3 },
{ "ldx", "A = [C + B]", 3 },
{ "lfd", "A = double[C + B]", 3 },
{ "lfdu", "A = double[C + B]", 3 },
{ "lfdux", "A = double[C + B]", 3 },
{ "lfdx", "A = double[C + B]", 3 },
{ "lfiwax", "A = float[C + B]", 3 },
{ "lfiwzx", "A = float[C + B]", 3 },
{ "lfs", "A = float[C + B]", 3 },
{ "lfsu", "A = float[C + B]", 3 },
{ "lfsux", "A = float[C + B]", 3 },
{ "lfsx", "A = float[C + B]", 3 },
{ "lha", "A = half[C + B]", 3 },
{ "lhau", "A = half[C + B]", 3 },
{ "lhaux", "A = half[C + B]", 3 },
{ "lhax", "A = half[C + B]", 3 },
{ "lhbrx", "A = half[C + B]", 3 },
{ "lhz", "A = half[C + B]", 3 },
{ "lhzcix", "A = half[C + B]", 3 },
{ "lhzu", "A = half[C + B]", 3 },
{ "lhzux", "A = half[C + B]", 3 },
{ "lhzx", "A = half[C + B]", 3 },
{ "li", "A = B", 2 },
{ "lis", "A = (B << 16)", 2 },
{ "lmw", "A = multiple word[C + B]", 3 },
{ "lswi", "A = string word[C + B]", 3 },
{ "lvebx", "A = vector[C + B]", 3 },
{ "lvehx", "A = vector[C + B]", 3 },
{ "lvewx", "A = vector[C + B]", 3 },
{ "lvsl", "A = vector[C + B]", 3 },
{ "lvsr", "A = vector[C + B]", 3 },
{ "lvx", "A = vector[C + B]", 3 },
{ "lvxl", "A = vector[C + B]", 3 },
{ "lwa", "A = word[C + B]", 3 },
{ "lwarx", "A = word[C + B]", 3 },
{ "lwaux", "A = word[C + B]", 3 },
{ "lwax", "A = word[C + B]", 3 },
{ "lwbrx", "A = word[C + B]", 3 },
{ "lwsync", "sync_load_store", 0 },
{ "lwz", "A = word[C + B]", 3 },
{ "lwzcix", "A = word[C + B]", 3 },
{ "lwzu", "A = word[C + B]", 3 },
{ "lwzux", "A = word[C + B]", 3 },
{ "lwzx", "A = word[C + B]", 3 },
// { "lxsdx", "A = ???[C + B]", 3},
{ "lxvdbx", "A = vector[C + B]", 3 },
{ "lxvdsx", "A = vector[C + B]", 3 },
{ "lxvwdx", "A = vector[C + B]", 3 },
{ "mbar", "memory_barrier(A)", 1 },
{ "mcrf", "A = B", 2 },
{ "mcrfs", "A = B", 2 },
{ "mfamr", "A = amr", 1 },
{ "mfasr", "A = asr", 1 },
{ "mfbr0", "A = br0", 1 },
{ "mfbra", "A = br1", 1 },
{ "mfbrb", "A = br2", 1 },
{ "mfbrc", "A = br3", 1 },
{ "mfbrd", "A = br4", 1 },
{ "mfbr5", "A = br5", 1 },
{ "mfbr6", "A = br6", 1 },
{ "mfbr7", "A = br7", 1 },
{ "mfcfar", "A = cfar", 3 },
{ "mfcr", "A = crB", 2 },
{ "mfctr", "A = ctr", 3 },
{ "mfdar", "A = dar", 1 },
{ "mfdbatl", "A = dbatBl", 1 },
{ "mfdbatu", "A = dbatBu", 1 },
{ "mfdccr", "A = dccr", 1 },
{ "mfdcr", "A = dcr", 1 },
{ "mfdear", "A = dear", 1 },
{ "mfdscr", "A = dscr", 1 },
{ "mfdsisr", "A = dsisr", 1 },
{ "mfesr", "A = esr", 1 },
{ "mffs", "A = fs", 1 },
{ "mfibatl", "A = ibatBl", 2 },
{ "mfibatu", "A = ibatBu", 2 },
{ "mficcr", "A = iccr", 1 },
{ "mflr", "A = lr", 1 },
{ "mfmsr", "A = msr", 1 },
{ "mfocrf", "A = ocrf", 1 },
{ "mfpid", "A = pid", 1 },
{ "mfpvr", "A = pvr", 1 },
{ "mfrtcl", "A = rtc_lo", 1 },
{ "mfrtcu", "A = rtc_hi", 1 },
{ "mfspefscr", "A = fscr", 1 },
{ "mfsr", "A = srB", 3 },
{ "mfsrin", "A = sr_indirect(B)", 2 },
{ "mfsrr2", "A = srr2", 1 },
{ "mfsrr3", "A = srr3", 1 },
{ "mftb", "A = tb(B)", 2 },
{ "mftbhi", "A = tb_hi(B)", 2 },
{ "mftblo", "A = tb_lo(B)", 2 },
{ "mftbu", "A = tbu", 1 },
{ "mftcr", "A = tcr", 1 },
{ "mfvscr", "A = vscr", 1 },
{ "mfxer", "A = xer", 1 },
{ "mr", "A = B", 2 },
{ "msync", "sync_memory", 3 },
{ "mtamr", "amr = A", 1 },
{ "mtbr0", "br0 = A", 1 },
{ "mtbr1", "br1 = A", 1 },
{ "mtbr2", "br2 = A", 1 },
{ "mtbr3", "br3 = A", 1 },
{ "mtbr4", "br4 = A", 1 },
{ "mtbr5", "br5 = A", 1 },
{ "mtbr6", "br6 = A", 1 },
{ "mtbr7", "br7 = A", 1 },
{ "mtcfar", "cfar = A", 1 },
{ "mtcr", "tcr = A", 1 },
{ "mtcrf", "crf = A", 1 },
{ "mtctr", "ctr = A", 1 },
{ "mtdar", "dar = A", 1 },
{ "mtdbatl", "dbatBl = A", 2 },
{ "mtdbatu", "dbatBu = A", 2 },
{ "mtdccr", "dccr = A", 1 },
{ "mtdcr", "dcr = A", 1 },
{ "mtdear", "dear = A", 1 },
{ "mtdscr", "dscr = A", 1 },
{ "mtdsisr", "dsisr = A", 1 },
{ "mtesr", "esr = A", 1 },
{ "mtfsb0", "fsb0 = A", 1 },
{ "mtfsb1", "fsb1 = A", 1 },
{ "mtfsf", "fsf = A", 1 },
{ "mtfsfi", "fsfi = A", 1 },
{ "mtibatl", "ibatBl = A", 2 },
{ "mtibatu", "ibatBu = A", 2 },
{ "mticcr", "iccr = A", 1 },
{ "mtlr", "lr = A", 1 },
{ "mtmsr", "msr = A", 1 },
{ "mtmsrd", "msr = A", 1 },
{ "mtocrf", "cr0 = B & fxm_mask(A)", 2 },
{ "mtpid", "pid = A", 1 },
{ "mtspefscr", "fscr = A", 1 },
{ "mtsr", "srA = B", 2 },
{ "mtsrin", "sr_indirect(A) = B", 2 },
{ "mtsrr2", "srr2 = A", 1 },
{ "mtsrr3", "srr3 = A ", 1 },
{ "mttbhi", "tb_hi(A) = B", 2 },
{ "mttbl", "tbl(A) = B", 2 },
{ "mttblo", "tb_lo(A) = B", 2 },
{ "mttbu", "tbu = A", 1 },
{ "mtvscr", "vscr = A", 1 },
{ "mtxer", "xer = A", 1 },
{ "mulhd", "A = hi(B) * hi(C)", 3 },
{ "mulhdu", "A = (unsigned) hi(B) * hi(C)", 3 },
{ "mulhw", "A = (word) hi(B) * hi(C)", 3 },
{ "mulhwu", "A = (unsigned word) hi(B) * hi(C)", 3 },
{ "mulld", "A = lo(B) * lo(C)", 3 },
{ "mulli", "A = lo(B) * lo(C)", 3 },
{ "mullw", "A = (word) lo(B) * lo(C)", 3 },
{ "nand", "A = B & !C", 3 },
{ "neg", "A = -B", 2 },
{ "nop", "", 0 },
{ "nor", "A = B | !C", 3 },
{ "not", "A = !B", 2 },
{ "or", "A = B | C", 3 },
{ "orc", "A = B | C", 3 },
{ "ori", "A = B | C", 3 },
{ "oris", "A = B | (C << 16)", 3 },
{ "popcntd", "A = count_bits(B)", 2 },
{ "popcntw", "A = count_bits(B)", 2 },
{ "ptesync", "sync_page_tbl", 0 },
// Are you kidding? QPX Architecture totally NO.
/*
{ "qvaligni", "A = B + C", 3},
{ "qvesplati", "A = B + C", 3},
{ "qvfabs", "A = B + C", 3},
{ "qvfadd", "A = B + C", 3},
{ "qvfadds", "A = B + C", 3},
{ "qvfand", "A = B + C", 3},
{ "qvfandc", "A = B + C", 3},
{ "qvfcfid", "A = B + C", 3},
{ "qvfcfids", "A = B + C", 3},
{ "qvfcfidu", "A = B + C", 3},
{ "qvfcfidus", "A = B + C", 3},
{ "qvfclr", "A = B + C", 3},
{ "qvfcmpeq", "A = B + C", 3},
{ "qvfcmpgt", "A = B + C", 3},
{ "qvfcmplt", "A = B + C", 3},
{ "qvfcpsgn", "A = B + C", 3},
{ "qvfctfb", "A = B + C", 3},
{ "qvfctid", "A = B + C", 3},
{ "qvfctidu", "A = B + C", 3},
{ "qvfctiduz", "A = B + C", 3},
{ "qvfctidz", "A = B + C", 3},
{ "qvfctiw", "A = B + C", 3},
{ "qvfctiwu", "A = B + C", 3},
{ "qvfctiwuz", "A = B + C", 3},
{ "qvfctiwz", "A = B + C", 3},
{ "qvfequ", "A = B + C", 3},
{ "qvflogical", "A = B + C", 3},
{ "qvfmadd", "A = B + C", 3},
{ "qvfmadds", "A = B + C", 3},
{ "qvfmr", "A = B + C", 3},
{ "qvfmsub", "A = B + C", 3},
{ "qvfmsubs", "A = B + C", 3},
{ "qvfmul", "A = B + C", 3},
{ "qvfmuls", "A = B + C", 3},
{ "qvfnabs", "A = B + C", 3},
{ "qvfnand", "A = B + C", 3},
{ "qvfneg", "A = B + C", 3},
{ "qvfnmadd", "A = B + C", 3},
{ "qvfnmadds", "A = B + C", 3},
{ "qvfnmsub", "A = B + C", 3},
{ "qvfnmsubs", "A = B + C", 3},
{ "qvfnor", "A = B + C", 3},
{ "qvfnot", "A = B + C", 3},
{ "qvfor", "A = B + C", 3},
{ "qvforc", "A = B + C", 3},
{ "qvfperm", "A = B + C", 3},
{ "qvfre", "A = B + C", 3},
{ "qvfres", "A = B + C", 3},
{ "qvfrim", "A = B + C", 3},
{ "qvfrin", "A = B + C", 3},
{ "qvfrip", "A = B + C", 3},
{ "qvfriz", "A = B + C", 3},
{ "qvfrsp", "A = B + C", 3},
{ "qvfrsqrte", "A = B + C", 3},
{ "qvfrsqrtes", "A = B + C", 3},
{ "qvfsel", "A = B + C", 3},
{ "qvfset", "A = B + C", 3},
{ "qvfsub", "A = B + C", 3},
{ "qvfsubs", "A = B + C", 3},
{ "qvftstnan", "A = B + C", 3},
{ "qvfxmadd", "A = B + C", 3},
{ "qvfxmadds", "A = B + C", 3},
{ "qvfxmul", "A = B + C", 3},
{ "qvfxmuls", "A = B + C", 3},
{ "qvfxor", "A = B + C", 3},
{ "qvfxxcpnmadd", "A = B + C", 3},
{ "qvfxxcpnmadds", "A = B + C", 3},
{ "qvfxxmadd", "A = B + C", 3},
{ "qvfxxmadds", "A = B + C", 3},
{ "qvfxxnpmadd", "A = B + C", 3},
{ "qvfxxnpmadds", "A = B + C", 3},
{ "qvgpci", "A = B + C", 3},
{ "qvlfcdux", "A = B + C", 3},
{ "qvlfcduxa", "A = B + C", 3},
{ "qvlfcdx", "A = B + C", 3},
{ "qvlfcdxa", "A = B + C", 3},
{ "qvlfcsux", "A = B + C", 3},
{ "qvlfcsuxa", "A = B + C", 3},
{ "qvlfcsx", "A = B + C", 3},
{ "qvlfcsxa", "A = B + C", 3},
{ "qvlfdux", "A = B + C", 3},
{ "qvlfduxa", "A = B + C", 3},
{ "qvlfdx", "A = B + C", 3},
{ "qvlfdxa", "A = B + C", 3},
{ "qvlfiwax", "A = B + C", 3},
{ "qvlfiwaxa", "A = B + C", 3},
{ "qvlfiwzx", "A = B + C", 3},
{ "qvlfiwzxa", "A = B + C", 3},
{ "qvlfsux", "A = B + C", 3},
{ "qvlfsuxa", "A = B + C", 3},
{ "qvlfsx", "A = B + C", 3},
{ "qvlfsxa", "A = B + C", 3},
{ "qvlpcldx", "A = B + C", 3},
{ "qvlpclsx", "A = B + C", 3},
{ "qvlpcrdx", "A = B + C", 3},
{ "qvlpcrsx", "A = B + C", 3},
{ "qvstfcdux", "A = B + C", 3},
{ "qvstfcduxa", "A = B + C", 3},
{ "qvstfcduxi", "A = B + C", 3},
{ "qvstfcduxia", "A = B + C", 3},
{ "qvstfcdx", "A = B + C", 3},
{ "qvstfcdxa", "A = B + C", 3},
{ "qvstfcdxi", "A = B + C", 3},
{ "qvstfcdxia", "A = B + C", 3},
{ "qvstfcsux", "A = B + C", 3},
{ "qvstfcsuxa", "A = B + C", 3},
{ "qvstfcsuxi", "A = B + C", 3},
{ "qvstfcsuxia", "A = B + C", 3},
{ "qvstfcsx", "A = B + C", 3},
{ "qvstfcsxa", "A = B + C", 3},
{ "qvstfcsxi", "A = B + C", 3},
{ "qvstfcsxia", "A = B + C", 3},
{ "qvstfdux", "A = B + C", 3},
{ "qvstfduxa", "A = B + C", 3},
{ "qvstfduxi", "A = B + C", 3},
{ "qvstfduxia", "A = B + C", 3},
{ "qvstfdx", "A = B + C", 3},
{ "qvstfdxa", "A = B + C", 3},
{ "qvstfdxi", "A = B + C", 3},
{ "qvstfdxia", "A = B + C", 3},
{ "qvstfiwx", "A = B + C", 3},
{ "qvstfiwxa", "A = B + C", 3},
{ "qvstfsux", "A = B + C", 3},
{ "qvstfsuxa", "A = B + C", 3},
{ "qvstfsuxi", "A = B + C", 3},
{ "qvstfsuxia", "A = B + C", 3},
{ "qvstfsx", "A = B + C", 3},
{ "qvstfsxa", "A = B + C", 3},
{ "qvstfsxi", "A = B + C", 3},
{ "qvstfsxia", "A = B + C", 3},
*/
{ "rfci", "msr = csrr1; nia = csrr0; ret", 0 },
{ "rfdi", "msr = drr1; nia = drr0; ret", 0 },
{ "rfi", "msr = srr1; nia = srr0; ret", 0 },
{ "rfid", "msr = srr1; nia = srr0; ret", 0 },
{ "rfmci", "msr = mcrr1; nia = mcrr0; ret", 3 },
{ "rotld", "A = rot64(B,C)", 3 },
{ "rotldi", "A = rot64(B,C)", 3 },
{ "rotlw", "A = rot32(B,C)", 3 },
{ "rotlwi", "A = rot32(B,C)", 3 },
{ "sc", "syscall", 0 },
{ "slbia", "slb_inval_all", 0 },
{ "slbie", "slb_inval_entry(A)", 1 },
{ "slbmfee", "A = slb[B]", 2 },
{ "slbmte", "slb[A] = B", 2 },
{ "sld", "A = B << C", 3 },
{ "sldi", "A = B << C", 3 },
{ "slw", "A = (word) B << C", 3 },
{ "slwi", "A = (word) B << C", 3 },
{ "srad", "A = B >> C", 3 },
{ "sradi", "A = B >> C", 3 },
{ "sraw", "A = (word) B >> C", 3 },
{ "srawi", "A = (word) B >> C", 3 },
{ "srd", "A = B >> C", 3 },
{ "srw", "A = (word) B >> C", 3 },
{ "srwi", "A = (word) B >> C", 3 },
{ "stb", "byte[C + B] = A", 3 },
{ "stbcix", "byte[C + B] = A", 3 },
{ "stbu", "byte[C + B] = A", 3 },
{ "stbux", "byte[C + B] = A", 3 },
{ "stbx", "byte[C + B] = A", 3 },
{ "std", "[C + B] = A", 3 },
{ "stdbrx", "[C + B] = A", 3 },
{ "stdcix", "[C + B] = A", 3 },
{ "stdcx", "[C + B] = A", 3 },
{ "stdu", "[C + B] = A", 3 },
{ "stdux", "[C + B] = A", 3 },
{ "stdx", "[C + B] = A", 3 },
{ "stfd", "float[C + B] = A", 3 },
{ "stfdu", "float[C + B] = A", 3 },
{ "stfdux", "float[C + B] = A", 3 },
{ "stfdx", "float[C + B] = A", 3 },
{ "stfiwx", "float[C + B] = A", 3 },
{ "stfs", "float[C + B] = A", 3 },
{ "stfsu", "float[C + B] = A", 3 },
{ "stfsux", "float[C + B] = A", 3 },
{ "stfsx", "float[C + B] = A", 3 },
{ "sth", "half[C + B] = A", 3 },
{ "sthbrx", "half[C + B] = A", 3 },
{ "sthcix", "half[C + B] = A", 3 },
{ "sthu", "half[C + B] = A", 3 },
{ "sthux", "half[C + B] = A", 3 },
{ "sthx", "half[C + B] = A", 3 },
{ "stmw", "multiple word[C + B] = A", 3 },
{ "stswi", "string word[C + B] = A", 3 },
{ "stvebx", "vector byte[C + B] = A", 3 },
{ "stvehx", "vector half[C + B] = A", 3 },
{ "stvewx", "vector word[C + B] = A", 3 },
{ "stvx", "vector[C + B] = A", 3 },
{ "stvxl", "vector[C + B] = A", 3 },
{ "stw", "word[C + B] = A", 3 },
{ "stwbrx", "word[C + B] = A", 3 },
{ "stwcix", "word[C + B] = A", 3 },
{ "stwcx", "word[C + B] = A", 3 },
{ "stwu", "word[C + B] = A", 3 },
{ "stwux", "word[C + B] = A", 3 },
{ "stwx", "word[C + B] = A", 3 },
{ "stxsdx", "vsx[C + B] = A", 3 },
{ "stxvdbx", "vector double[C + B] = A", 3 },
{ "stxvwdx", "vector word[C + B] = A", 3 },
{ "sub", "A = C - B", 3 },
{ "subc", "A = C - B", 3 },
{ "subf", "A = C - B", 3 },
{ "subfc", "A = C - B", 3 },
{ "subfe", "A = C - B", 3 },
{ "subfic", "A = C - B", 3 },
{ "subfme", "A = C - B", 3 },
{ "subfze", "A = C - B", 3 },
{ "sync", "sync_instr_cache", 0 },
{ "tdeq", "if (A == B) trap", 2 },
{ "tdeqi", "if (A == B) trap", 2 },
{ "tdgt", "if (A > B) trap", 2 },
{ "tdgti", "if (A > B) trap", 2 },
{ "tdlgt", "if (A > B) trap", 2 },
{ "tdlgti", "if (A > B) trap", 2 },
{ "tdllt", "if (A < B) trap", 2 },
{ "tdllti", "if (A < B) trap", 2 },
{ "tdlt", "if (A < B) trap", 2 },
{ "tdlti", "if (A < B) trap", 2 },
{ "tdne", "if (A != B) trap", 2 },
{ "tdnei", "if (A != B) trap", 2 },
{ "tlbia", "inval_all_tlb", 0 },
{ "tlbie", "inval_tbl(A, B)", 2 },
{ "tlbiel", "inval_tbl(A)", 1 },
{ "tlbivax", "inval_va(A, B)", 2 },
{ "tlbld", "tlb_data_load(A)", 1 },
{ "tlbli", "tlb_instr_load(A)", 1 },
{ "tlbre", "A = tlb_read_entry(B,C)", 3 },
{ "tlbrehi", "A = tlb_read_entry_hi(B)", 2 },
{ "tlbrelo", "A = tlb_read_entry_lo(B)", 2 },
{ "tlbsx", "A = tlb_search(B)", 2 },
{ "tlbsync", "sync_tlb", 3 },
{ "tlbwe", "tlb_write_entry(B,C) = A", 3 },
{ "tlbwehi", "tlb_write_entry_hi(B) = A", 2 },
{ "tlbwelo", "tlb_write_entry_lo(B) = A", 2 },
{ "trap", "trap", 3 },
{ "tweq", "if ((word) A == (word) B) trap", 2 },
{ "tweqi", "if ((word) A == (word) B) trap", 2 },
{ "twgt", "if ((word) A > (word) B) trap", 2 },
{ "twgti", "if ((word) A > (word) B) trap", 2 },
{ "twlgt", "if ((word) A > (word) B) trap", 2 },
{ "twlgti", "if ((word) A > (word) B) trap", 2 },
{ "twllt", "if ((word) A < (word) B) trap", 2 },
{ "twllti", "if ((word) A < (word) B) trap", 2 },
{ "twlt", "if ((word) A < (word) B) trap", 2 },
{ "twlti", "if ((word) A < (word) B) trap", 2 },
{ "twne", "if ((word) A != (word) B) trap", 2 },
{ "twnei", "if ((word) A != (word) B) trap", 2 },
{ "vaddcuw", "A = (unsigned vector) B + C", 3 },
{ "vaddfp", "A = (float vector) B + C", 3 },
{ "vaddsbs", "A = (byte vector) B + C", 3 },
{ "vaddshs", "A = (half vector) B + C", 3 },
{ "vaddsws", "A = (word vector) B + C", 3 },
/* too much complexity to represent
{ "vaddubm", "A = (byte vector) B + C + (modulo?)", 3},
{ "vaddubs", "A = (byte vector) B + C", 3},
{ "vaddudm", "A = (vector) B + C + (modulo?)", 3},
{ "vadduhm", "A = (half vector) B + C", 3},
{ "vadduhs", "A = (half vector) B + C", 3},
{ "vadduwm", "A = (word vector) B + C", 3},
{ "vadduws", "A = (word vector) B + C", 3},
*/
{ "vand", "A = B & C", 3 },
{ "vandc", "A = B & C", 3 },
{ "vavgsb", "A = (byte vector) avg(B, C)", 3 },
{ "vavgsh", "A = (half vector) avg(B, C)", 3 },
{ "vavgsw", "A = (word vector) avg(B, C)", 3 },
{ "vavgub", "A = (unsigned byte vector) avg(B, C)", 3 },
{ "vavguh", "A = (unsigned half vector) avg(B, C)", 3 },
{ "vavguw", "A = (unsigned word vector) avg(B, C)", 3 },
{ "vcfsx", "A = (float vector) B", 2 },
{ "vcfux", "A = (float vector) B", 2 },
{ "vclzb", "A = (byte vector) count_zeros(B)", 2 },
{ "vclzd", "A = (vector) count_zeros(B)", 2 },
{ "vclzh", "A = (half vector) count_zeros(B)", 2 },
{ "vclzw", "A = (word vector) count_zeros(B)", 2 },
{ "vcmpbfp", "A = !(B < C) | (B == C) | !(B > C)", 3 },
{ "vcmpeqfp", "A = (float) B == (float) C", 3 },
{ "vcmpequb", "A = (unsigned byte) B == (byte) C", 3 },
{ "vcmpequd", "A = (unsigned) B == (unsigned) C", 3 },
{ "vcmpequh", "A = (unsigned half) B == (unsigned half) C", 3 },
{ "vcmpequw", "A = (unsigned word) B == (unsigned word) C", 3 },
{ "vcmpgefp", "A = (float) B >= (float) C", 3 },
{ "vcmpgtsb", "A = (byte) B > (byte) C", 3 },
{ "vcmpgtsd", "A = B > C", 3 },
{ "vcmpgtsh", "A = (half) B > (half) C", 3 },
{ "vcmpgtsw", "A = (word) B > (word) C", 3 },
{ "vcmpgtub", "A = (unsigned byte) B > (byte) C", 3 },
{ "vcmpgtud", "A = (unsigned) B > (unsigned) C", 3 },
{ "vcmpgtuh", "A = (unsigned half) B > (unsigned half) C", 3 },
{ "vcmpgtuw", "A = (unsigned word) B > (unsigned word) C", 3 },
{ "vctsxs", "A = (word) B", 2 },
{ "vctuxs", "A = (unsigned word) B", 2 },
{ "veqv", "A = (vector) B ^ C", 3 },
{ "vexptefp", "A = (float vector) pow(2, B)", 2 },
{ "vlogefp", "A = (float vector) log2(B)", 2 },
{ "vmaddfp", "A = (float vector) (B * C) + round(D)", 4 },
{ "vmaxfp", "A = (float vector) max(B, C)", 3 },
{ "vmaxsb", "A = (byte vector) max(B, C)", 3 },
{ "vmaxsd", "A = (vector) max(B, C)", 3 },
{ "vmaxsh", "A = (half vector) max(B, C)", 3 },
{ "vmaxsw", "A = (word vector) max(B, C)", 3 },
{ "vmaxub", "A = (unsigned byte vector) max(B, C)", 3 },
{ "vmaxud", "A = (vector) max(B, C)", 3 },
{ "vmaxuh", "A = (unsigned half vector) max(B, C)", 3 },
{ "vmaxuw", "A = (unsigned word vector) max(B, C)", 3 },
// { "vmhaddshs", "A = (vector) B + C + D", 4},
// { "vmhraddshs", "A = (vector) B + C + D", 4},
{ "vminfp", "A = (float vector) min(B, C)", 3 },
{ "vminsb", "A = (byte vector) min(B, C)", 3 },
{ "vminsd", "A = (vector) min(B, C)", 3 },
{ "vminsh", "A = (half vector) min(B, C)", 3 },
{ "vminsw", "A = (word vector) min(B, C)", 3 },
{ "vminub", "A = (unsigned byte vector) min(B, C)", 3 },
{ "vminud", "A = (vector) min(B, C)", 3 },
{ "vminuh", "A = (unsigned half vector) min(B, C)", 3 },
{ "vminuw", "A = (unsigned word vector) min(B, C)", 3 },
// { "vmladduhm", "A = (unsigned half vector) B + C", 3},
{ "vmrghb", "A = (byte vector) merge_hi(B, C)", 3 },
{ "vmrghh", "A = (half vector) merge_hi(B, C)", 3 },
{ "vmrghw", "A = (word vector) merge_hi(B, C)", 3 },
{ "vmrglb", "A = (byte vector) merge_lo(B, C)", 3 },
{ "vmrglh", "A = (half vector) merge_lo(B, C)", 3 },
{ "vmrglw", "A = (word vector) merge_lo(B, C)", 3 },
{ "vmsummbm", "A = (byte vector) B + C", 3 },
{ "vmsumshm", "A = (half vector) B + C", 3 },
{ "vmsumshs", "A = (half vector) B + C", 3 },
{ "vmsumubm", "A = (unsigned byte vector) B + C", 3 },
{ "vmsumuhm", "A = (unsigned half vector) B + C", 3 },
{ "vmsumuhs", "A = (unsigned half vector) B + C", 3 },
{ "vmulesb", "A = (byte vector) B * C", 3 },
{ "vmulesh", "A = (half vector) B * C", 3 },
{ "vmulesw", "A = (word vector) B * C", 3 },
{ "vmuleub", "A = (unsigned byte vector) B * C", 3 },
{ "vmuleuh", "A = (unsigned half vector) B * C", 3 },
{ "vmuleuw", "A = (unsigned word vector) B * C", 3 },
{ "vmulosb", "A = (byte vector) B * C", 3 },
{ "vmulosh", "A = (byte vector) B * C", 3 },
{ "vmulosw", "A = (byte vector) B * C", 3 },
{ "vmuloub", "A = (byte vector) B * C", 3 },
{ "vmulouh", "A = (unsigned byte vector) B * C", 3 },
{ "vmulouw", "A = (unsigned byte vector) B * C", 3 },
{ "vmuluwm", "A = (unsigned word vector) B * C", 3 },
{ "vnand", "A = (vector) B & C", 3 },
{ "vnmsubfp", "A = (float vector) (B * C) - round(D)", 4 },
{ "vnor", "A = (vector) B | !C", 3 },
{ "vor", "A = (vector) B | C", 3 },
{ "vorc", "A = (vector) B | C", 3 },
// This should be represented as a for loop of bits comparing.. too much complex for pseudo
// { "vperm", "A = (vector) B + C", 3},
{ "vpkpx", "A = (vector) pack_pixel(B, C)", 3 },
{ "vpkshss", "A = (half vector) pack_pixel_saturate(B, C)", 3 },
{ "vpkshus", "A = (unsigned half vector) pack_pixel_saturate(B, C)", 3 },
{ "vpkswss", "A = (word vector) pack_pixel_saturate(B, C)", 3 },
{ "vpkswus", "A = (unsigned word vector) pack_pixel_saturate(B, C)", 3 },
// { "vpkuhum", "A = (vector) B + C", 3},
// { "vpkuhus", "A = (vector) B + C", 3},
// { "vpkuwum", "A = (vector) B + C", 3},
// { "vpkuwus", "A = (vector) B + C", 3},
{ "vpopcntb", "A = (vector) count_8bits(B)", 2 },
{ "vpopcntd", "A = (vector) count_64bits(B)", 2 },
{ "vpopcnth", "A = (vector) count_16bits(B)", 2 },
{ "vpopcntw", "A = (vector) count_32bits(B)", 2 },
{ "vrefp", "A = (float vector) 1/B", 2 },
{ "vrfim", "A = (vector) floor(B)", 2 },
{ "vrfin", "A = (vector) near(B)", 2 },
{ "vrfip", "A = (vector) ceil(B)", 2 },
{ "vrfiz", "A = (vector) trunc(B)", 2 },
{ "vrlb", "A = (vector) rotl_byte(B, C)", 3 },
{ "vrld", "A = (vector) rotl(B, C)", 3 },
{ "vrlh", "A = (vector) rotl_half(B, C)", 3 },
{ "vrlw", "A = (vector) rotl_word(B, C)", 3 },
{ "vrsqrtefp", "A = (vector) sqrt(B)", 2 },
{ "vsel", "A = (vector) if (D & 1) B else C", 4 },
{ "vsl", "A = (vector) B << C", 3 },
{ "vslb", "A = (byte vector) B << C", 3 },
{ "vsld", "A = (vector) B << C", 3 },
{ "vsldoi", "A = (vector) B << (octet) C", 3 },
{ "vslh", "A = (half vector) B << C", 3 },
{ "vslo", "A = (vector) B <<< (octet) C", 3 },
{ "vslw", "A = (word vector) B + C", 3 },
{ "vspltb", "A = (vector) splat_byte(B, C)", 3 },
{ "vsplth", "A = (vector) splat_half(B, C)", 3 },
{ "vspltisb", "A = (vector) sign_extend(B, 8)", 3 },
{ "vspltish", "A = (vector) sign_extend(B, 16)", 3 },
{ "vspltisw", "A = (vector) sign_extend(B, 32)", 3 },
{ "vspltw", "A = (vector) splat_word(B, C)", 3 },
{ "vsr", "A = (vector) B >> C", 3 },
{ "vsrab", "A = (byte vector) B >> C", 3 },
{ "vsrad", "A = (vector) B >> C", 3 },
{ "vsrah", "A = (half vector) B >> C", 3 },
{ "vsraw", "A = (word vector) B >> C", 3 },
{ "vsrb", "A = (byte vector) B >> C", 3 },
{ "vsrd", "A = (vector) B >> C", 3 },
{ "vsrh", "A = (half vector) B >> C", 3 },
{ "vsro", "A = (vector) B >> (octet) C", 3 },
{ "vsrw", "A = (word vector) B >> C", 3 },
{ "vsubcuw", "A = (unsigned word vector) (C - B) & 1", 3 },
{ "vsubfp", "A = (float vector) C - B", 3 },
{ "vsubsbs", "A = (byte vector) C - B", 3 },
{ "vsubshs", "A = (half vector) C - B", 3 },
{ "vsubsws", "A = (word vector) C - B", 3 },
{ "vsububm", "A = (byte vector) C - B", 3 },
{ "vsububs", "A = (byte vector) C - B", 3 },
{ "vsubudm", "A = (unsigned vector) C - B", 3 },
{ "vsubuhm", "A = (unsigned half vector) C - B", 3 },
{ "vsubuhs", "A = (unsigned half vector) C - B", 3 },
{ "vsubuwm", "A = (unsigned word vector) C - B", 3 },
{ "vsubuws", "A = (unsigned word vector) C - B", 3 },
{ "vsumbsws", "A = (word vector) B + C", 3 },
{ "vsumdsbs", "A = (byte vector) B + C", 3 },
{ "vsumdshs", "A = (half vector) B + C", 3 },
{ "vsumdubs", "A = (unsigned vector) B + C", 3 },
{ "vsumsws", "A = (word vector) B + C", 3 },
{ "vupkhpx", "A = (vector) unpack_hi_pixel(B)", 3 },
{ "vupkhsb", "A = (byte vector) unpack_hi_pixel(B)", 3 },
{ "vupkhsh", "A = (half vector) unpack_hi_pixel(B)", 3 },
{ "vupklpx", "A = (vector) unpack_lo_pixel(B)", 3 },
{ "vupklsb", "A = (byte vector) unpack_lo_pixel(B)", 3 },
{ "vupklsh", "A = (half vector) unpack_lo_pixel(B)", 3 },
{ "vxor", "A = (vector) B ^ C", 3 },
{ "wait", "wait_interrupt", 0 },
{ "waitimpl", "wait_interrupt_thread_reservation", 0 },
{ "waitrsv", "wait_interrupt_implemention", 0 },
{ "wrtee", "msr &= A", 1 },
{ "wrteei", "msr &= A", 1 },
{ "xnop", "", 0 },
{ "xor", "A = B ^ C", 3 },
{ "xori", "A = B ^ C", 3 },
{ "xoris", "A = B ^ (C << 16)", 3 },
{ "xsabsdp", "A = (double vector) abs(B)", 2 },
{ "xsadddp", "A = (double vector) B + C", 3 },
{ "xscmpodp", "A = (double vector) B == C", 3 },
{ "xscmpudp", "A = (double vector) B == C", 3 },
{ "xscpsgndp", "A = (double vector) copy_sign(B, C)", 3 },
{ "xscvdpsp", "A = (double vector) round(B)", 2 },
{ "xscvdpsxds", "A = (vector) ((double) B)", 2 },
{ "xscvdpsxws", "A = (word vector) ((double) B)", 2 },
{ "xscvdpuxds", "A = (unsigned vector) ((double) B)", 2 },
{ "xscvdpuxws", "A = (unsigned word vector) ((double) B)", 2 },
{ "xscvspdp", "A = (double vector) ((float) B)", 2 },
{ "xscvsxddp", "A = (double vector) B", 2 },
{ "xscvuxddp", "A = (double vector) ((unsigned) B)", 2 },
{ "xsdivdp", "A = (double vector) B / C", 3 },
// multiply add
// { "xsmaddadp", "A = (double vector) B * C + ?", 3},
// { "xsmaddmdp", "A = (double vector) B * C + ?", 3},
{ "xsmaxdp", "A = (double vector) max(B, C)", 3 },
{ "xsmindp", "A = (double vector) min(B, C)", 3 },
// multiply sub
// { "xsmsubadp", "A = (double vector) B * C - ?", 3},
// { "xsmsubmdp", "A = (double vector) B * C - ?", 3},
{ "xsmuldp", "A = (double vector) B * C", 3 },
{ "xsnabsdp", "A = (double vector) -abs(B)", 2 },
{ "xsnegdp", "A = (double vector) -B", 2 },
// negative multiply add
// { "xsnmaddadp", "A = (double vector) B * C + ?", 3},
// { "xsnmaddmdp", "A = (double vector) B + C + ?", 3},
// negative multiply sub
// { "xsnmsubadp", "A = (double vector) B + C - ?", 3},
// { "xsnmsubmdp", "A = (double vector) B + C - ?", 3},
{ "xsrdpi", "A = (double vector) round(B)", 2 },
{ "xsrdpic", "A = (double vector) round(B)", 2 },
{ "xsrdpim", "A = (double vector) floor(B)", 2 },
{ "xsrdpip", "A = (double vector) ceil(B)", 2 },
{ "xsrdpiz", "A = (double vector) trunc(B)", 2 },
{ "xsredp", "A = (double vector) 1/B", 2 },
{ "xsrsqrtedp", "A = (double vector) 1/sqrt(B)", 2 },
{ "xssqrtdp", "A = sqrt(B)", 2 },
{ "xssubdp", "A = C - B", 3 },
{ "xstdivdp", "A = test_sw_divide(B, C)", 3 },
{ "xstsqrtdp", "A = test_sw_sqrt(B)", 2 },
{ "xvabsdp", "A = (double vector) abs(B)", 2 },
{ "xvabssp", "A = (float vector) abs(B)", 2 },
{ "xvadddp", "A = (double vector) B + C", 3 },
{ "xvaddsp", "A = (float vector) B + C", 3 },
{ "xvcmpeqdp", "A = (double vector) B == (double vector) C", 3 },
{ "xvcmpeqsp", "A = (float vector) B == (float vector) C", 3 },
{ "xvcmpgedp", "A = (double vector) B >= (double vector) C", 3 },
{ "xvcmpgesp", "A = (float vector) B >= (float vector) C", 3 },
{ "xvcmpgtdp", "A = (double vector) B > (double vector) C", 3 },
{ "xvcmpgtsp", "A = (float vector) B > (float vector) C", 3 },
{ "xvcpsgndp", "A = (double vector) copy_sign(B, C)", 3 },
{ "xvcpsgnsp", "A = (float vector) copy_sign(B, C)", 3 },
{ "xvcvdpsp", "A = (float vector) ((double vector)B)", 2 },
{ "xvcvdpsxds", "A = (vector) B", 2 },
{ "xvcvdpsxws", "A = (word vector) B", 2 },
{ "xvcvdpuxds", "A = (unsigned vector) B", 2 },
{ "xvcvdpuxws", "A = (unsigned word vector) B", 2 },
{ "xvcvspdp", "(double vector) ((float vector) B)", 2 },
{ "xvcvspsxds", "A = (vector) ((float vector) B)", 2 },
{ "xvcvspsxws", "A = (word vector) ((float vector) B)", 2 },
{ "xvcvspuxds", "A = (unsigned vector) ((float vector) B)", 2 },
{ "xvcvspuxws", "A = (unsigned word vector) ((float vector) B)", 2 },
{ "xvcvsxddp", "A = (double vector) B", 2 },
{ "xvcvsxdsp", "A = (float vector) B", 2 },
{ "xvcvsxwdp", "A = (double vector) ((word) B)", 2 },
{ "xvcvsxwsp", "A = (float vector) ((word) B)", 2 },
{ "xvcvuxddp", "A = (double vector) (unsigned) B", 2 },
{ "xvcvuxdsp", "A = (float vector) (unsigned) B", 2 },
{ "xvcvuxwdp", "A = (double vector) ((unsigned word) B)", 2 },
{ "xvcvuxwsp", "A = (float vector) ((unsigned word) B)", 2 },
{ "xvdivdp", "A = (double vector) B / C", 3 },
{ "xvdivsp", "A = (float vector) B / C", 3 },
// Multiply add (double & float)
// { "xvmaddadp", "A = B + C", 3},
// { "xvmaddasp", "A = B + C", 3},
// { "xvmaddmdp", "A = B + C", 3},
// { "xvmaddmsp", "A = B + C", 3},
{ "xvmaxdp", "A = (double vector) max(B)", 2 },
{ "xvmaxsp", "A = (float vector) max(B)", 2 },
{ "xvmindp", "A = (double vector) min(B)", 2 },
{ "xvminsp", "A = (float vector) min(B)", 2 },
{ "xvmovdp", "A = (double vector) B", 2 },
{ "xvmovsp", "A = (float vector) B", 2 },
// Multiply sub (double & float)
// { "xvmsubadp", "A = B + C", 3},
// { "xvmsubasp", "A = B + C", 3},
// { "xvmsubmdp", "A = B + C", 3},
// { "xvmsubmsp", "A = B + C", 3},
{ "xvmuldp", "A = (double vector) B * C", 3 },
{ "xvmulsp", "A = (float vector) B * C", 3 },
{ "xvnabsdp", "A = (double vector) -abs(B)", 2 },
{ "xvnabssp", "A = (float vector) -abs(B)", 2 },
{ "xvnegdp", "A = (double vector) -B", 2 },
{ "xvnegsp", "A = (float vector) -B", 2 },
// Negate multiply add (double & float)
// { "xvnmaddadp", "A = B + C", 3},
// { "xvnmaddasp", "A = B + C", 3},
// { "xvnmaddmdp", "A = B + C", 3},
// { "xvnmaddmsp", "A = B + C", 3},
// Negate multiply sub (double & float)
// { "xvnmsubadp", "A = B + C", 3},
// { "xvnmsubasp", "A = B + C", 3},
// { "xvnmsubmdp", "A = B + C", 3},
// { "xvnmsubmsp", "A = B + C", 3},
{ "xvrdpi", "A = (double vector) round(B)", 2 },
{ "xvrdpic", "A = (double vector) round(B)", 2 },
{ "xvrdpim", "A = (double vector) floor(B)", 2 },
{ "xvrdpip", "A = (double vector) ceil(B)", 2 },
{ "xvrdpiz", "A = (double vector) trunc(B)", 2 },
{ "xvredp", "A = (double vector) 1/B", 2 },
{ "xvresp", "A = (float vector) B", 2 },
{ "xvrspi", "A = (float vector) round(B)", 2 },
{ "xvrspic", "A = (float vector) round(B)", 2 },
{ "xvrspim", "A = (float vector) floor(B)", 2 },
{ "xvrspip", "A = (float vector) ceil(B)", 2 },
{ "xvrspiz", "A = (float vector) trunc(B)", 2 },
{ "xvrsqrtedp", "A = (double vector) 1/sqrt(B)", 2 },
{ "xvrsqrtesp", "A = (float vector) 1/sqrt(B)", 2 },
{ "xvsqrtdp", "A = (double vector) sqrt(B)", 2 },
{ "xvsqrtsp", "A = (float vector) sqrt(B)", 2 },
{ "xvsubdp", "A = (double vector) C - B", 3 },
{ "xvsubsp", "A = (float vector) C - B", 3 },
{ "xvtdivdp", "A = (double vector) B / C", 3 },
{ "xvtdivsp", "A = (float vector) B / C", 3 },
{ "xvtsqrtdp", "A = (double vector) test_sw_sqrt(B)", 3 },
{ "xvtsqrtsp", "A = (float vector) test_sw_sqrt(B)", 3 },
{ "xxland", "A = B & C", 3 },
{ "xxlandc", "A = B & C", 3 },
{ "xxleqv", "A = B ^ C", 3 },
{ "xxlnand", "A = B & !C", 3 },
{ "xxlnor", "A = B + !C", 3 },
{ "xxlor", "A = B | C", 3 },
{ "xxlorc", "A = B | C", 3 },
{ "xxlxor", "A = B ^ C", 3 },
{ "xxmrghd", "A = hi(B) || hi(C)", 3 },
{ "xxmrghw", "A = (word vector) hi(B) || hi(C)", 3 },
{ "xxmrgld", "A = lo(B) || lo(C)", 3 },
{ "xxmrglw", "A = (word vector) lo(B) || lo(C)", 3 },
// Permute Doubleword Immediate
// { "xxpermdi", "A = B + C", 3},
// Select (aka concat)
// { "xxsel", "A = B + C + D", 4},
{ "xxsldwi", "A = B << C", 3 },
{ "xxspltd", "A = split(B)", 2 },
{ "xxspltw", "A = (word vector) split(B)", 2 },
{ "xxswapd", "swap(A,B)", 2 },
{ NULL }
};
char ppc_mask[32] = { 0 }; // enough to represent max val of 0xffffffffffffffff
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (can_replace(ops[i].str, j, ops[i].max_operands)) {
if (i >= 0 && i <= 26 && argv[ops[i].max_operands][0] == 0) {
char *tmp = (char *)argv[ops[i].max_operands];
argv[ops[i].max_operands] = argv[ops[i].max_operands - 1];
if (ops[i].max_operands == 3) {
argv[2] = argv[1];
}
tmp[0] = 'c';
tmp[1] = 'r';
tmp[2] = '0';
tmp[3] = '\0';
argv[1] = tmp;
}
int letter = ops[i].str[j] - '@';
const char *w = argv[letter];
// eprintf("%s:%d %s\n", ops[i].op, letter, w);
if (letter == 4 && !strncmp(argv[0], "rlwinm", 6)) {
// { "rlwinm", "A = rol32(B, C) & D", 5},
w = ppc_mask;
// MASK(MB+32, ME+32)
ut64 MB = PPC_UT64(argv[4]) + 32;
ut64 ME = PPC_UT64(argv[5]) + 32;
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, mask64(MB, ME));
} else if (letter == 4 && (!strncmp(argv[0], "rldcl", 5) || !strncmp(argv[0], "rldicl", 6))) {
// { "rld[i]cl", "A = rol64(B, C) & D", 4},
w = ppc_mask;
// MASK(MB, 63)
ut64 MB = PPC_UT64(argv[4]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, mask64(MB, 63));
} else if (letter == 4 && !strncmp(argv[0], "rldic", 5)) {
// { "rldic", "A = rol64(B, C) & D", 4},
w = ppc_mask;
// MASK(MB, 63 - SH)
ut64 MB = PPC_UT64(argv[4]);
ut64 ME = 63 - PPC_UT64(argv[3]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, mask64(MB, ME));
} else if (letter == 4 && (!strncmp(argv[0], "rldcr", 5) || !strncmp(argv[0], "rldicr", 6))) {
// { "rld[i]cr", "A = rol64(B, C) & D", 4},
w = ppc_mask;
// MASK(0, ME)
ut64 ME = PPC_UT64(argv[4]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, mask64(0, ME));
} else if (letter == 4 && !strncmp(argv[0], "rldimi", 6)) {
// { "rldimi", "A = (rol64(B, C) & D) | (A & E)", 5}, //32
// first mask (normal)
w = ppc_mask;
// MASK(MB, 63 - SH)
ut64 MB = PPC_UT64(argv[4]);
ut64 ME = 63 - PPC_UT64(argv[3]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, mask64(MB, ME));
} else if (letter == 5 && !strncmp(argv[0], "rldimi", 6)) {
// { "rldimi", "A = (rol64(B, C) & D) | (A & E)", 5}, //32
// second mask (inverted)
w = ppc_mask;
// MASK(MB, 63 - SH)
ut64 MB = PPC_UT64(argv[4]);
ut64 ME = 63 - PPC_UT64(argv[3]);
ut64 inverted = ~(mask64(MB, ME));
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT64x, inverted);
} else if (letter == 4 && !strncmp(argv[0], "rlwimi", 6)) {
// { "rlwimi", "A = (rol64(B, C) & D) | (A & E)", 5}, //32
// first mask (normal)
w = ppc_mask;
// MASK(MB, ME)
ut32 MB = PPC_UT32(argv[4]);
ut32 ME = PPC_UT32(argv[5]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT32x "", mask32(MB, ME));
} else if (letter == 5 && !strncmp(argv[0], "rlwimi", 6)) {
// { "rlwimi", "A = (rol32(B, C) & D) | (A & E)", 5}, //32
// second mask (inverted)
w = ppc_mask;
// MASK(MB, ME)
ut32 MB = PPC_UT32(argv[4]);
ut32 ME = PPC_UT32(argv[5]);
ut32 inverted = ~mask32(MB, ME);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT32x "", inverted);
} else if (letter == 4 && !strncmp(argv[0], "rlwnm", 5)) {
// { "rlwnm", "A = rol32(B, C) & D", 5}, //32
w = ppc_mask;
// MASK(MB, ME)
ut32 MB = PPC_UT32(argv[4]);
ut32 ME = PPC_UT32(argv[5]);
snprintf(ppc_mask, sizeof(ppc_mask), "0x%" PFMT32x "", mask32(MB, ME));
} else if (letter == 1 && i >= 36 && i <= 43) {
int to = atoi(w);
switch (to) {
case 4:
w = "==";
break;
case 1:
case 8:
w = ">";
break;
case 5:
case 12:
w = ">=";
break;
case 2:
case 16:
w = "<";
break;
case 6:
case 20:
w = "<=";
break;
case 24:
w = "!=";
break;
case 31:
// If no parameters t[dw][i] 32, 0, 0 just TRAP
w = "==";
break;
default:
w = "?";
break;
}
} else if ((i == 44 && letter == 2) || (i == 45 && letter == 1)) { // spr
k += getspr_pseudo(w, newstr + k);
}
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
}
return true;
}
}
/* TODO: this is slow */
if (newstr) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
}
return false;
}
#define WSZ 128
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
char w2[WSZ];
char w3[WSZ];
char w4[WSZ];
char w5[WSZ];
char str[1024] = { 0 };
char *buf, *ptr, *optr;
if (!strcmp(data, "jr ra")) {
rz_strbuf_set(sb, "return");
return true;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_replace_char(buf, '(', ',');
rz_str_replace_char(buf, ')', ' ');
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
// nothing to see here
}
strncpy(w0, buf, WSZ - 1);
strncpy(w1, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
// nothing to see here
}
strncpy(w1, optr, WSZ - 1);
strncpy(w2, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
// nothing to see here
}
strncpy(w2, optr, WSZ - 1);
strncpy(w3, ptr, WSZ - 1);
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
// nothing to see here
}
strncpy(w3, optr, WSZ - 1);
strncpy(w4, ptr, WSZ - 1);
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
// nothing to see here
}
strncpy(w4, optr, WSZ - 1);
strncpy(w5, ptr, WSZ - 1);
}
}
}
}
} else {
strncpy(w0, buf, WSZ - 1);
}
{
const char *wa[] = { w0, w1, w2, w3, w4, w5 };
int nw = 0;
for (i = 0; i < 4; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
replace(nw, wa, str);
{
char *p = rz_str_dup(str);
p = rz_str_replace(p, "+ -", "- ", 0);
p = rz_str_replace(p, " + ]", "] ", 0);
// p = rz_str_replace (p, "if (r0 == r0) trap", "trap ", 0);
#if EXPERIMENTAL_ZERO
p = rz_str_replace(p, "zero", "0", 0);
if (!memcmp(p, "0 = ", 4))
*p = 0; // nop
#endif
if (!strcmp(w1, w2)) {
char a[64], b[64];
#define REPLACE(x, y) \
do { \
int snprintf_len1_ = snprintf(a, 64, x, w1, w1); \
int snprintf_len2_ = snprintf(b, 64, y, w1); \
if (snprintf_len1_ < 64 && snprintf_len2_ < 64) { \
p = rz_str_replace(p, a, b, 0); \
} \
} while (0)
// TODO: optimize
REPLACE("%s = %s +", "%s +=");
REPLACE("%s = %s -", "%s -=");
REPLACE("%s = %s &", "%s &=");
REPLACE("%s = %s |", "%s |=");
REPLACE("%s = %s ^", "%s ^=");
REPLACE("%s = %s >>", "%s >>=");
REPLACE("%s = %s <<", "%s <<=");
}
p = rz_str_replace(p, ":", "0000", 0);
strcpy(str, p);
free(p);
}
}
}
free(buf);
rz_strbuf_set(sb, str);
return true;
}
RzParsePlugin rz_parse_plugin_ppc_cs_pseudo = {
.name = "ppc.pseudo",
.desc = "PowerPC pseudo syntax",
.parse = parse,
};