Misc accumulated Jit64IL work; I don't recall whether any of these

changes individually led to perf improvements, although overall it's 
spending a lot less time in interpreter fallbacks.



git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1904 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
magumagu9 2009-01-17 22:22:54 +00:00
parent 9cb25d6ba2
commit ee2bf31e56
9 changed files with 184 additions and 83 deletions

View File

@ -38,7 +38,7 @@
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// ¯¯¯¯¯¯¯¯¯¯
#ifdef JITTEST
#if JITTEST
#include "../Jit64IL/Jit.h"
#else

View File

@ -1197,11 +1197,9 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
case RFIExit:
case InterpreterBranch:
case IdleLoop:
// No liveness effects
break;
case ShortIdleLoop:
case Tramp:
if (thisUsed)
regMarkUse(RI, I, I - 1 - (*I >> 8), 1);
// No liveness effects
break;
case SExt8:
case SExt16:
@ -1232,6 +1230,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
break;
case StoreCR:
case StoreCarry:
case StoreFPRF:
regMarkUse(RI, I, getOp1(I), 1);
break;
case StoreGReg:
@ -1277,6 +1276,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
case FPMerge01:
case FPMerge10:
case FPMerge11:
case FDCmpCR:
case InsertDoubleInMReg:
if (thisUsed) {
regMarkUse(RI, I, getOp1(I), 1);
@ -1411,6 +1411,15 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
regNormalRegClear(RI, I);
break;
}
case StoreFPRF: {
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp1(I)));
Jit->AND(32, R(ECX), Imm8(0x1F));
Jit->SHL(32, R(ECX), Imm8(12));
Jit->AND(32, M(&FPSCR), Imm32(~(0x1F << 12)));
Jit->OR(32, M(&FPSCR), R(ECX));
regNormalRegClear(RI, I);
break;
}
case Load8: {
regEmitMemLoad(RI, I, 8);
break;
@ -1851,6 +1860,35 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
fregEmitBinInst(RI, I, &Jit64::SUBSD);
break;
}
case FDCmpCR: {
X64Reg destreg = regFindFreeReg(RI);
// TODO: Add case for NaN (CC_P)
Jit->MOVSD(XMM0, fregLocForInst(RI, getOp1(I)));
Jit->UCOMISD(XMM0, fregLocForInst(RI, getOp2(I)));
FixupBranch pNan = Jit->J_CC(CC_P);
FixupBranch pEqual = Jit->J_CC(CC_Z);
FixupBranch pLesser = Jit->J_CC(CC_C);
// Greater
Jit->MOV(32, R(destreg), Imm32(0x4));
FixupBranch continue1 = Jit->J();
// NaN
Jit->SetJumpTarget(pNan);
Jit->MOV(32, R(destreg), Imm32(0x1));
FixupBranch continue2 = Jit->J();
// Equal
Jit->SetJumpTarget(pEqual);
Jit->MOV(32, R(destreg), Imm32(0x2));
FixupBranch continue3 = Jit->J();
// Less
Jit->SetJumpTarget(pLesser);
Jit->MOV(32, R(destreg), Imm32(0x8));
Jit->SetJumpTarget(continue1);
Jit->SetJumpTarget(continue2);
Jit->SetJumpTarget(continue3);
RI.regs[destreg] = I;
fregNormalRegClear(RI, I);
break;
}
case FPAdd: {
if (!thisUsed) break;
fregEmitBinInst(RI, I, &Jit64::ADDPS);
@ -1962,7 +2000,14 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
unsigned IdleParam = ibuild->GetImmValue(getOp1(I));
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
Jit->ABI_CallFunctionC((void *)&PowerPC::OnIdle, IdleParam);
Jit->MOV(32, M(&PowerPC::ppcState.pc), Imm32(InstLoc + 12));
Jit->MOV(32, M(&PC), Imm32(InstLoc + 12));
Jit->JMP(asm_routines.testExceptions, true);
break;
}
case ShortIdleLoop: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->ABI_CallFunction((void *)&CoreTiming::Idle);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->JMP(asm_routines.testExceptions, true);
break;
}
@ -1998,25 +2043,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
Jit->WriteRfiExitDestInEAX();
break;
}
case Tramp: {
if (!thisUsed) break;
// FIXME: Optimize!
InstLoc Op = I - 1 - (*I >> 8);
if (isFResult(*Op)) {
X64Reg reg = fregFindFreeReg(RI);
Jit->MOVAPD(reg, fregLocForInst(RI, Op));
RI.fregs[reg] = I;
if (RI.IInfo[I - RI.FirstI] & 4)
fregClearInst(RI, Op);
} else {
X64Reg reg = regFindFreeReg(RI);
Jit->MOV(32, R(reg), regLocForInst(RI, Op));
RI.regs[reg] = I;
if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, Op);
}
break;
}
case Tramp: break;
case Nop: break;
default:
PanicAlert("Unknown JIT instruction; aborting!");
@ -2034,7 +2061,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
}
}
if (UseProfile && RI.numSpills)
if (!RI.MakeProfile && RI.numSpills)
printf("Block: %x, numspills %d\n", Jit->js.blockStart, RI.numSpills);
Jit->UD2();

View File

@ -54,6 +54,7 @@ namespace IREmitter {
StoreCarry,
StoreCTR,
StoreMSR,
StoreFPRF,
// Arbitrary interpreter instruction
InterpreterFallback,
@ -184,6 +185,7 @@ namespace IREmitter {
StoreSingle,
StoreDouble,
StoreFReg,
FDCmpCR,
// "Trinary" operators
// FIXME: Need to change representation!
@ -197,7 +199,9 @@ namespace IREmitter {
SystemCall,
RFIExit,
InterpreterBranch,
IdleLoop,
IdleLoop, // The "usual" idle loop, load+compare+branch
ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong,
// just a branch
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
@ -227,11 +231,19 @@ namespace IREmitter {
}
InstLoc inline getOp1(InstLoc i) {
return i - 1 - ((*i >> 8) & 255);
i = i - 1 - ((*i >> 8) & 255);
if (getOpcode(*i) == Tramp) {
i = i - 1 - (*i >> 8);
}
return i;
}
InstLoc inline getOp2(InstLoc i) {
return i - 1 - ((*i >> 16) & 255);
i = i - 1 - ((*i >> 16) & 255);
if (getOpcode(*i) == Tramp) {
i = i - 1 - (*i >> 8);
}
return i;
}
class IRBuilder {
@ -288,6 +300,9 @@ namespace IREmitter {
InstLoc EmitStoreMSR(InstLoc val) {
return FoldUOp(StoreMSR, val);
}
InstLoc EmitStoreFPRF(InstLoc value) {
return FoldUOp(StoreFPRF, value);
}
InstLoc EmitLoadGReg(unsigned reg) {
return FoldZeroOp(LoadGReg, reg);
}
@ -390,6 +405,9 @@ namespace IREmitter {
InstLoc EmitInterpreterBranch() {
return FoldZeroOp(InterpreterBranch, 0);
}
InstLoc EmitLoadCarry() {
return FoldZeroOp(LoadCarry, 0);
}
InstLoc EmitStoreCarry(InstLoc op1) {
return FoldUOp(StoreCarry, op1);
}
@ -402,6 +420,9 @@ namespace IREmitter {
InstLoc EmitIdleLoop(InstLoc idleParam, InstLoc pc) {
return FoldBiOp(IdleLoop, idleParam, pc);
}
InstLoc EmitShortIdleLoop(InstLoc pc) {
return FoldUOp(ShortIdleLoop, pc);
}
InstLoc EmitLoadSingle(InstLoc addr) {
return FoldUOp(LoadSingle, addr);
}
@ -498,6 +519,9 @@ namespace IREmitter {
InstLoc EmitDoubleToSingle(InstLoc op1) {
return FoldUOp(DoubleToSingle, op1);
}
InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) {
return FoldBiOp(FDCmpCR, op1, op2);
}
void StartBackPass() { curReadPtr = &InstList[InstList.size()]; }
void StartForwardPass() { curReadPtr = &InstList[0]; }

View File

@ -280,11 +280,8 @@ public:
void subfx(UGeckoInstruction inst);
void subfex(UGeckoInstruction inst);
void lbzx(UGeckoInstruction inst);
void lwzx(UGeckoInstruction inst);
void lXzx(UGeckoInstruction inst);
void lhax(UGeckoInstruction inst);
void lwzux(UGeckoInstruction inst);
void stXx(UGeckoInstruction inst);

View File

@ -68,6 +68,11 @@ using namespace Gen;
else
destination = js.compilerPC + SignExt26(inst.LI << 2);
if (destination == js.compilerPC) {
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
@ -109,7 +114,8 @@ using namespace Gen;
}
if (!Test) {
PanicAlert("Unconditional conditional branch?!");
Test = ibuild.EmitIntConst(1);
//PanicAlert("Unconditional conditional branch?!");
}
u32 destination;

View File

@ -28,7 +28,7 @@
void Jit64::fp_arith_s(UGeckoInstruction inst)
{
if (inst.Rc || inst.OPCD != 59 || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
@ -61,22 +61,24 @@
void Jit64::fmaddXX(UGeckoInstruction inst)
{
if (inst.Rc || inst.OPCD != 59) {
if (inst.Rc) {
Default(inst); return;
}
bool single_precision = inst.OPCD == 59;
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitFSMul(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FC)));
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
if (inst.SUBOP5 & 1)
val = ibuild.EmitFSAdd(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FB)));
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
else
val = ibuild.EmitFSSub(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FB)));
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
if (inst.SUBOP5 & 2)
val = ibuild.EmitFSNeg(val);
val = ibuild.EmitDupSingleToMReg(val);
val = ibuild.EmitFDNeg(val);
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
@ -92,6 +94,11 @@
void Jit64::fcmpx(UGeckoInstruction inst)
{
Default(inst);
return;
printf("fcmpx at %x\n", js.compilerPC);
IREmitter::InstLoc lhs, rhs, res;
lhs = ibuild.EmitLoadFReg(inst.FA);
rhs = ibuild.EmitLoadFReg(inst.FB);
res = ibuild.EmitFDCmpCR(lhs, rhs);
ibuild.EmitStoreFPRF(res);
ibuild.EmitStoreCR(res, inst.CRFD);
}

View File

@ -211,19 +211,21 @@
void Jit64::subfex(UGeckoInstruction inst)
{
INSTRUCTION_START;
Default(inst);
return;
/*
u32 a = m_GPR[_inst.RA];
u32 b = m_GPR[_inst.RB];
int carry = GetCarry();
m_GPR[_inst.RD] = (~a) + b + carry;
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
if (_inst.OE) PanicAlert("OE: subfcx");
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
*/
if (inst.OE) PanicAlert("OE: subfex");
IREmitter::InstLoc val, test, lhs, rhs, carry;
rhs = ibuild.EmitLoadGReg(inst.RA);
carry = ibuild.EmitLoadCarry();
rhs = ibuild.EmitXor(rhs, ibuild.EmitIntConst(-1));
rhs = ibuild.EmitAdd(rhs, carry);
test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0));
test = ibuild.EmitAnd(test, carry);
lhs = ibuild.EmitLoadGReg(inst.RB);
val = ibuild.EmitAdd(lhs, rhs);
ibuild.EmitStoreGReg(val, inst.RD);
test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val));
ibuild.EmitStoreCarry(test);
if (inst.Rc)
ComputeRC(ibuild, val);
}
void Jit64::subfx(UGeckoInstruction inst)

View File

@ -39,24 +39,6 @@
//#define INSTRUCTION_START Default(inst); return;
#define INSTRUCTION_START
void Jit64::lbzx(UGeckoInstruction inst)
{
INSTRUCTION_START
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
ibuild.EmitStoreGReg(ibuild.EmitLoad8(addr), inst.RD);
}
void Jit64::lwzx(UGeckoInstruction inst)
{
INSTRUCTION_START
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
ibuild.EmitStoreGReg(ibuild.EmitLoad32(addr), inst.RD);
}
void Jit64::lhax(UGeckoInstruction inst)
{
INSTRUCTION_START
@ -113,15 +95,24 @@ void Jit64::lha(UGeckoInstruction inst)
ibuild.EmitStoreGReg(val, inst.RD);
}
void Jit64::lwzux(UGeckoInstruction inst)
void Jit64::lXzx(UGeckoInstruction inst)
{
INSTRUCTION_START
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA) {
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
ibuild.EmitStoreGReg(addr, inst.RA);
if (inst.SUBOP10 & 32)
ibuild.EmitStoreGReg(addr, inst.RA);
}
ibuild.EmitStoreGReg(ibuild.EmitLoad32(addr), inst.RD);
IREmitter::InstLoc val;
switch (inst.SUBOP10 & ~32)
{
default: PanicAlert("lXzx: invalid access size");
case 23: val = ibuild.EmitLoad32(addr); break; //lwzx
case 279: val = ibuild.EmitLoad16(addr); break; //lhzx
case 87: val = ibuild.EmitLoad8(addr); break; //lbzx
}
ibuild.EmitStoreGReg(val, inst.RD);
}
// Zero cache line.
@ -183,10 +174,28 @@ void Jit64::stXx(UGeckoInstruction inst)
// A few games use these heavily in video codecs.
void Jit64::lmw(UGeckoInstruction inst)
{
Default(inst); return;
INSTRUCTION_START
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoad32(addr);
ibuild.EmitStoreGReg(val, i);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}
void Jit64::stmw(UGeckoInstruction inst)
{
Default(inst); return;
INSTRUCTION_START
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoadGReg(i);
ibuild.EmitStore32(val, addr);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}

View File

@ -167,12 +167,21 @@ static GekkoOPTemplate primarytable[] =
{28, Interpreter::andi_rc, &Jit64::reg_imm, {"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, Interpreter::andis_rc, &Jit64::reg_imm, {"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
#if JITTEST
{32, Interpreter::lwz, &Jit64::lXz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, Interpreter::lwzu, &Jit64::lXz, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{34, Interpreter::lbz, &Jit64::lXz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{35, Interpreter::lbzu, &Jit64::lXz, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{40, Interpreter::lhz, &Jit64::lXz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{41, Interpreter::lhzu, &Jit64::lXz, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
#else
{32, Interpreter::lwz, &Jit64::lXz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, Interpreter::lwzu, &Jit64::Default, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{34, Interpreter::lbz, &Jit64::lXz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{35, Interpreter::lbzu, &Jit64::Default, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{40, Interpreter::lhz, &Jit64::lXz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{41, Interpreter::lhzu, &Jit64::Default, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
#endif
{42, Interpreter::lha, &Jit64::lha, {"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{43, Interpreter::lhau, &Jit64::Default, {"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
@ -302,13 +311,33 @@ static GekkoOPTemplate table31[] =
{24, Interpreter::slwx, &Jit64::slwx, {"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, Interpreter::dcbst, &Jit64::Default, {"dcbst", OPTYPE_DCACHE, 0, 4}},
#if JITTEST
{86, Interpreter::dcbf, &Jit64::DoNothing, {"dcbf", OPTYPE_DCACHE, 0, 4}},
#else
{86, Interpreter::dcbf, &Jit64::Default, {"dcbf", OPTYPE_DCACHE, 0, 4}},
#endif
{246, Interpreter::dcbtst, &Jit64::Default, {"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, Interpreter::dcbt, &Jit64::Default, {"dcbt", OPTYPE_DCACHE, 0, 1}},
{470, Interpreter::dcbi, &Jit64::Default, {"dcbi", OPTYPE_DCACHE, 0, 4}},
{758, Interpreter::dcba, &Jit64::Default, {"dcba", OPTYPE_DCACHE, 0, 4}},
{1014, Interpreter::dcbz, &Jit64::dcbz, {"dcbz", OPTYPE_DCACHE, 0, 4}},
#if JITTEST
//load word
{23, Interpreter::lwzx, &Jit64::lXzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{55, Interpreter::lwzux, &Jit64::lXzx, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword
{279, Interpreter::lhzx, &Jit64::lXzx, {"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{311, Interpreter::lhzux, &Jit64::lXzx, {"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword signextend
{343, Interpreter::lhax, &Jit64::lhax, {"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{375, Interpreter::lhaux, &Jit64::Default, {"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load byte
{87, Interpreter::lbzx, &Jit64::lXzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{119, Interpreter::lbzux, &Jit64::lXzx, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
#else
//load word
{23, Interpreter::lwzx, &Jit64::lwzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{55, Interpreter::lwzux, &Jit64::lwzux, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
@ -324,7 +353,7 @@ static GekkoOPTemplate table31[] =
//load byte
{87, Interpreter::lbzx, &Jit64::lbzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{119, Interpreter::lbzux, &Jit64::Default, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
#endif
//load byte reverse
{534, Interpreter::lwbrx, &Jit64::Default, {"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{790, Interpreter::lhbrx, &Jit64::Default, {"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},