mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-26 08:51:05 -04:00
refactor: added more instructions decoder
This commit is contained in:
@@ -47,6 +47,8 @@ namespace ps2recomp
|
||||
std::string translatePEXCH(const Instruction &inst);
|
||||
std::string translatePCPYH(const Instruction &inst);
|
||||
std::string translatePEXCW(const Instruction &inst);
|
||||
std::string translatePMTHI(const Instruction &inst);
|
||||
std::string translatePMTLO(const Instruction &inst);
|
||||
|
||||
// SPECIAL instructions
|
||||
std::string translateSYNC(const Instruction &inst);
|
||||
|
||||
@@ -280,6 +280,8 @@ namespace ps2recomp
|
||||
MMI3_PEXCH = 0x1A,
|
||||
MMI3_PCPYH = 0x1B,
|
||||
MMI3_PEXCW = 0x1E,
|
||||
MMI3_PMTHI = 0x08, // Move To HI register
|
||||
MMI3_PMTLO = 0x09 // Move To LO register
|
||||
};
|
||||
|
||||
// COP0 (rs field)
|
||||
|
||||
@@ -23,17 +23,42 @@ namespace ps2recomp
|
||||
uint32_t immediate; // Immediate value for I-type instructions
|
||||
uint32_t target; // Jump target for J-type instructions
|
||||
uint32_t raw; // Raw instruction value
|
||||
bool isMMI; // Is MMI instruction (PS2 specific)
|
||||
bool isVU; // Is VU instruction (PS2 specific)
|
||||
bool isBranch; // Is branch instruction
|
||||
bool isJump; // Is jump instruction
|
||||
bool isCall; // Is function call
|
||||
bool isReturn; // Is return instruction
|
||||
bool hasDelaySlot; // Has delay slot
|
||||
bool isMultimedia; // PS2-specific multimedia operations
|
||||
bool isStore;
|
||||
bool isLoad;
|
||||
uint8_t pmfhlVariation;
|
||||
|
||||
// Instruction type flags
|
||||
bool isMMI; // Is MMI instruction (PS2 specific)
|
||||
bool isVU; // Is VU instruction (PS2 specific)
|
||||
bool isBranch; // Is branch instruction
|
||||
bool isJump; // Is jump instruction
|
||||
bool isCall; // Is function call
|
||||
bool isReturn; // Is return instruction
|
||||
bool hasDelaySlot; // Has delay slot
|
||||
bool isMultimedia; // PS2-specific multimedia operations
|
||||
bool isStore; // Is store instruction
|
||||
bool isLoad; // Is load instruction
|
||||
|
||||
// Additional PS2-specific fields
|
||||
uint8_t mmiType; // 0=MMI0, 1=MMI1, 2=MMI2, 3=MMI3
|
||||
uint8_t mmiFunction; // Function within MMI type
|
||||
uint8_t pmfhlVariation; // For PMFHL instructions
|
||||
uint8_t vuFunction; // For VU instructions
|
||||
|
||||
struct
|
||||
{
|
||||
bool isVector; // Uses vector operations
|
||||
bool usesQReg; // Uses Q register
|
||||
bool usesPReg; // Uses P register
|
||||
bool modifiesMAC; // Modifies MAC flags
|
||||
uint8_t vectorField; // xyzw field mask
|
||||
} vectorInfo;
|
||||
|
||||
struct
|
||||
{
|
||||
bool modifiesGPR; // Modifies general purpose register
|
||||
bool modifiesFPR; // Modifies floating point register
|
||||
bool modifiesVFR; // Modifies vector float register
|
||||
bool modifiesMemory; // Modifies memory
|
||||
bool modifiesControl; // Modifies control register
|
||||
} modificationInfo;
|
||||
};
|
||||
|
||||
// Function information
|
||||
|
||||
@@ -465,6 +465,11 @@ namespace ps2recomp
|
||||
{
|
||||
return "// NOP (addiu $zero, ...)";
|
||||
}
|
||||
if (inst.modificationInfo.modifiesGPR)
|
||||
{
|
||||
return fmt::format("ctx->r[{}] = ADD32(ctx->r[{}], 0x{:X}); // Modifies GPR",
|
||||
inst.rt, inst.rs, (int16_t)inst.immediate);
|
||||
}
|
||||
return fmt::format("ctx->r[{}] = ADD32(ctx->r[{}], 0x{:X});",
|
||||
inst.rt, inst.rs, (int16_t)inst.immediate);
|
||||
|
||||
@@ -526,10 +531,20 @@ namespace ps2recomp
|
||||
|
||||
// PS2-specific 128-bit load/store
|
||||
case OPCODE_LQ:
|
||||
if (inst.vectorInfo.isVector)
|
||||
{
|
||||
return fmt::format("ctx->r[{}] = (__m128i)READ128(ADD32(ctx->r[{}], 0x{:X})); // Vector load",
|
||||
inst.rt, inst.rs, (int16_t)inst.immediate);
|
||||
}
|
||||
return fmt::format("ctx->r[{}] = (__m128i)READ128(ADD32(ctx->r[{}], 0x{:X}));",
|
||||
inst.rt, inst.rs, (int16_t)inst.immediate);
|
||||
|
||||
case OPCODE_SQ:
|
||||
if (inst.vectorInfo.isVector)
|
||||
{
|
||||
return fmt::format("WRITE128(ADD32(ctx->r[{}], 0x{:X}), (__m128i)ctx->r[{}]); // Vector store",
|
||||
inst.rs, (int16_t)inst.immediate, inst.rt);
|
||||
}
|
||||
return fmt::format("WRITE128(ADD32(ctx->r[{}], 0x{:X}), (__m128i)ctx->r[{}]);",
|
||||
inst.rs, (int16_t)inst.immediate, inst.rt);
|
||||
|
||||
@@ -553,6 +568,14 @@ namespace ps2recomp
|
||||
return fmt::format("WRITE128(ADD32(ctx->r[{}], 0x{:X}), (__m128i)ctx->vu0_vf[{}]);",
|
||||
inst.rs, (int16_t)inst.immediate, inst.rt);
|
||||
|
||||
case OPCODE_J:
|
||||
return fmt::format("// J 0x{:X} - Handled by branch logic",
|
||||
(inst.address & 0xF0000000) | (inst.target << 2));
|
||||
|
||||
case OPCODE_JAL:
|
||||
return fmt::format("// JAL 0x{:X} - Handled by branch logic",
|
||||
(inst.address & 0xF0000000) | (inst.target << 2));
|
||||
|
||||
case OPCODE_LWC1:
|
||||
return fmt::format("{{ uint32_t val = READ32(ADD32(ctx->r[{}], 0x{:X})); ctx->f[{}] = *(float*)&val; }}",
|
||||
inst.rs, (int16_t)inst.immediate, inst.rt);
|
||||
@@ -579,20 +602,17 @@ namespace ps2recomp
|
||||
switch (inst.rt)
|
||||
{
|
||||
case REGIMM_BLTZ:
|
||||
return fmt::format("// BLTZ r{}, 0x{:X} - Handled by branch logic",
|
||||
inst.rs, inst.address + 4 + ((int16_t)inst.immediate << 2));
|
||||
|
||||
case REGIMM_BGEZ:
|
||||
return fmt::format("// BGEZ r{}, 0x{:X} - Handled by branch logic",
|
||||
inst.rs, inst.address + 4 + ((int16_t)inst.immediate << 2));
|
||||
|
||||
case REGIMM_BLTZL:
|
||||
case REGIMM_BGEZL:
|
||||
case REGIMM_BLTZAL:
|
||||
return fmt::format("// BLTZAL r{}, 0x{:X} - Handled by branch logic",
|
||||
inst.rs, inst.address + 4 + ((int16_t)inst.immediate << 2));
|
||||
|
||||
case REGIMM_BGEZAL:
|
||||
return fmt::format("// BGEZAL r{}, 0x{:X} - Handled by branch logic",
|
||||
inst.rs, inst.address + 4 + ((int16_t)inst.immediate << 2));
|
||||
case REGIMM_BLTZALL:
|
||||
case REGIMM_BGEZALL:
|
||||
{
|
||||
uint32_t target = inst.address + 4 + ((int16_t)inst.immediate << 2);
|
||||
return fmt::format("// REGIMM branch instruction to 0x{:X} - Handled by branch logic", target);
|
||||
}
|
||||
|
||||
case REGIMM_MTSAB:
|
||||
return fmt::format("ctx->sa = (ctx->r[{}] + 0x{:X}) & 0x0F;",
|
||||
@@ -631,6 +651,10 @@ namespace ps2recomp
|
||||
}
|
||||
|
||||
// MIPS-IV special format opcodes
|
||||
case OPCODE_BEQ:
|
||||
case OPCODE_BNE:
|
||||
case OPCODE_BLEZ:
|
||||
case OPCODE_BGTZ:
|
||||
case OPCODE_BEQL:
|
||||
case OPCODE_BNEL:
|
||||
case OPCODE_BLEZL:
|
||||
@@ -1128,6 +1152,15 @@ namespace ps2recomp
|
||||
switch (inst.sa)
|
||||
{
|
||||
case MMI0_PADDW:
|
||||
if (inst.vectorInfo.isVector && inst.vectorInfo.vectorField != 0xF)
|
||||
{
|
||||
return fmt::format("{{ __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->r[{}] = _mm_blendv_epi8(ctx->r[{}], PS2_PADDW(ctx->r[{}], ctx->r[{}]), mask); }}",
|
||||
(inst.vectorInfo.vectorField & 0x8) ? 0xFFFFFFFF : 0,
|
||||
(inst.vectorInfo.vectorField & 0x4) ? 0xFFFFFFFF : 0,
|
||||
(inst.vectorInfo.vectorField & 0x2) ? 0xFFFFFFFF : 0,
|
||||
(inst.vectorInfo.vectorField & 0x1) ? 0xFFFFFFFF : 0,
|
||||
inst.rd, inst.rd, inst.rs, inst.rt);
|
||||
}
|
||||
return fmt::format("ctx->r[{}] = PS2_PADDW(ctx->r[{}], ctx->r[{}]);",
|
||||
inst.rd, inst.rs, inst.rt);
|
||||
|
||||
@@ -1192,7 +1225,8 @@ namespace ps2recomp
|
||||
inst.rd, inst.rs, inst.rt);
|
||||
|
||||
case MMI0_PPACB:
|
||||
return fmt::format("// PS2_PPACB not implemented");
|
||||
return fmt::format("ctx->r[{}] = PS2_PPACB(ctx->r[{}], ctx->r[{}]);",
|
||||
inst.rd, inst.rs, inst.rt);
|
||||
|
||||
default:
|
||||
return fmt::format("// Unhandled MMI0 function: 0x{:X}", inst.sa);
|
||||
@@ -1316,6 +1350,36 @@ namespace ps2recomp
|
||||
case MMI2_PHMADH:
|
||||
return translatePHMADH(inst);
|
||||
|
||||
case MMI2_PMSUBH:
|
||||
return fmt::format("{{ __m128i product = _mm_mullo_epi16(ctx->r[{}], ctx->r[{}]); "
|
||||
"// Convert products to 32-bit\n"
|
||||
"__m128i prod_lo = _mm_unpacklo_epi16(product, _mm_srai_epi16(product, 15));\n"
|
||||
"__m128i prod_hi = _mm_unpackhi_epi16(product, _mm_srai_epi16(product, 15));\n"
|
||||
"// Subtract from accumulator\n"
|
||||
"__m128i acc = _mm_set_epi32(0, ctx->hi, 0, ctx->lo);\n"
|
||||
"__m128i result = _mm_sub_epi32(acc, _mm_add_epi32(prod_lo, prod_hi));\n"
|
||||
"ctx->r[{}] = result;\n"
|
||||
"ctx->lo = _mm_extract_epi32(result, 0);\n"
|
||||
"ctx->hi = _mm_extract_epi32(result, 1); }}",
|
||||
inst.rs, inst.rt, inst.rd);
|
||||
|
||||
case MMI2_PHMSBH:
|
||||
return fmt::format("{{ // Multiply horizontally adjacent halfwords\n"
|
||||
"__m128i rtEven = _mm_shuffle_epi32(ctx->r[{}], _MM_SHUFFLE(2, 0, 2, 0));\n"
|
||||
"__m128i rtOdd = _mm_shuffle_epi32(ctx->r[{}], _MM_SHUFFLE(3, 1, 3, 1));\n"
|
||||
"__m128i rsEven = _mm_shuffle_epi32(ctx->r[{}], _MM_SHUFFLE(2, 0, 2, 0));\n"
|
||||
"__m128i rsOdd = _mm_shuffle_epi32(ctx->r[{}], _MM_SHUFFLE(3, 1, 3, 1));\n"
|
||||
"__m128i prod1 = _mm_mullo_epi16(rtEven, rsEven);\n"
|
||||
"__m128i prod2 = _mm_mullo_epi16(rtOdd, rsOdd);\n"
|
||||
"__m128i sum = _mm_add_epi16(prod1, prod2);\n"
|
||||
"// Convert to 32-bit and subtract from accumulator\n"
|
||||
"__m128i acc = _mm_set_epi32(0, ctx->hi, 0, ctx->lo);\n"
|
||||
"__m128i result = _mm_sub_epi32(acc, _mm_unpacklo_epi16(sum, _mm_srai_epi16(sum, 15)));\n"
|
||||
"ctx->r[{}] = result;\n"
|
||||
"ctx->lo = _mm_extract_epi32(result, 0);\n"
|
||||
"ctx->hi = _mm_extract_epi32(result, 1); }}",
|
||||
inst.rt, inst.rt, inst.rs, inst.rs, inst.rd);
|
||||
|
||||
case MMI2_PEXEH:
|
||||
return translatePEXEH(inst);
|
||||
|
||||
@@ -1352,7 +1416,11 @@ namespace ps2recomp
|
||||
inst.rd, inst.rs, inst.rt);
|
||||
|
||||
case MMI3_PMADDUW:
|
||||
return fmt::format("// PS2_PMADDUW - Packed Multiply-Add Unsigned Word");
|
||||
return fmt::format("{{ uint64_t result = (uint64_t)(((uint64_t)ctx->hi << 32) | ctx->lo) + "
|
||||
"(uint64_t)_mm_extract_epi32(ctx->r[{}], 0) * (uint64_t)_mm_extract_epi32(ctx->r[{}], 0); "
|
||||
"ctx->lo = (uint32_t)result; ctx->hi = (uint32_t)(result >> 32); "
|
||||
"ctx->r[{}] = _mm_set_epi32(0, 0, ctx->hi, ctx->lo); }}",
|
||||
inst.rs, inst.rt, inst.rd);
|
||||
|
||||
case MMI3_PSRAVW:
|
||||
return fmt::format("ctx->r[{}] = PS2_PSRAVW(ctx->r[{}], ctx->r[{}]);",
|
||||
@@ -1380,6 +1448,12 @@ namespace ps2recomp
|
||||
case MMI3_PEXCW:
|
||||
return translatePEXCW(inst);
|
||||
|
||||
case MMI3_PMTHI:
|
||||
return translatePMTHI(inst);
|
||||
|
||||
case MMI3_PMTLO:
|
||||
return translatePMTLO(inst);
|
||||
|
||||
default:
|
||||
return fmt::format("// Unhandled MMI3 function: 0x{:X}", inst.sa);
|
||||
}
|
||||
@@ -2258,6 +2332,16 @@ namespace ps2recomp
|
||||
inst.rs, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translatePMTHI(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->hi = _mm_extract_epi32(ctx->r[{}], 0);", inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translatePMTLO(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->lo = _mm_extract_epi32(ctx->r[{}], 0);", inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::generateJumpTableSwitch(const Instruction &inst, uint32_t tableAddress,
|
||||
const std::vector<JumpTableEntry> &entries)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,26 @@ namespace ps2recomp
|
||||
inst.isReturn = false;
|
||||
inst.hasDelaySlot = false;
|
||||
inst.isMultimedia = false;
|
||||
inst.isLoad = false;
|
||||
inst.isStore = false;
|
||||
|
||||
// Initialize the enhanced fields
|
||||
inst.mmiType = 0;
|
||||
inst.mmiFunction = 0;
|
||||
inst.pmfhlVariation = 0;
|
||||
inst.vuFunction = 0;
|
||||
|
||||
inst.vectorInfo.isVector = false;
|
||||
inst.vectorInfo.usesQReg = false;
|
||||
inst.vectorInfo.usesPReg = false;
|
||||
inst.vectorInfo.modifiesMAC = false;
|
||||
inst.vectorInfo.vectorField = 0xF; // All fields (xyzw)
|
||||
|
||||
inst.modificationInfo.modifiesGPR = false;
|
||||
inst.modificationInfo.modifiesFPR = false;
|
||||
inst.modificationInfo.modifiesVFR = false;
|
||||
inst.modificationInfo.modifiesMemory = false;
|
||||
inst.modificationInfo.modifiesControl = false;
|
||||
|
||||
switch (inst.opcode)
|
||||
{
|
||||
@@ -86,18 +106,21 @@ namespace ps2recomp
|
||||
decodeMMI(inst);
|
||||
inst.isMMI = true;
|
||||
inst.isMultimedia = true;
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LQ:
|
||||
decodeIType(inst);
|
||||
inst.isLoad = true;
|
||||
inst.isMultimedia = true; // 128-bit load
|
||||
inst.modificationInfo.modifiesGPR = true;
|
||||
break;
|
||||
|
||||
case OPCODE_SQ:
|
||||
decodeIType(inst);
|
||||
inst.isStore = true;
|
||||
inst.isMultimedia = true; // 128-bit store
|
||||
inst.modificationInfo.modifiesMemory = true;
|
||||
break;
|
||||
|
||||
case OPCODE_LB:
|
||||
@@ -462,71 +485,341 @@ namespace ps2recomp
|
||||
|
||||
void R5900Decoder::decodeCOP2(Instruction &inst) const
|
||||
{
|
||||
// COP2 (VU0 macro mode) instructions
|
||||
inst.isVU = true;
|
||||
inst.isMultimedia = true;
|
||||
|
||||
uint32_t rs = inst.rs; // The VU0 format field
|
||||
uint32_t rs = inst.rs; // The format field
|
||||
|
||||
if (rs == COP2_MFC2)
|
||||
switch (rs)
|
||||
{
|
||||
// Move From COP2 register
|
||||
case COP2_QMFC2: // Move From COP2 (128-bit)
|
||||
case COP2_CFC2: // Move Control From COP2
|
||||
case COP2_QMTC2: // Move To COP2 (128-bit)
|
||||
case COP2_CTC2: // Move Control To COP2
|
||||
// Register transfer operations
|
||||
break;
|
||||
|
||||
case COP2_BC2: // Branch on COP2 condition
|
||||
{
|
||||
uint32_t rt = inst.rt; // The condition code
|
||||
|
||||
if (rt == COP2_BCF || rt == COP2_BCT ||
|
||||
rt == COP2_BCFL || rt == COP2_BCTL ||
|
||||
rt == COP2_BCEF || rt == COP2_BCET ||
|
||||
rt == COP2_BCEFL || rt == COP2_BCETL)
|
||||
{
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
}
|
||||
else if (rs == COP2_CFC2)
|
||||
break;
|
||||
|
||||
case COP2_CO: // VU0 vector operations
|
||||
{
|
||||
// Move From COP2 Control register
|
||||
uint32_t function = inst.function;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case VU0_VADD:
|
||||
case VU0_VSUB:
|
||||
case VU0_VMUL:
|
||||
// Basic vector math operations
|
||||
break;
|
||||
|
||||
case VU0_VDIV:
|
||||
case VU0_VSQRT:
|
||||
case VU0_VRSQRT:
|
||||
// Division and square root operations
|
||||
break;
|
||||
|
||||
case VU0_VMULQ:
|
||||
// Multiply by Q register
|
||||
break;
|
||||
|
||||
case VU0_VIADD:
|
||||
case VU0_VISUB:
|
||||
case VU0_VIADDI:
|
||||
// Integer operations
|
||||
break;
|
||||
|
||||
case VU0_VIAND:
|
||||
case VU0_VIOR:
|
||||
// Logical operations
|
||||
break;
|
||||
|
||||
case VU0_VILWR:
|
||||
case VU0_VISWR:
|
||||
// Load/Store operations
|
||||
inst.isLoad = (function == VU0_VILWR);
|
||||
inst.isStore = (function == VU0_VISWR);
|
||||
break;
|
||||
|
||||
case VU0_VCALLMS:
|
||||
case VU0_VCALLMSR:
|
||||
// VU0 microprogram calls
|
||||
inst.isCall = true;
|
||||
break;
|
||||
|
||||
case VU0_VRGET:
|
||||
// Get random number from R register
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other VU0 operations
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (rs == COP2_MTC2)
|
||||
break;
|
||||
|
||||
case COP2_CTCVU: // Control Transfer to VU0
|
||||
case COP2_MTVUCF: // Move To VU Control/Flag register
|
||||
case COP2_VMTIR: // Move To VU0 I Register
|
||||
// Special register operations
|
||||
break;
|
||||
|
||||
case COP2_VU0OPS: // Additional VU0 operations
|
||||
{
|
||||
// Move To COP2 register
|
||||
uint32_t function = inst.function;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case VU0OPS_QMFC2_NI: // Non-incrementing QMFC2
|
||||
case VU0OPS_QMFC2_I: // Incrementing QMFC2
|
||||
case VU0OPS_QMTC2_NI: // Non-incrementing QMTC2
|
||||
case VU0OPS_QMTC2_I: // Incrementing QMTC2
|
||||
// Extended register transfer operations
|
||||
break;
|
||||
|
||||
case VU0OPS_VMFIR: // Move From Integer Register
|
||||
// Move operations
|
||||
break;
|
||||
|
||||
case VU0OPS_VXITOP: // Execute Interrupt on VU0
|
||||
break;
|
||||
|
||||
case VU0OPS_VWAITQ: // Wait for Q register operations
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown VU0OPS
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (rs == COP2_CTC2)
|
||||
{
|
||||
// Move To COP2 Control register
|
||||
}
|
||||
else if (rs == COP2_BCF || rs == COP2_BCT)
|
||||
{
|
||||
// VU0 Branch on Condition
|
||||
inst.isBranch = true;
|
||||
inst.hasDelaySlot = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// VU0 vector operations
|
||||
// These would need detailed decoding based on function field
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown COP2 format
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeMMI0(Instruction &inst) const
|
||||
{
|
||||
// Decode MMI0 subfunctions (based on function field)
|
||||
uint32_t subFunction = inst.function & 0x3F;
|
||||
uint32_t sa = inst.sa;
|
||||
|
||||
// The implementation would set appropriate flags or properties based on the specific MMI0 operation
|
||||
switch (sa)
|
||||
{
|
||||
case MMI0_PADDW:
|
||||
case MMI0_PSUBW:
|
||||
case MMI0_PCGTW:
|
||||
case MMI0_PMAXW:
|
||||
case MMI0_PADDH:
|
||||
case MMI0_PSUBH:
|
||||
case MMI0_PCGTH:
|
||||
case MMI0_PMAXH:
|
||||
case MMI0_PADDB:
|
||||
case MMI0_PSUBB:
|
||||
case MMI0_PCGTB:
|
||||
// Arithmetic and comparison operations
|
||||
break;
|
||||
|
||||
case MMI0_PADDSW:
|
||||
case MMI0_PSUBSW:
|
||||
case MMI0_PADDSH:
|
||||
case MMI0_PSUBSH:
|
||||
case MMI0_PADDSB:
|
||||
case MMI0_PSUBSB:
|
||||
// Saturated arithmetic operations
|
||||
break;
|
||||
|
||||
case MMI0_PEXTLW:
|
||||
case MMI0_PPACW:
|
||||
case MMI0_PEXTLH:
|
||||
case MMI0_PPACH:
|
||||
case MMI0_PEXTLB:
|
||||
case MMI0_PPACB:
|
||||
case MMI0_PEXT5:
|
||||
case MMI0_PPAC5:
|
||||
// Data packing/unpacking operations
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown MMI0 operation
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeMMI1(Instruction &inst) const
|
||||
{
|
||||
// Decode MMI1 subfunctions (based on function field)
|
||||
uint32_t subFunction = inst.function & 0x3F;
|
||||
|
||||
// The implementation would set appropriate flags or properties based on the specific MMI1 operation
|
||||
uint32_t sa = inst.sa;
|
||||
|
||||
switch (sa)
|
||||
{
|
||||
case MMI1_PABSW:
|
||||
case MMI1_PABSH:
|
||||
// Absolute value operations
|
||||
break;
|
||||
|
||||
case MMI1_PCEQW:
|
||||
case MMI1_PCEQH:
|
||||
case MMI1_PCEQB:
|
||||
// Equality comparison operations
|
||||
break;
|
||||
|
||||
case MMI1_PMINW:
|
||||
case MMI1_PMINH:
|
||||
// Minimum value operations
|
||||
break;
|
||||
|
||||
case MMI1_PADDUW:
|
||||
case MMI1_PSUBUW:
|
||||
case MMI1_PEXTUW:
|
||||
case MMI1_PADDUH:
|
||||
case MMI1_PSUBUH:
|
||||
case MMI1_PEXTUH:
|
||||
case MMI1_PADDUB:
|
||||
case MMI1_PSUBUB:
|
||||
case MMI1_PEXTUB:
|
||||
// Unsigned arithmetic and extension operations
|
||||
break;
|
||||
|
||||
case MMI1_QFSRV:
|
||||
// Quadword funnel shift right variable
|
||||
inst.isMultimedia = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown MMI1 operation
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeMMI2(Instruction &inst) const
|
||||
{
|
||||
// Decode MMI2 subfunctions (based on function field)
|
||||
uint32_t subFunction = inst.function & 0x3F;
|
||||
uint32_t sa = inst.sa;
|
||||
|
||||
// The implementation would set appropriate flags or properties based on the specific MMI2 operation
|
||||
switch (sa)
|
||||
{
|
||||
case MMI2_PMADDW:
|
||||
case MMI2_PMSUBW:
|
||||
case MMI2_PMADDH:
|
||||
case MMI2_PHMADH:
|
||||
case MMI2_PMSUBH:
|
||||
case MMI2_PHMSBH:
|
||||
case MMI2_PMULTH:
|
||||
// Multiply/multiply-add operations
|
||||
inst.isMultimedia = true;
|
||||
break;
|
||||
|
||||
case MMI2_PSLLVW:
|
||||
case MMI2_PSRLVW:
|
||||
// Variable shift operations
|
||||
break;
|
||||
|
||||
case MMI2_PMFHI:
|
||||
case MMI2_PMFLO:
|
||||
// Move from HI/LO registers
|
||||
break;
|
||||
|
||||
case MMI2_PINTH:
|
||||
// Interleave half words
|
||||
break;
|
||||
|
||||
case MMI2_PMULTW:
|
||||
case MMI2_PDIVW:
|
||||
case MMI2_PDIVBW:
|
||||
// Multiply/divide operations
|
||||
inst.isMultimedia = true;
|
||||
break;
|
||||
|
||||
case MMI2_PCPYLD:
|
||||
// Copy lower doubleword
|
||||
break;
|
||||
|
||||
case MMI2_PAND:
|
||||
case MMI2_PXOR:
|
||||
// Logical operations
|
||||
break;
|
||||
|
||||
case MMI2_PEXEH:
|
||||
case MMI2_PREVH:
|
||||
case MMI2_PEXEW:
|
||||
case MMI2_PROT3W:
|
||||
// Data permutation operations
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown MMI2 operation
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodeMMI3(Instruction &inst) const
|
||||
{
|
||||
// Decode MMI3 subfunctions (based on function field)
|
||||
uint32_t subFunction = inst.function & 0x3F;
|
||||
uint32_t sa = inst.sa;
|
||||
|
||||
// The implementation would set appropriate flags or properties based on the specific MMI3 operation
|
||||
switch (sa)
|
||||
{
|
||||
case MMI3_PMADDUW:
|
||||
// Unsigned multiply-add
|
||||
inst.isMultimedia = true;
|
||||
break;
|
||||
|
||||
case MMI3_PSRAVW:
|
||||
// Packed shift right arithmetic variable word
|
||||
break;
|
||||
|
||||
case MMI3_PMTHI:
|
||||
inst.mmiFunction = MMI3_PMTHI;
|
||||
inst.modificationInfo.modifiesControl = true; // HI register is modified
|
||||
break;
|
||||
|
||||
case MMI3_PMTLO:
|
||||
inst.mmiFunction = MMI3_PMTLO;
|
||||
inst.modificationInfo.modifiesControl = true; // LO register is modified
|
||||
break;
|
||||
|
||||
case MMI3_PINTEH:
|
||||
// Interleave even halfwords
|
||||
break;
|
||||
|
||||
case MMI3_PMULTUW:
|
||||
case MMI3_PDIVUW:
|
||||
// Unsigned multiply/divide operations
|
||||
inst.isMultimedia = true;
|
||||
break;
|
||||
|
||||
case MMI3_PCPYUD:
|
||||
// Copy upper doubleword
|
||||
break;
|
||||
|
||||
case MMI3_POR:
|
||||
case MMI3_PNOR:
|
||||
// Logical operations
|
||||
break;
|
||||
|
||||
case MMI3_PEXCH:
|
||||
case MMI3_PCPYH:
|
||||
case MMI3_PEXCW:
|
||||
// Data permutation operations
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown MMI3 operation
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R5900Decoder::decodePMFHL(Instruction &inst) const
|
||||
|
||||
Reference in New Issue
Block a user