PPCRec: Move Segment and Instruction struct into separate files

This commit is contained in:
Exzap 2022-11-04 22:44:15 +01:00
parent ce5d010611
commit 4abd5127c0
10 changed files with 435 additions and 489 deletions

View file

@ -67,14 +67,17 @@ add_library(CemuCafe
HW/Espresso/Recompiler/PPCFunctionBoundaryTracker.h
HW/Espresso/Recompiler/PPCRecompiler.cpp
HW/Espresso/Recompiler/PPCRecompiler.h
HW/Espresso/Recompiler/IML/IMLSegment.cpp
HW/Espresso/Recompiler/IML/IMLSegment.h
HW/Espresso/Recompiler/IML/IMLInstruction.cpp
HW/Espresso/Recompiler/IML/IMLInstruction.h
HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp
HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp
HW/Espresso/Recompiler/PPCRecompilerImlGenFPU.cpp
HW/Espresso/Recompiler/PPCRecompilerIml.h
HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp
HW/Espresso/Recompiler/PPCRecompilerImlRanges.cpp
HW/Espresso/Recompiler/PPCRecompilerImlRanges.h
HW/Espresso/Recompiler/PPCRecompilerImlRanges.h
HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp
HW/Espresso/Recompiler/PPCRecompilerIntermediate.cpp
HW/Espresso/Recompiler/PPCRecompilerX64AVX.cpp

View file

@ -0,0 +1,387 @@
#pragma once
#define PPCREC_IML_OP_FLAG_SIGNEXTEND (1<<0)
#define PPCREC_IML_OP_FLAG_SWITCHENDIAN (1<<1)
#define PPCREC_IML_OP_FLAG_NOT_EXPANDED (1<<2) // set single-precision load instructions to indicate that the value should not be rounded to double-precision
#define PPCREC_IML_OP_FLAG_UNUSED (1<<7) // used to mark instructions that are not used
enum
{
PPCREC_IML_OP_ASSIGN, // '=' operator
PPCREC_IML_OP_ENDIAN_SWAP, // '=' operator with 32bit endian swap
PPCREC_IML_OP_ADD, // '+' operator
PPCREC_IML_OP_SUB, // '-' operator
PPCREC_IML_OP_SUB_CARRY_UPDATE_CARRY, // complex operation, result = operand + ~operand2 + carry bit, updates carry bit
PPCREC_IML_OP_COMPARE_SIGNED, // arithmetic/signed comparison operator (updates cr)
PPCREC_IML_OP_COMPARE_UNSIGNED, // logical/unsigned comparison operator (updates cr)
PPCREC_IML_OP_MULTIPLY_SIGNED, // '*' operator (signed multiply)
PPCREC_IML_OP_MULTIPLY_HIGH_UNSIGNED, // unsigned 64bit multiply, store only high 32bit-word of result
PPCREC_IML_OP_MULTIPLY_HIGH_SIGNED, // signed 64bit multiply, store only high 32bit-word of result
PPCREC_IML_OP_DIVIDE_SIGNED, // '/' operator (signed divide)
PPCREC_IML_OP_DIVIDE_UNSIGNED, // '/' operator (unsigned divide)
PPCREC_IML_OP_ADD_CARRY, // complex operation, result = operand + carry bit, updates carry bit
PPCREC_IML_OP_ADD_CARRY_ME, // complex operation, result = operand + carry bit + (-1), updates carry bit
PPCREC_IML_OP_ADD_UPDATE_CARRY, // '+' operator but also updates carry flag
PPCREC_IML_OP_ADD_CARRY_UPDATE_CARRY, // '+' operator and also adds carry, updates carry flag
// assign operators with cast
PPCREC_IML_OP_ASSIGN_S16_TO_S32, // copy 16bit and sign extend
PPCREC_IML_OP_ASSIGN_S8_TO_S32, // copy 8bit and sign extend
// binary operation
PPCREC_IML_OP_OR, // '|' operator
PPCREC_IML_OP_ORC, // '|' operator, second operand is complemented first
PPCREC_IML_OP_AND, // '&' operator
PPCREC_IML_OP_XOR, // '^' operator
PPCREC_IML_OP_LEFT_ROTATE, // left rotate operator
PPCREC_IML_OP_LEFT_SHIFT, // shift left operator
PPCREC_IML_OP_RIGHT_SHIFT, // right shift operator (unsigned)
PPCREC_IML_OP_NOT, // complement each bit
PPCREC_IML_OP_NEG, // negate
// ppc
PPCREC_IML_OP_RLWIMI, // RLWIMI instruction (rotate, merge based on mask)
PPCREC_IML_OP_SRAW, // SRAWI/SRAW instruction (algebraic shift right, sets ca flag)
PPCREC_IML_OP_SLW, // SLW (shift based on register by up to 63 bits)
PPCREC_IML_OP_SRW, // SRW (shift based on register by up to 63 bits)
PPCREC_IML_OP_CNTLZW,
PPCREC_IML_OP_SUBFC, // SUBFC and SUBFIC (subtract from and set carry)
PPCREC_IML_OP_DCBZ, // clear 32 bytes aligned to 0x20
PPCREC_IML_OP_MFCR, // copy cr to gpr
PPCREC_IML_OP_MTCRF, // copy gpr to cr (with mask)
// condition register
PPCREC_IML_OP_CR_CLEAR, // clear cr bit
PPCREC_IML_OP_CR_SET, // set cr bit
PPCREC_IML_OP_CR_OR, // OR cr bits
PPCREC_IML_OP_CR_ORC, // OR cr bits, complement second input operand bit first
PPCREC_IML_OP_CR_AND, // AND cr bits
PPCREC_IML_OP_CR_ANDC, // AND cr bits, complement second input operand bit first
// FPU
PPCREC_IML_OP_FPR_ADD_BOTTOM,
PPCREC_IML_OP_FPR_ADD_PAIR,
PPCREC_IML_OP_FPR_SUB_PAIR,
PPCREC_IML_OP_FPR_SUB_BOTTOM,
PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM,
PPCREC_IML_OP_FPR_MULTIPLY_PAIR,
PPCREC_IML_OP_FPR_DIVIDE_BOTTOM,
PPCREC_IML_OP_FPR_DIVIDE_PAIR,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM_AND_TOP,
PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM_AND_TOP,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_TOP, // leave bottom of destination untouched
PPCREC_IML_OP_FPR_COPY_TOP_TO_TOP, // leave bottom of destination untouched
PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM, // leave top of destination untouched
PPCREC_IML_OP_FPR_COPY_BOTTOM_AND_TOP_SWAPPED,
PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64, // expand bottom f32 to f64 in bottom and top half
PPCREC_IML_OP_FPR_BOTTOM_FRES_TO_BOTTOM_AND_TOP, // calculate reciprocal with Espresso accuracy of source bottom half and write result to destination bottom and top half
PPCREC_IML_OP_FPR_FCMPO_BOTTOM,
PPCREC_IML_OP_FPR_FCMPU_BOTTOM,
PPCREC_IML_OP_FPR_FCMPU_TOP,
PPCREC_IML_OP_FPR_NEGATE_BOTTOM,
PPCREC_IML_OP_FPR_NEGATE_PAIR,
PPCREC_IML_OP_FPR_ABS_BOTTOM, // abs(fp0)
PPCREC_IML_OP_FPR_ABS_PAIR,
PPCREC_IML_OP_FPR_FRES_PAIR, // 1.0/fp approx (Espresso accuracy)
PPCREC_IML_OP_FPR_FRSQRTE_PAIR, // 1.0/sqrt(fp) approx (Espresso accuracy)
PPCREC_IML_OP_FPR_NEGATIVE_ABS_BOTTOM, // -abs(fp0)
PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_BOTTOM, // round 64bit double to 64bit double with 32bit float precision (in bottom half of xmm register)
PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_PAIR, // round two 64bit doubles to 64bit double with 32bit float precision
PPCREC_IML_OP_FPR_BOTTOM_RECIPROCAL_SQRT,
PPCREC_IML_OP_FPR_BOTTOM_FCTIWZ,
PPCREC_IML_OP_FPR_SELECT_BOTTOM, // selectively copy bottom value from operand B or C based on value in operand A
PPCREC_IML_OP_FPR_SELECT_PAIR, // selectively copy top/bottom from operand B or C based on value in top/bottom of operand A
// PS
PPCREC_IML_OP_FPR_SUM0,
PPCREC_IML_OP_FPR_SUM1,
};
#define PPCREC_IML_OP_FPR_COPY_PAIR (PPCREC_IML_OP_ASSIGN)
enum
{
PPCREC_IML_MACRO_BLR, // macro for BLR instruction code
PPCREC_IML_MACRO_BLRL, // macro for BLRL instruction code
PPCREC_IML_MACRO_BCTR, // macro for BCTR instruction code
PPCREC_IML_MACRO_BCTRL, // macro for BCTRL instruction code
PPCREC_IML_MACRO_BL, // call to different function (can be within same function)
PPCREC_IML_MACRO_B_FAR, // branch to different function
PPCREC_IML_MACRO_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount
PPCREC_IML_MACRO_HLE, // HLE function call
PPCREC_IML_MACRO_MFTB, // get TB register value (low or high)
PPCREC_IML_MACRO_LEAVE, // leaves recompiler and switches to interpeter
// debugging
PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak
};
enum
{
PPCREC_JUMP_CONDITION_NONE,
PPCREC_JUMP_CONDITION_E, // equal / zero
PPCREC_JUMP_CONDITION_NE, // not equal / not zero
PPCREC_JUMP_CONDITION_LE, // less or equal
PPCREC_JUMP_CONDITION_L, // less
PPCREC_JUMP_CONDITION_GE, // greater or equal
PPCREC_JUMP_CONDITION_G, // greater
// special case:
PPCREC_JUMP_CONDITION_SUMMARYOVERFLOW, // needs special handling
PPCREC_JUMP_CONDITION_NSUMMARYOVERFLOW, // not summaryoverflow
};
enum
{
PPCREC_CR_MODE_COMPARE_SIGNED,
PPCREC_CR_MODE_COMPARE_UNSIGNED, // alias logic compare
// others: PPCREC_CR_MODE_ARITHMETIC,
PPCREC_CR_MODE_ARITHMETIC, // arithmetic use (for use with add/sub instructions without generating extra code)
PPCREC_CR_MODE_LOGICAL,
};
enum
{
PPCREC_IML_TYPE_NONE,
PPCREC_IML_TYPE_NO_OP, // no-op instruction
PPCREC_IML_TYPE_JUMPMARK, // possible jump destination (generated before each ppc instruction)
PPCREC_IML_TYPE_R_R, // r* (op) *r
PPCREC_IML_TYPE_R_R_R, // r* = r* (op) r*
PPCREC_IML_TYPE_R_R_S32, // r* = r* (op) s32*
PPCREC_IML_TYPE_LOAD, // r* = [r*+s32*]
PPCREC_IML_TYPE_LOAD_INDEXED, // r* = [r*+r*]
PPCREC_IML_TYPE_STORE, // [r*+s32*] = r*
PPCREC_IML_TYPE_STORE_INDEXED, // [r*+r*] = r*
PPCREC_IML_TYPE_R_NAME, // r* = name
PPCREC_IML_TYPE_NAME_R, // name* = r*
PPCREC_IML_TYPE_R_S32, // r* (op) imm
PPCREC_IML_TYPE_MACRO,
PPCREC_IML_TYPE_CJUMP, // conditional jump
PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK, // jumps only if remaining thread cycles >= 0
PPCREC_IML_TYPE_PPC_ENTER, // used to mark locations that should be written to recompilerCallTable
PPCREC_IML_TYPE_CR, // condition register specific operations (one or more operands)
// conditional
PPCREC_IML_TYPE_CONDITIONAL_R_S32,
// FPR
PPCREC_IML_TYPE_FPR_R_NAME, // name = f*
PPCREC_IML_TYPE_FPR_NAME_R, // f* = name
PPCREC_IML_TYPE_FPR_LOAD, // r* = (bitdepth) [r*+s32*] (single or paired single mode)
PPCREC_IML_TYPE_FPR_LOAD_INDEXED, // r* = (bitdepth) [r*+r*] (single or paired single mode)
PPCREC_IML_TYPE_FPR_STORE, // (bitdepth) [r*+s32*] = r* (single or paired single mode)
PPCREC_IML_TYPE_FPR_STORE_INDEXED, // (bitdepth) [r*+r*] = r* (single or paired single mode)
PPCREC_IML_TYPE_FPR_R_R,
PPCREC_IML_TYPE_FPR_R_R_R,
PPCREC_IML_TYPE_FPR_R_R_R_R,
PPCREC_IML_TYPE_FPR_R,
};
enum
{
PPCREC_NAME_NONE,
PPCREC_NAME_TEMPORARY,
PPCREC_NAME_R0 = 1000,
PPCREC_NAME_SPR0 = 2000,
PPCREC_NAME_FPR0 = 3000,
PPCREC_NAME_TEMPORARY_FPR0 = 4000, // 0 to 7
//PPCREC_NAME_CR0 = 3000, // value mapped condition register (usually it isn't needed and can be optimized away)
};
// special cases for LOAD/STORE
#define PPC_REC_LOAD_LWARX_MARKER (100) // lwarx instruction (similar to LWZX but sets reserved address/value)
#define PPC_REC_STORE_STWCX_MARKER (100) // stwcx instruction (similar to STWX but writes only if reservation from LWARX is valid)
#define PPC_REC_STORE_STSWI_1 (200) // stswi nb = 1
#define PPC_REC_STORE_STSWI_2 (201) // stswi nb = 2
#define PPC_REC_STORE_STSWI_3 (202) // stswi nb = 3
#define PPC_REC_STORE_LSWI_1 (200) // lswi nb = 1
#define PPC_REC_STORE_LSWI_2 (201) // lswi nb = 2
#define PPC_REC_STORE_LSWI_3 (202) // lswi nb = 3
#define PPC_REC_INVALID_REGISTER 0xFF
#define PPCREC_CR_BIT_LT 0
#define PPCREC_CR_BIT_GT 1
#define PPCREC_CR_BIT_EQ 2
#define PPCREC_CR_BIT_SO 3
enum
{
// fpr load
PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0,
PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1,
PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0,
PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0,
PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0,
PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_S16_PS0,
PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_U16_PS0,
PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_S8_PS0,
PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_U8_PS0,
PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1,
// fpr store
PPCREC_FPR_ST_MODE_SINGLE_FROM_PS0, // store 1 single precision float from ps0
PPCREC_FPR_ST_MODE_DOUBLE_FROM_PS0, // store 1 double precision float from ps0
PPCREC_FPR_ST_MODE_UI32_FROM_PS0, // store raw low-32bit of PS0
PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0,
PPCREC_FPR_ST_MODE_PSQ_FLOAT_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_FLOAT_PS0,
PPCREC_FPR_ST_MODE_PSQ_S8_PS0,
PPCREC_FPR_ST_MODE_PSQ_S8_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_U8_PS0,
PPCREC_FPR_ST_MODE_PSQ_U8_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_U16_PS0,
PPCREC_FPR_ST_MODE_PSQ_U16_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_S16_PS0,
PPCREC_FPR_ST_MODE_PSQ_S16_PS0_PS1,
};
struct PPCRecImlInstruction_t
{
uint8 type;
uint8 operation;
uint8 crRegister; // set to 0xFF if not set, not all IML instruction types support cr.
uint8 crMode; // only used when crRegister is valid, used to differentiate between various forms of condition flag set/clear behavior
uint32 crIgnoreMask; // bit set for every respective CR bit that doesn't need to be updated
uint32 associatedPPCAddress; // ppc address that is associated with this instruction
union
{
struct
{
uint8 _padding[7];
}padding;
struct
{
// R (op) A [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
}op_r_r;
struct
{
// R = A (op) B [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
uint8 registerB;
}op_r_r_r;
struct
{
// R = A (op) immS32 [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
sint32 immS32;
}op_r_r_s32;
struct
{
// R/F = NAME or NAME = R/F
uint8 registerIndex;
uint8 copyWidth;
uint32 name;
uint8 flags;
}op_r_name;
struct
{
// R (op) s32 [update cr* in mode *]
uint8 registerIndex;
sint32 immS32;
}op_r_immS32;
struct
{
uint32 address;
uint8 flags;
}op_jumpmark;
struct
{
uint32 param;
uint32 param2;
uint16 paramU16;
}op_macro;
struct
{
uint32 jumpmarkAddress;
bool jumpAccordingToSegment; //PPCRecImlSegment_t* destinationSegment; // if set, this replaces jumpmarkAddress
uint8 condition; // only used when crRegisterIndex is 8 or above (update: Apparently only used to mark jumps without a condition? -> Cleanup)
uint8 crRegisterIndex;
uint8 crBitIndex;
bool bitMustBeSet;
}op_conditionalJump;
struct
{
uint8 registerData;
uint8 registerMem;
uint8 registerMem2;
uint8 registerGQR;
uint8 copyWidth;
//uint8 flags;
struct
{
bool swapEndian : 1;
bool signExtend : 1;
bool notExpanded : 1; // for floats
}flags2;
uint8 mode; // transfer mode (copy width, ps0/ps1 behavior)
sint32 immS32;
}op_storeLoad;
struct
{
struct
{
uint8 registerMem;
sint32 immS32;
}src;
struct
{
uint8 registerMem;
sint32 immS32;
}dst;
uint8 copyWidth;
}op_mem2mem;
struct
{
uint8 registerResult;
uint8 registerOperand;
uint8 flags;
}op_fpr_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 flags;
}op_fpr_r_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 registerOperandC;
uint8 flags;
}op_fpr_r_r_r_r;
struct
{
uint8 registerResult;
//uint8 flags;
}op_fpr_r;
struct
{
uint32 ppcAddress;
uint32 x64Offset;
}op_ppcEnter;
struct
{
uint8 crD; // crBitIndex (result)
uint8 crA; // crBitIndex
uint8 crB; // crBitIndex
}op_cr;
// conditional operations (emitted if supported by target platform)
struct
{
// r_s32
uint8 registerIndex;
sint32 immS32;
// condition
uint8 crRegisterIndex;
uint8 crBitIndex;
bool bitMustBeSet;
}op_conditional_r_s32;
};
};

View file

@ -0,0 +1,40 @@
#pragma once
struct PPCRecImlSegment_t
{
sint32 momentaryIndex{}; // index in segment list, generally not kept up to date except if needed (necessary for loop detection)
sint32 startOffset{}; // offset to first instruction in iml instruction list
sint32 count{}; // number of instructions in segment
uint32 ppcAddress{}; // ppc address (0xFFFFFFFF if not associated with an address)
uint32 x64Offset{}; // x64 code offset of segment start
uint32 cycleCount{}; // number of PPC cycles required to execute this segment (roughly)
// list of intermediate instructions in this segment
std::vector<PPCRecImlInstruction_t> imlList;
// segment link
PPCRecImlSegment_t* nextSegmentBranchNotTaken{}; // this is also the default for segments where there is no branch
PPCRecImlSegment_t* nextSegmentBranchTaken{};
bool nextSegmentIsUncertain{};
sint32 loopDepth{};
std::vector<PPCRecImlSegment_t*> list_prevSegments{};
// PPC range of segment
uint32 ppcAddrMin{};
uint32 ppcAddrMax{};
// enterable segments
bool isEnterable{}; // this segment can be entered from outside the recompiler (no preloaded registers necessary)
uint32 enterPPCAddress{}; // used if isEnterable is true
// jump destination segments
bool isJumpDestination{}; // segment is a destination for one or more (conditional) jumps
uint32 jumpDestinationPPCAddress{};
// PPC FPR use mask
bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
// CR use mask
uint32 crBitsInput{}; // bits that are expected to be set from the previous segment (read in this segment but not overwritten)
uint32 crBitsRead{}; // all bits that are read in this segment
uint32 crBitsWritten{}; // bits that are written in this segment
// register allocator info
PPCSegmentRegisterAllocatorInfo_t raInfo{};
PPCRecVGPRDistances_t raDistances{};
bool raRangeExtendProcessed{};
// segment points
ppcRecompilerSegmentPoint_t* segmentPointList{};
};

View file

@ -26,167 +26,12 @@ typedef struct
std::vector<ppcRecRange_t> list_ranges;
}PPCRecFunction_t;
#define PPCREC_IML_OP_FLAG_SIGNEXTEND (1<<0)
#define PPCREC_IML_OP_FLAG_SWITCHENDIAN (1<<1)
#define PPCREC_IML_OP_FLAG_NOT_EXPANDED (1<<2) // set single-precision load instructions to indicate that the value should not be rounded to double-precision
#define PPCREC_IML_OP_FLAG_UNUSED (1<<7) // used to mark instructions that are not used
typedef struct
{
uint8 type;
uint8 operation;
uint8 crRegister; // set to 0xFF if not set, not all IML instruction types support cr.
uint8 crMode; // only used when crRegister is valid, used to differentiate between various forms of condition flag set/clear behavior
uint32 crIgnoreMask; // bit set for every respective CR bit that doesn't need to be updated
uint32 associatedPPCAddress; // ppc address that is associated with this instruction
union
{
struct
{
uint8 _padding[7];
}padding;
struct
{
// R (op) A [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
}op_r_r;
struct
{
// R = A (op) B [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
uint8 registerB;
}op_r_r_r;
struct
{
// R = A (op) immS32 [update cr* in mode *]
uint8 registerResult;
uint8 registerA;
sint32 immS32;
}op_r_r_s32;
struct
{
// R/F = NAME or NAME = R/F
uint8 registerIndex;
uint8 copyWidth;
uint32 name;
uint8 flags;
}op_r_name;
struct
{
// R (op) s32 [update cr* in mode *]
uint8 registerIndex;
sint32 immS32;
}op_r_immS32;
struct
{
uint32 address;
uint8 flags;
}op_jumpmark;
struct
{
uint32 param;
uint32 param2;
uint16 paramU16;
}op_macro;
struct
{
uint32 jumpmarkAddress;
bool jumpAccordingToSegment; //PPCRecImlSegment_t* destinationSegment; // if set, this replaces jumpmarkAddress
uint8 condition; // only used when crRegisterIndex is 8 or above (update: Apparently only used to mark jumps without a condition? -> Cleanup)
uint8 crRegisterIndex;
uint8 crBitIndex;
bool bitMustBeSet;
}op_conditionalJump;
struct
{
uint8 registerData;
uint8 registerMem;
uint8 registerMem2;
uint8 registerGQR;
uint8 copyWidth;
//uint8 flags;
struct
{
bool swapEndian : 1;
bool signExtend : 1;
bool notExpanded : 1; // for floats
}flags2;
uint8 mode; // transfer mode (copy width, ps0/ps1 behavior)
sint32 immS32;
}op_storeLoad;
struct
{
struct
{
uint8 registerMem;
sint32 immS32;
}src;
struct
{
uint8 registerMem;
sint32 immS32;
}dst;
uint8 copyWidth;
}op_mem2mem;
struct
{
uint8 registerResult;
uint8 registerOperand;
uint8 flags;
}op_fpr_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 flags;
}op_fpr_r_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 registerOperandC;
uint8 flags;
}op_fpr_r_r_r_r;
struct
{
uint8 registerResult;
//uint8 flags;
}op_fpr_r;
struct
{
uint32 ppcAddress;
uint32 x64Offset;
}op_ppcEnter;
struct
{
uint8 crD; // crBitIndex (result)
uint8 crA; // crBitIndex
uint8 crB; // crBitIndex
}op_cr;
// conditional operations (emitted if supported by target platform)
struct
{
// r_s32
uint8 registerIndex;
sint32 immS32;
// condition
uint8 crRegisterIndex;
uint8 crBitIndex;
bool bitMustBeSet;
}op_conditional_r_s32;
};
}PPCRecImlInstruction_t;
typedef struct _PPCRecImlSegment_t PPCRecImlSegment_t;
#include "Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h"
typedef struct _ppcRecompilerSegmentPoint_t
{
sint32 index;
PPCRecImlSegment_t* imlSegment;
struct PPCRecImlSegment_t* imlSegment;
_ppcRecompilerSegmentPoint_t* next;
_ppcRecompilerSegmentPoint_t* prev;
}ppcRecompilerSegmentPoint_t;
@ -260,45 +105,7 @@ struct PPCRecVGPRDistances_t
bool isProcessed[PPC_REC_MAX_VIRTUAL_GPR]{};
};
typedef struct _PPCRecImlSegment_t
{
sint32 momentaryIndex{}; // index in segment list, generally not kept up to date except if needed (necessary for loop detection)
sint32 startOffset{}; // offset to first instruction in iml instruction list
sint32 count{}; // number of instructions in segment
uint32 ppcAddress{}; // ppc address (0xFFFFFFFF if not associated with an address)
uint32 x64Offset{}; // x64 code offset of segment start
uint32 cycleCount{}; // number of PPC cycles required to execute this segment (roughly)
// list of intermediate instructions in this segment
std::vector<PPCRecImlInstruction_t> imlList;
// segment link
_PPCRecImlSegment_t* nextSegmentBranchNotTaken{}; // this is also the default for segments where there is no branch
_PPCRecImlSegment_t* nextSegmentBranchTaken{};
bool nextSegmentIsUncertain{};
sint32 loopDepth{};
//sList_t* list_prevSegments;
std::vector<_PPCRecImlSegment_t*> list_prevSegments{};
// PPC range of segment
uint32 ppcAddrMin{};
uint32 ppcAddrMax{};
// enterable segments
bool isEnterable{}; // this segment can be entered from outside the recompiler (no preloaded registers necessary)
uint32 enterPPCAddress{}; // used if isEnterable is true
// jump destination segments
bool isJumpDestination{}; // segment is a destination for one or more (conditional) jumps
uint32 jumpDestinationPPCAddress{};
// PPC FPR use mask
bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
// CR use mask
uint32 crBitsInput{}; // bits that are expected to be set from the previous segment (read in this segment but not overwritten)
uint32 crBitsRead{}; // all bits that are read in this segment
uint32 crBitsWritten{}; // bits that are written in this segment
// register allocator info
PPCSegmentRegisterAllocatorInfo_t raInfo{};
PPCRecVGPRDistances_t raDistances{};
bool raRangeExtendProcessed{};
// segment points
ppcRecompilerSegmentPoint_t* segmentPointList{};
}PPCRecImlSegment_t;
#include "Cafe/HW/Espresso/Recompiler/IML/IMLSegment.h"
struct ppcImlGenContext_t
{

View file

@ -1,239 +1,6 @@
#define PPCREC_CR_REG_TEMP 8 // there are only 8 cr registers (0-7) we use the 8th as temporary cr register that is never stored (BDNZ instruction for example)
enum
{
PPCREC_IML_OP_ASSIGN, // '=' operator
PPCREC_IML_OP_ENDIAN_SWAP, // '=' operator with 32bit endian swap
PPCREC_IML_OP_ADD, // '+' operator
PPCREC_IML_OP_SUB, // '-' operator
PPCREC_IML_OP_SUB_CARRY_UPDATE_CARRY, // complex operation, result = operand + ~operand2 + carry bit, updates carry bit
PPCREC_IML_OP_COMPARE_SIGNED, // arithmetic/signed comparison operator (updates cr)
PPCREC_IML_OP_COMPARE_UNSIGNED, // logical/unsigned comparison operator (updates cr)
PPCREC_IML_OP_MULTIPLY_SIGNED, // '*' operator (signed multiply)
PPCREC_IML_OP_MULTIPLY_HIGH_UNSIGNED, // unsigned 64bit multiply, store only high 32bit-word of result
PPCREC_IML_OP_MULTIPLY_HIGH_SIGNED, // signed 64bit multiply, store only high 32bit-word of result
PPCREC_IML_OP_DIVIDE_SIGNED, // '/' operator (signed divide)
PPCREC_IML_OP_DIVIDE_UNSIGNED, // '/' operator (unsigned divide)
PPCREC_IML_OP_ADD_CARRY, // complex operation, result = operand + carry bit, updates carry bit
PPCREC_IML_OP_ADD_CARRY_ME, // complex operation, result = operand + carry bit + (-1), updates carry bit
PPCREC_IML_OP_ADD_UPDATE_CARRY, // '+' operator but also updates carry flag
PPCREC_IML_OP_ADD_CARRY_UPDATE_CARRY, // '+' operator and also adds carry, updates carry flag
// assign operators with cast
PPCREC_IML_OP_ASSIGN_S16_TO_S32, // copy 16bit and sign extend
PPCREC_IML_OP_ASSIGN_S8_TO_S32, // copy 8bit and sign extend
// binary operation
PPCREC_IML_OP_OR, // '|' operator
PPCREC_IML_OP_ORC, // '|' operator, second operand is complemented first
PPCREC_IML_OP_AND, // '&' operator
PPCREC_IML_OP_XOR, // '^' operator
PPCREC_IML_OP_LEFT_ROTATE, // left rotate operator
PPCREC_IML_OP_LEFT_SHIFT, // shift left operator
PPCREC_IML_OP_RIGHT_SHIFT, // right shift operator (unsigned)
PPCREC_IML_OP_NOT, // complement each bit
PPCREC_IML_OP_NEG, // negate
// ppc
PPCREC_IML_OP_RLWIMI, // RLWIMI instruction (rotate, merge based on mask)
PPCREC_IML_OP_SRAW, // SRAWI/SRAW instruction (algebraic shift right, sets ca flag)
PPCREC_IML_OP_SLW, // SLW (shift based on register by up to 63 bits)
PPCREC_IML_OP_SRW, // SRW (shift based on register by up to 63 bits)
PPCREC_IML_OP_CNTLZW,
PPCREC_IML_OP_SUBFC, // SUBFC and SUBFIC (subtract from and set carry)
PPCREC_IML_OP_DCBZ, // clear 32 bytes aligned to 0x20
PPCREC_IML_OP_MFCR, // copy cr to gpr
PPCREC_IML_OP_MTCRF, // copy gpr to cr (with mask)
// condition register
PPCREC_IML_OP_CR_CLEAR, // clear cr bit
PPCREC_IML_OP_CR_SET, // set cr bit
PPCREC_IML_OP_CR_OR, // OR cr bits
PPCREC_IML_OP_CR_ORC, // OR cr bits, complement second input operand bit first
PPCREC_IML_OP_CR_AND, // AND cr bits
PPCREC_IML_OP_CR_ANDC, // AND cr bits, complement second input operand bit first
// FPU
PPCREC_IML_OP_FPR_ADD_BOTTOM,
PPCREC_IML_OP_FPR_ADD_PAIR,
PPCREC_IML_OP_FPR_SUB_PAIR,
PPCREC_IML_OP_FPR_SUB_BOTTOM,
PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM,
PPCREC_IML_OP_FPR_MULTIPLY_PAIR,
PPCREC_IML_OP_FPR_DIVIDE_BOTTOM,
PPCREC_IML_OP_FPR_DIVIDE_PAIR,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM_AND_TOP,
PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM_AND_TOP,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM,
PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_TOP, // leave bottom of destination untouched
PPCREC_IML_OP_FPR_COPY_TOP_TO_TOP, // leave bottom of destination untouched
PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM, // leave top of destination untouched
PPCREC_IML_OP_FPR_COPY_BOTTOM_AND_TOP_SWAPPED,
PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64, // expand bottom f32 to f64 in bottom and top half
PPCREC_IML_OP_FPR_BOTTOM_FRES_TO_BOTTOM_AND_TOP, // calculate reciprocal with Espresso accuracy of source bottom half and write result to destination bottom and top half
PPCREC_IML_OP_FPR_FCMPO_BOTTOM,
PPCREC_IML_OP_FPR_FCMPU_BOTTOM,
PPCREC_IML_OP_FPR_FCMPU_TOP,
PPCREC_IML_OP_FPR_NEGATE_BOTTOM,
PPCREC_IML_OP_FPR_NEGATE_PAIR,
PPCREC_IML_OP_FPR_ABS_BOTTOM, // abs(fp0)
PPCREC_IML_OP_FPR_ABS_PAIR,
PPCREC_IML_OP_FPR_FRES_PAIR, // 1.0/fp approx (Espresso accuracy)
PPCREC_IML_OP_FPR_FRSQRTE_PAIR, // 1.0/sqrt(fp) approx (Espresso accuracy)
PPCREC_IML_OP_FPR_NEGATIVE_ABS_BOTTOM, // -abs(fp0)
PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_BOTTOM, // round 64bit double to 64bit double with 32bit float precision (in bottom half of xmm register)
PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_PAIR, // round two 64bit doubles to 64bit double with 32bit float precision
PPCREC_IML_OP_FPR_BOTTOM_RECIPROCAL_SQRT,
PPCREC_IML_OP_FPR_BOTTOM_FCTIWZ,
PPCREC_IML_OP_FPR_SELECT_BOTTOM, // selectively copy bottom value from operand B or C based on value in operand A
PPCREC_IML_OP_FPR_SELECT_PAIR, // selectively copy top/bottom from operand B or C based on value in top/bottom of operand A
// PS
PPCREC_IML_OP_FPR_SUM0,
PPCREC_IML_OP_FPR_SUM1,
};
#define PPCREC_IML_OP_FPR_COPY_PAIR (PPCREC_IML_OP_ASSIGN)
enum
{
PPCREC_IML_MACRO_BLR, // macro for BLR instruction code
PPCREC_IML_MACRO_BLRL, // macro for BLRL instruction code
PPCREC_IML_MACRO_BCTR, // macro for BCTR instruction code
PPCREC_IML_MACRO_BCTRL, // macro for BCTRL instruction code
PPCREC_IML_MACRO_BL, // call to different function (can be within same function)
PPCREC_IML_MACRO_B_FAR, // branch to different function
PPCREC_IML_MACRO_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount
PPCREC_IML_MACRO_HLE, // HLE function call
PPCREC_IML_MACRO_MFTB, // get TB register value (low or high)
PPCREC_IML_MACRO_LEAVE, // leaves recompiler and switches to interpeter
// debugging
PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak
};
enum
{
PPCREC_JUMP_CONDITION_NONE,
PPCREC_JUMP_CONDITION_E, // equal / zero
PPCREC_JUMP_CONDITION_NE, // not equal / not zero
PPCREC_JUMP_CONDITION_LE, // less or equal
PPCREC_JUMP_CONDITION_L, // less
PPCREC_JUMP_CONDITION_GE, // greater or equal
PPCREC_JUMP_CONDITION_G, // greater
// special case:
PPCREC_JUMP_CONDITION_SUMMARYOVERFLOW, // needs special handling
PPCREC_JUMP_CONDITION_NSUMMARYOVERFLOW, // not summaryoverflow
};
enum
{
PPCREC_CR_MODE_COMPARE_SIGNED,
PPCREC_CR_MODE_COMPARE_UNSIGNED, // alias logic compare
// others: PPCREC_CR_MODE_ARITHMETIC,
PPCREC_CR_MODE_ARITHMETIC, // arithmetic use (for use with add/sub instructions without generating extra code)
PPCREC_CR_MODE_LOGICAL,
};
enum
{
PPCREC_IML_TYPE_NONE,
PPCREC_IML_TYPE_NO_OP, // no-op instruction
PPCREC_IML_TYPE_JUMPMARK, // possible jump destination (generated before each ppc instruction)
PPCREC_IML_TYPE_R_R, // r* (op) *r
PPCREC_IML_TYPE_R_R_R, // r* = r* (op) r*
PPCREC_IML_TYPE_R_R_S32, // r* = r* (op) s32*
PPCREC_IML_TYPE_LOAD, // r* = [r*+s32*]
PPCREC_IML_TYPE_LOAD_INDEXED, // r* = [r*+r*]
PPCREC_IML_TYPE_STORE, // [r*+s32*] = r*
PPCREC_IML_TYPE_STORE_INDEXED, // [r*+r*] = r*
PPCREC_IML_TYPE_R_NAME, // r* = name
PPCREC_IML_TYPE_NAME_R, // name* = r*
PPCREC_IML_TYPE_R_S32, // r* (op) imm
PPCREC_IML_TYPE_MACRO,
PPCREC_IML_TYPE_CJUMP, // conditional jump
PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK, // jumps only if remaining thread cycles >= 0
PPCREC_IML_TYPE_PPC_ENTER, // used to mark locations that should be written to recompilerCallTable
PPCREC_IML_TYPE_CR, // condition register specific operations (one or more operands)
// conditional
PPCREC_IML_TYPE_CONDITIONAL_R_S32,
// FPR
PPCREC_IML_TYPE_FPR_R_NAME, // name = f*
PPCREC_IML_TYPE_FPR_NAME_R, // f* = name
PPCREC_IML_TYPE_FPR_LOAD, // r* = (bitdepth) [r*+s32*] (single or paired single mode)
PPCREC_IML_TYPE_FPR_LOAD_INDEXED, // r* = (bitdepth) [r*+r*] (single or paired single mode)
PPCREC_IML_TYPE_FPR_STORE, // (bitdepth) [r*+s32*] = r* (single or paired single mode)
PPCREC_IML_TYPE_FPR_STORE_INDEXED, // (bitdepth) [r*+r*] = r* (single or paired single mode)
PPCREC_IML_TYPE_FPR_R_R,
PPCREC_IML_TYPE_FPR_R_R_R,
PPCREC_IML_TYPE_FPR_R_R_R_R,
PPCREC_IML_TYPE_FPR_R,
// special
PPCREC_IML_TYPE_MEM2MEM, // memory to memory copy (deprecated)
};
enum
{
PPCREC_NAME_NONE,
PPCREC_NAME_TEMPORARY,
PPCREC_NAME_R0 = 1000,
PPCREC_NAME_SPR0 = 2000,
PPCREC_NAME_FPR0 = 3000,
PPCREC_NAME_TEMPORARY_FPR0 = 4000, // 0 to 7
//PPCREC_NAME_CR0 = 3000, // value mapped condition register (usually it isn't needed and can be optimized away)
};
// special cases for LOAD/STORE
#define PPC_REC_LOAD_LWARX_MARKER (100) // lwarx instruction (similar to LWZX but sets reserved address/value)
#define PPC_REC_STORE_STWCX_MARKER (100) // stwcx instruction (similar to STWX but writes only if reservation from LWARX is valid)
#define PPC_REC_STORE_STSWI_1 (200) // stswi nb = 1
#define PPC_REC_STORE_STSWI_2 (201) // stswi nb = 2
#define PPC_REC_STORE_STSWI_3 (202) // stswi nb = 3
#define PPC_REC_STORE_LSWI_1 (200) // lswi nb = 1
#define PPC_REC_STORE_LSWI_2 (201) // lswi nb = 2
#define PPC_REC_STORE_LSWI_3 (202) // lswi nb = 3
#define PPC_REC_INVALID_REGISTER 0xFF
#define PPCREC_CR_BIT_LT 0
#define PPCREC_CR_BIT_GT 1
#define PPCREC_CR_BIT_EQ 2
#define PPCREC_CR_BIT_SO 3
enum
{
// fpr load
PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0,
PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1,
PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0,
PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0,
PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0,
PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_S16_PS0,
PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_U16_PS0,
PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_S8_PS0,
PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1,
PPCREC_FPR_LD_MODE_PSQ_U8_PS0,
PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1,
// fpr store
PPCREC_FPR_ST_MODE_SINGLE_FROM_PS0, // store 1 single precision float from ps0
PPCREC_FPR_ST_MODE_DOUBLE_FROM_PS0, // store 1 double precision float from ps0
PPCREC_FPR_ST_MODE_UI32_FROM_PS0, // store raw low-32bit of PS0
PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0,
PPCREC_FPR_ST_MODE_PSQ_FLOAT_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_FLOAT_PS0,
PPCREC_FPR_ST_MODE_PSQ_S8_PS0,
PPCREC_FPR_ST_MODE_PSQ_S8_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_U8_PS0,
PPCREC_FPR_ST_MODE_PSQ_U8_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_U16_PS0,
PPCREC_FPR_ST_MODE_PSQ_U16_PS0_PS1,
PPCREC_FPR_ST_MODE_PSQ_S16_PS0,
PPCREC_FPR_ST_MODE_PSQ_S16_PS0_PS1,
};
bool PPCRecompiler_generateIntermediateCode(ppcImlGenContext_t& ppcImlGenContext, PPCRecFunction_t* PPCRecFunction, std::set<uint32>& entryAddresses);
void PPCRecompiler_freeContext(ppcImlGenContext_t* ppcImlGenContext); // todo - move to destructor
@ -267,7 +34,6 @@ void PPCRecompilerImlGen_generateNewInstruction_r_r(ppcImlGenContext_t* ppcImlGe
// IML instruction generation (new style, can generate new instructions but also overwrite existing ones)
void PPCRecompilerImlGen_generateNewInstruction_noOp(ppcImlGenContext_t* ppcImlGenContext, PPCRecImlInstruction_t* imlInstruction);
void PPCRecompilerImlGen_generateNewInstruction_memory_memory(ppcImlGenContext_t* ppcImlGenContext, PPCRecImlInstruction_t* imlInstruction, uint8 srcMemReg, sint32 srcImmS32, uint8 dstMemReg, sint32 dstImmS32, uint8 copyWidth);
void PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext_t* ppcImlGenContext, PPCRecImlInstruction_t* imlInstruction, sint32 operation, uint8 registerResult, sint32 crRegister = PPC_REC_INVALID_REGISTER);

View file

@ -280,21 +280,6 @@ void PPCRecompilerImlGen_generateNewInstruction_memory_r_indexed(ppcImlGenContex
imlInstruction->op_storeLoad.flags2.signExtend = signExtend;
}
void PPCRecompilerImlGen_generateNewInstruction_memory_memory(ppcImlGenContext_t* ppcImlGenContext, PPCRecImlInstruction_t* imlInstruction, uint8 srcMemReg, sint32 srcImmS32, uint8 dstMemReg, sint32 dstImmS32, uint8 copyWidth)
{
// copy from memory to memory
if(imlInstruction == NULL)
imlInstruction = PPCRecompilerImlGen_generateNewEmptyInstruction(ppcImlGenContext);
imlInstruction->type = PPCREC_IML_TYPE_MEM2MEM;
imlInstruction->operation = 0;
imlInstruction->crRegister = PPC_REC_INVALID_REGISTER;
imlInstruction->op_mem2mem.src.registerMem = srcMemReg;
imlInstruction->op_mem2mem.src.immS32 = srcImmS32;
imlInstruction->op_mem2mem.dst.registerMem = dstMemReg;
imlInstruction->op_mem2mem.dst.immS32 = dstImmS32;
imlInstruction->op_mem2mem.copyWidth = copyWidth;
}
uint32 PPCRecompilerImlGen_getAndLockFreeTemporaryGPR(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
{
if( mappedName == PPCREC_NAME_NONE )
@ -3234,10 +3219,6 @@ void PPCRecompiler_dumpIMLSegment(PPCRecImlSegment_t* imlSegment, sint32 segment
else
strOutput.addFmt("[t{}+{}]", inst.op_storeLoad.registerMem, inst.op_storeLoad.immS32);
}
else if (inst.type == PPCREC_IML_TYPE_MEM2MEM)
{
strOutput.addFmt("{} [t{}+{}] = [t{}+{}]", inst.op_mem2mem.copyWidth, inst.op_mem2mem.dst.registerMem, inst.op_mem2mem.dst.immS32, inst.op_mem2mem.src.registerMem, inst.op_mem2mem.src.immS32);
}
else if( inst.type == PPCREC_IML_TYPE_CJUMP )
{
if (inst.op_conditionalJump.condition == PPCREC_JUMP_CONDITION_E)

View file

@ -142,11 +142,6 @@ void PPCRecompiler_checkRegisterUsage(ppcImlGenContext_t* ppcImlGenContext, cons
if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem;
}
else if (imlInstruction->type == PPCREC_IML_TYPE_MEM2MEM)
{
registersUsed->readNamedReg1 = imlInstruction->op_mem2mem.src.registerMem;
registersUsed->readNamedReg2 = imlInstruction->op_mem2mem.dst.registerMem;
}
else if( imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED )
{
registersUsed->writtenNamedReg1 = imlInstruction->op_storeLoad.registerData;
@ -655,10 +650,6 @@ void PPCRecompiler_replaceFPRRegisterUsageMultiple(ppcImlGenContext_t* ppcImlGen
{
// not affected
}
else if (imlInstruction->type == PPCREC_IML_TYPE_MEM2MEM)
{
// not affected
}
else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED)
{
// not affected
@ -777,10 +768,6 @@ void PPCRecompiler_replaceFPRRegisterUsage(ppcImlGenContext_t* ppcImlGenContext,
{
// not affected
}
else if (imlInstruction->type == PPCREC_IML_TYPE_MEM2MEM)
{
// not affected
}
else if( imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED )
{
// not affected

View file

@ -675,27 +675,6 @@ bool PPCRecompilerX64Gen_imlInstruction_store(PPCRecFunction_t* PPCRecFunction,
return false;
}
/*
* Copy byte/word/dword from memory to memory
*/
void PPCRecompilerX64Gen_imlInstruction_mem2mem(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, PPCRecImlInstruction_t* imlInstruction)
{
sint32 realSrcMemReg = tempToRealRegister(imlInstruction->op_mem2mem.src.registerMem);
sint32 realSrcMemImm = imlInstruction->op_mem2mem.src.immS32;
sint32 realDstMemReg = tempToRealRegister(imlInstruction->op_mem2mem.dst.registerMem);
sint32 realDstMemImm = imlInstruction->op_mem2mem.dst.immS32;
// PPCRecompilerX64Gen_crConditionFlags_forget() is not needed here, since MOVs don't affect eflags
if (imlInstruction->op_mem2mem.copyWidth == 32)
{
x64Emit_mov_reg32_mem32(x64GenContext, REG_RESV_TEMP, REG_R13, realSrcMemReg, realSrcMemImm);
x64Gen_movTruncate_mem32Reg64PlusReg64_reg64(x64GenContext, REG_R13, realDstMemReg, realDstMemImm, REG_RESV_TEMP);
}
else
{
assert_dbg();
}
}
bool PPCRecompilerX64Gen_imlInstruction_r_r(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, PPCRecImlInstruction_t* imlInstruction)
{
if (imlInstruction->operation == PPCREC_IML_OP_ASSIGN)
@ -2395,10 +2374,6 @@ bool PPCRecompiler_generateX64Code(PPCRecFunction_t* PPCRecFunction, ppcImlGenCo
codeGenerationFailed = true;
}
}
else if (imlInstruction->type == PPCREC_IML_TYPE_MEM2MEM)
{
PPCRecompilerX64Gen_imlInstruction_mem2mem(PPCRecFunction, ppcImlGenContext, &x64GenContext, imlInstruction);
}
else if( imlInstruction->type == PPCREC_IML_TYPE_CR )
{
if( PPCRecompilerX64Gen_imlInstruction_cr(PPCRecFunction, ppcImlGenContext, &x64GenContext, imlInstruction) == false )