mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-06-22 14:29:30 +00:00
Update ppcdisasm.cpp
This commit is contained in:
parent
99559c1e0c
commit
82b4f5717e
|
@ -1,5 +1,6 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <functional> //Mandated by Visual Studio
|
||||
#include "ppcdisasm.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -19,10 +20,6 @@ std::string my_sprintf(const char* format, Args... args)
|
|||
return str;
|
||||
}
|
||||
|
||||
const char* arith_im_mnem[9] = {
|
||||
"mulli", "subfic", "", "", "", "addic", "addic.", "addi", "addis"
|
||||
};
|
||||
|
||||
const char* bx_mnem[4] = {
|
||||
"b", "bl", "ba", "bla"
|
||||
};
|
||||
|
@ -56,21 +53,31 @@ const char* opc_muldivs[16] = { /* multiply and division instructions */
|
|||
"", "", "divwu", "divw"
|
||||
};
|
||||
|
||||
const char* opc_int_ldst[16] = { /* integer load and store instructions */
|
||||
"lwz", "lwzu", "lbz", "lbzu", "stw", "stwu", "stb", "stbu", "lhz", "lhzu",
|
||||
"lha", "lhau", "sth", "sthu", "lmw", "stmw"
|
||||
};
|
||||
|
||||
|
||||
/** various formatting helpers. */
|
||||
void fmt_oneop(string& buf, const char* opc, int src)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d", opc, src);
|
||||
}
|
||||
|
||||
void fmt_twoop(string& buf, const char* opc, int dst, int src)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d, r%d", opc, dst, src);
|
||||
}
|
||||
|
||||
void fmt_twoop_simm(string& buf, const char* opc, int dst, int imm)
|
||||
void fmt_twoop_imm(string& buf, const char* opc, int dst, int imm)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d, %s0x%X", opc, dst, (imm < 0) ? "-" : "", abs(imm));
|
||||
buf = my_sprintf("%-8sr%d, 0x%04X", opc, dst, imm);
|
||||
}
|
||||
|
||||
void fmt_twoop_fromspr(string& buf, const char* opc, int dst, int src)
|
||||
{
|
||||
buf = my_sprintf("%-8sspr%d, r%d", opc, dst, src);
|
||||
}
|
||||
|
||||
void fmt_twoop_tospr(string& buf, const char* opc, int dst, int src)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d, spr%d", opc, dst, src);
|
||||
}
|
||||
|
||||
void fmt_threeop(string& buf, const char* opc, int dst, int src1, int src2)
|
||||
|
@ -78,15 +85,22 @@ void fmt_threeop(string& buf, const char* opc, int dst, int src1, int src2)
|
|||
buf = my_sprintf("%-8sr%d, r%d, r%d", opc, dst, src1, src2);
|
||||
}
|
||||
|
||||
void fmt_threeop_uimm(string& buf, const char* opc, int dst, int src1, int imm)
|
||||
void fmt_threeop_imm(string& buf, const char* opc, int dst, int src1, int imm)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d, r%d, 0x%04X", opc, dst, src1, imm);
|
||||
}
|
||||
|
||||
void fmt_threeop_simm(string& buf, const char* opc, int dst, int src1, int imm)
|
||||
void fmt_fourop(string& buf, const char* opc, int dst, int src1, int src2, int src3)
|
||||
{
|
||||
buf = my_sprintf("%-8sr%d, r%d, %s0x%X", opc, dst, src1,
|
||||
(imm < 0) ? "-" : "", abs(imm));
|
||||
buf = my_sprintf("%-8sr%d, r%d, r%d, r%d", opc, dst, src1, src2, src3);
|
||||
}
|
||||
|
||||
void fmt_rotateop(string& buf, const char* opc, int dst, int src1, int sh, int mb, int me, bool imm)
|
||||
{
|
||||
if (imm)
|
||||
buf = my_sprintf("%-8sr%d, r%d, sh%d, mb%d, me%d", opc, dst, src1, sh, mb, me);
|
||||
else
|
||||
buf = my_sprintf("%-8sr%d, r%d, r%d, mb%d, me%d", opc, dst, src1, sh, mb, me);
|
||||
}
|
||||
|
||||
void opc_illegal(PPCDisasmContext* ctx)
|
||||
|
@ -104,34 +118,163 @@ void opc_group4(PPCDisasmContext* ctx)
|
|||
printf("Altivec group 4 not supported yet\n");
|
||||
}
|
||||
|
||||
void opc_ar_im(PPCDisasmContext* ctx)
|
||||
void opc_rlwimi(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto sh = (ctx->instr_code >> 11) & 0x1F;
|
||||
auto mb = (ctx->instr_code >> 6) & 0x1F;
|
||||
auto me = (ctx->instr_code >> 1) & 0x1F;
|
||||
|
||||
if (ctx->instr_code & 1)
|
||||
fmt_rotateop(ctx->instr_str, "rlwimi.", rs, ra, sh, mb, me, true);
|
||||
else
|
||||
fmt_rotateop(ctx->instr_str, "rlwimi", rs, ra, sh, mb, me, true);
|
||||
}
|
||||
|
||||
void opc_rlwinm(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto sh = (ctx->instr_code >> 11) & 0x1F;
|
||||
auto mb = (ctx->instr_code >> 6) & 0x1F;
|
||||
auto me = (ctx->instr_code >> 1) & 0x1F;
|
||||
|
||||
if (ctx->instr_code & 1)
|
||||
fmt_rotateop(ctx->instr_str, "rlwinm.", rs, ra, sh, mb, me, true);
|
||||
else
|
||||
fmt_rotateop(ctx->instr_str, "rlwinm", rs, ra, sh, mb, me, true);
|
||||
}
|
||||
|
||||
void opc_rlwnm(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rb = (ctx->instr_code >> 11) & 0x1F;
|
||||
auto mb = (ctx->instr_code >> 6) & 0x1F;
|
||||
auto me = (ctx->instr_code >> 1) & 0x1F;
|
||||
|
||||
if (ctx->instr_code & 1)
|
||||
fmt_rotateop(ctx->instr_str, "rlwnm.", rs, ra, rb, mb, me, false);
|
||||
else
|
||||
fmt_rotateop(ctx->instr_str, "rlwnm", rs, ra, rb, mb, me, false);
|
||||
}
|
||||
|
||||
void opc_mulli(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
int32_t imm = SIGNEXT(ctx->instr_code & 0xFFFF, 15);
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if ((ctx->instr_code >> 26) == 0xE && !ra && ctx->simplified) {
|
||||
fmt_twoop_simm(ctx->instr_str, "li", rd, imm);
|
||||
}
|
||||
else {
|
||||
fmt_threeop_simm(ctx->instr_str, arith_im_mnem[(ctx->instr_code >> 26) - 7],
|
||||
rd, ra, imm);
|
||||
}
|
||||
fmt_threeop_imm(ctx->instr_str, "mulli", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_subfic(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "subfic", rd, ra, imm);
|
||||
}
|
||||
|
||||
void power_dozi(PPCDisasmContext* ctx)
|
||||
{
|
||||
//return "DEADBEEF";
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "dozi", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_cmpli(PPCDisasmContext* ctx)
|
||||
{
|
||||
//return "DEADBEEF";
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto crfd = (ctx->instr_code >> 23) & 0x07;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if (ctx->instr_code & 0x200000)
|
||||
opc_illegal(ctx);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "cmpli", crfd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_cmpi(PPCDisasmContext* ctx)
|
||||
{
|
||||
//return "DEADBEEF";
|
||||
auto crfd = (ctx->instr_code >> 23) & 0x07;
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if (ctx->instr_code & 0x200000)
|
||||
opc_illegal(ctx);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "cmpi", crfd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_addic(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "addic", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_addicdot(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "addic.", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_addi(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if (ra == 0 && ctx->simplified)
|
||||
fmt_twoop_imm(ctx->instr_str, "li", rd, imm);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "addi", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_addis(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if (ra == 0 && ctx->simplified)
|
||||
fmt_twoop_imm(ctx->instr_str, "lis", rd, imm);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "addis", rd, ra, imm);
|
||||
}
|
||||
|
||||
void opc_lwz(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto offset = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if (ra == 0)
|
||||
fmt_twoop_imm(ctx->instr_str, "lzw", rd, offset);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "lzw", rd, ra, offset);
|
||||
}
|
||||
|
||||
void opc_lwzu(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto offset = ctx->instr_code & 0xFFFF;
|
||||
|
||||
if ((ra == 0) || (ra == rd))
|
||||
opc_illegal(ctx);
|
||||
else
|
||||
fmt_threeop_imm(ctx->instr_str, "lzwu", rd, ra, offset);
|
||||
}
|
||||
|
||||
void generic_bcx(PPCDisasmContext* ctx, uint32_t bo, uint32_t bi, uint32_t dst)
|
||||
|
@ -139,10 +282,10 @@ void generic_bcx(PPCDisasmContext* ctx, uint32_t bo, uint32_t bi, uint32_t dst)
|
|||
char opcode[10] = "bc";
|
||||
|
||||
if (ctx->instr_code & 1) {
|
||||
strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */
|
||||
strcat_s(opcode, "l"); /* add suffix "l" if the LK bit is set */
|
||||
}
|
||||
if (ctx->instr_code & 2) {
|
||||
strcat(opcode, "a"); /* add suffix "a" if the AA bit is set */
|
||||
strcat_s(opcode, "a"); /* add suffix "a" if the AA bit is set */
|
||||
}
|
||||
ctx->instr_str = my_sprintf("%-8s%d, %d, 0x%08X", opcode, bo, bi, dst);
|
||||
}
|
||||
|
@ -171,37 +314,36 @@ void opc_bcx(PPCDisasmContext* ctx)
|
|||
}
|
||||
|
||||
if (!(bo & 4)) {
|
||||
strcat(opcode, "d");
|
||||
strcat(opcode, (bo & 2) ? "z" : "nz");
|
||||
strcat_s(opcode, "d");
|
||||
strcat_s(opcode, (bo & 2) ? "z" : "nz");
|
||||
if (!(bo & 0x10)) {
|
||||
strcat(opcode, (bo & 8) ? "t" : "f");
|
||||
strcat_s(opcode, (bo & 8) ? "t" : "f");
|
||||
if (cr) {
|
||||
strcat(operands, "4*cr0+");
|
||||
strcat_s(operands, "4*cr0+");
|
||||
operands[4] = cr + '0';
|
||||
}
|
||||
strcat(operands, br_cond[4 + (bi & 3)]);
|
||||
strcat(operands, ", ");
|
||||
strcat_s(operands, br_cond[4 + (bi & 3)]);
|
||||
}
|
||||
}
|
||||
else { /* CTR ignored */
|
||||
strcat(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]);
|
||||
strcat_s(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]);
|
||||
if (cr) {
|
||||
strcat(operands, "cr0, ");
|
||||
strcat_s(operands, "cr0");
|
||||
operands[2] = cr + '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->instr_code & 1) {
|
||||
strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */
|
||||
strcat_s(opcode, "l"); /* add suffix "l" if the LK bit is set */
|
||||
}
|
||||
if (ctx->instr_code & 2) {
|
||||
strcat(opcode, "a"); /* add suffix "a" if the AA bit is set */
|
||||
strcat_s(opcode, "a"); /* add suffix "a" if the AA bit is set */
|
||||
}
|
||||
if (bo & 1) { /* incorporate prediction bit if set */
|
||||
strcat(opcode, (ctx->instr_code & 0x8000) ? "-" : "+");
|
||||
strcat_s(opcode, (ctx->instr_code & 0x8000) ? "-" : "+");
|
||||
}
|
||||
|
||||
ctx->instr_str = my_sprintf("%-8s%s0x%08X", opcode, operands, dst);
|
||||
ctx->instr_str = my_sprintf("%-8s%s, 0x%08X", opcode, operands, dst);
|
||||
}
|
||||
|
||||
void opc_bx(PPCDisasmContext* ctx)
|
||||
|
@ -212,6 +354,24 @@ void opc_bx(PPCDisasmContext* ctx)
|
|||
ctx->instr_str = my_sprintf("%-8s0x%08X", bx_mnem[ctx->instr_code & 3], dst);
|
||||
}
|
||||
|
||||
void opc_andidot(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "andi.", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_andisdot(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "andi.", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_ori(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
|
@ -226,7 +386,42 @@ void opc_ori(PPCDisasmContext* ctx)
|
|||
fmt_twoop(ctx->instr_str, "mr", ra, rs);
|
||||
return;
|
||||
}
|
||||
fmt_threeop_uimm(ctx->instr_str, "ori", ra, rs, imm);
|
||||
fmt_threeop_imm(ctx->instr_str, "ori", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_oris(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "oris", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_xori(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "xori", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_xoris(PPCDisasmContext* ctx)
|
||||
{
|
||||
auto ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
auto rs = (ctx->instr_code >> 21) & 0x1F;
|
||||
auto imm = ctx->instr_code & 0xFFFF;
|
||||
|
||||
fmt_threeop_imm(ctx->instr_str, "xoris", ra, rs, imm);
|
||||
}
|
||||
|
||||
void opc_group19(PPCDisasmContext* ctx)
|
||||
{
|
||||
int ext_opc = (ctx->instr_code >> 1) & 0x3FF; /* extract extended opcode */
|
||||
|
||||
if (ext_opc == 50)
|
||||
ctx->instr_str = my_sprintf("%-8s, "rfi");
|
||||
}
|
||||
|
||||
void opc_group31(PPCDisasmContext* ctx)
|
||||
|
@ -248,11 +443,11 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
opc_illegal(ctx);
|
||||
}
|
||||
else {
|
||||
strcpy(opcode, opc_subs[index]);
|
||||
strcpy_s(opcode, opc_subs[index]);
|
||||
if (ext_opc & 0x200) /* check OE bit */
|
||||
strcat(opcode, "o");
|
||||
strcat_s(opcode, "o");
|
||||
if (rc_set)
|
||||
strcat(opcode, ".");
|
||||
strcat_s(opcode, ".");
|
||||
if (index == 3 || index == 6 || index == 7 || index == 11 ||
|
||||
index == 15) { /* ugly check for two-operands instructions */
|
||||
if (rb != 0)
|
||||
|
@ -271,11 +466,11 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
opc_illegal(ctx);
|
||||
}
|
||||
else {
|
||||
strcpy(opcode, opc_adds[index]);
|
||||
strcpy_s(opcode, opc_adds[index]);
|
||||
if (ext_opc & 0x200) /* check OE bit */
|
||||
strcat(opcode, "o");
|
||||
strcat_s(opcode, "o");
|
||||
if (rc_set)
|
||||
strcat(opcode, ".");
|
||||
strcat_s(opcode, ".");
|
||||
if (index == 6 || index == 7) {
|
||||
if (rb != 0)
|
||||
opc_illegal(ctx);
|
||||
|
@ -293,11 +488,11 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
opc_illegal(ctx);
|
||||
}
|
||||
else {
|
||||
strcpy(opcode, opc_muldivs[index]);
|
||||
strcpy_s(opcode, opc_muldivs[index]);
|
||||
if (ext_opc & 0x200) /* check OE bit */
|
||||
strcat(opcode, "o");
|
||||
strcat_s(opcode, "o");
|
||||
if (rc_set)
|
||||
strcat(opcode, ".");
|
||||
strcat_s(opcode, ".");
|
||||
if ((!index || index == 2) && (ext_opc & 0x200))
|
||||
opc_illegal(ctx);
|
||||
else
|
||||
|
@ -310,13 +505,13 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
fmt_twoop(ctx->instr_str, rc_set ? "mr." : "mr", ra, rs);
|
||||
}
|
||||
else {
|
||||
strcpy(opcode, opc_logic[index]);
|
||||
strcpy_s(opcode, opc_logic[index]);
|
||||
if (!strlen(opcode)) {
|
||||
opc_illegal(ctx);
|
||||
}
|
||||
else {
|
||||
if (rc_set)
|
||||
strcat(opcode, ".");
|
||||
strcat_s(opcode, ".");
|
||||
fmt_threeop(ctx->instr_str, opcode, ra, rs, rb);
|
||||
}
|
||||
}
|
||||
|
@ -336,6 +531,8 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
break;
|
||||
}
|
||||
|
||||
auto ref_spr = (((ctx->instr_code >> 11) & 31) << 5) | ((ctx->instr_code >> 16) & 31);
|
||||
|
||||
switch (ext_opc) {
|
||||
case 4:
|
||||
if (rc_set)
|
||||
|
@ -343,6 +540,9 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
else
|
||||
ctx->instr_str = my_sprintf("%-8s%d, r%d, r%d", "tw", rs, ra, rb);
|
||||
break;
|
||||
case 19: /* mfcr */
|
||||
fmt_oneop(ctx->instr_str, "mfcr", rs);
|
||||
break;
|
||||
case 144: /* mtcrf */
|
||||
if (ctx->instr_code & 0x100801)
|
||||
opc_illegal(ctx);
|
||||
|
@ -351,50 +551,34 @@ void opc_group31(PPCDisasmContext* ctx)
|
|||
(ctx->instr_code >> 12) & 0xFF, rs);
|
||||
}
|
||||
break;
|
||||
case 146: /* mtmsr */
|
||||
fmt_oneop(ctx->instr_str, "mtmsr", rs);
|
||||
break;
|
||||
case 339: /* mfspr */
|
||||
fmt_twoop_fromspr(ctx->instr_str, "mfspr", rs, ref_spr);
|
||||
break;
|
||||
case 467: /* mtspr */
|
||||
fmt_twoop_tospr(ctx->instr_str, "mtspr", ref_spr, rs);
|
||||
break;
|
||||
default:
|
||||
opc_illegal(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void opc_intldst(PPCDisasmContext* ctx)
|
||||
{
|
||||
int32_t opcode = (ctx->instr_code >> 26) - 32;
|
||||
int32_t ra = (ctx->instr_code >> 16) & 0x1F;
|
||||
int32_t rd = (ctx->instr_code >> 21) & 0x1F;
|
||||
int32_t imm = SIGNEXT(ctx->instr_code & 0xFFFF, 15);
|
||||
|
||||
/* ra = 0 is forbidden for loads and stores with update */
|
||||
/* ra = rd is forbidden for loads with update */
|
||||
if (((opcode < 14) && (opcode & 5) == 1 && ra == rd) || ((opcode & 1) && !ra))
|
||||
{
|
||||
opc_illegal(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ra) {
|
||||
ctx->instr_str = my_sprintf("%-8sr%d, %s0x%X(r%d)", opc_int_ldst[opcode],
|
||||
rd, ((imm < 0) ? "-" : ""), abs(imm), ra);
|
||||
}
|
||||
else {
|
||||
ctx->instr_str = my_sprintf("%-8sr%d, %s0x%X", opc_int_ldst[opcode],
|
||||
rd, ((imm < 0) ? "-" : ""), abs(imm));
|
||||
}
|
||||
}
|
||||
|
||||
/** main dispatch table. */
|
||||
static std::function<void(PPCDisasmContext*)> OpcodeDispatchTable[64] = {
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_twi,
|
||||
opc_group4, opc_illegal, opc_illegal, opc_ar_im,
|
||||
opc_ar_im, power_dozi, opc_cmpli, opc_cmpi,
|
||||
opc_ar_im, opc_ar_im, opc_ar_im, opc_ar_im,
|
||||
opc_bcx, opc_illegal, opc_bx, opc_illegal,
|
||||
opc_group4, opc_illegal, opc_illegal, opc_mulli,
|
||||
opc_subfic, power_dozi, opc_cmpli, opc_cmpi,
|
||||
opc_addic, opc_addicdot, opc_addi, opc_addis,
|
||||
opc_bcx, opc_illegal, opc_bx, opc_group19,
|
||||
opc_rlwimi, opc_rlwinm, opc_illegal, opc_rlwnm,
|
||||
opc_ori, opc_oris, opc_xori, opc_xoris,
|
||||
opc_andidot, opc_andisdot, opc_illegal, opc_group31,
|
||||
opc_lwz, opc_lwzu, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_ori, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_group31,
|
||||
opc_intldst, opc_intldst, opc_intldst, opc_intldst,
|
||||
opc_intldst, opc_intldst, opc_intldst, opc_intldst,
|
||||
opc_intldst, opc_intldst, opc_intldst, opc_intldst,
|
||||
opc_intldst, opc_intldst, opc_intldst, opc_intldst,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
opc_illegal, opc_illegal, opc_illegal, opc_illegal,
|
||||
|
|
Loading…
Reference in New Issue
Block a user