lhbrx/lwbrx/ldbrx/sthbrx/stwbrx/stdbrx
This commit is contained in:
parent
d60cf676c3
commit
d62e8aaf78
|
@ -413,33 +413,75 @@ XEDISASMR(stwx, 0x7C00012E, X )(InstrData& i, InstrDisasm& d) {
|
|||
// Integer load and store with byte reverse (A-1
|
||||
|
||||
XEDISASMR(lhbrx, 0x7C00062C, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("lhbrx", "Load Halfword Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
XEDISASMR(lwbrx, 0x7C00042C, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("lwbrx", "Load Word Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
XEDISASMR(ldbrx, 0x7C000428, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("ldbrx", "Load Doubleword Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
XEDISASMR(sthbrx, 0x7C00072C, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("sthbrx", "Store Halfword Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
XEDISASMR(stwbrx, 0x7C00052C, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("stwbrx", "Store Word Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
XEDISASMR(stdbrx, 0x7C000528, X )(InstrData& i, InstrDisasm& d) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
d.Init("stdbrx", "Store Doubleword Byte-Reverse Indexed", 0);
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
|
||||
if (i.X.RA) {
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||
} else {
|
||||
d.AddUImmOperand(0, 1);
|
||||
}
|
||||
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||
return d.Finish();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -911,33 +911,125 @@ XEEMITTER(stwx, 0x7C00012E, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// Integer load and store with byte reverse (A-1
|
||||
|
||||
XEEMITTER(lhbrx, 0x7C00062C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// RT <- i48.0 || bswap(MEM(EA, 2))
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.ReadMemory(i.address, ea, 2, false, false);
|
||||
// Zero extend done by ReadMemory.
|
||||
e.update_gpr_value(i.X.RT, v);
|
||||
|
||||
e.clear_constant_gpr_value(i.X.RT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(lwbrx, 0x7C00042C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// RT <- i32.0 || bswap(MEM(EA, 4))
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.ReadMemory(i.address, ea, 4, false, false);
|
||||
// Zero extend done by ReadMemory.
|
||||
e.update_gpr_value(i.X.RT, v);
|
||||
|
||||
e.clear_constant_gpr_value(i.X.RT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(ldbrx, 0x7C000428, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// RT <- bswap(MEM(EA, 8))
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.ReadMemory(i.address, ea, 8, false, false);
|
||||
e.update_gpr_value(i.X.RT, v);
|
||||
|
||||
e.clear_constant_gpr_value(i.X.RT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(sthbrx, 0x7C00072C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// MEM(EA, 2) <- bswap((RS)[48:63])
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.D.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.gpr_value(i.X.RT);
|
||||
e.WriteMemory(i.address, ea, 2, v, false, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(stwbrx, 0x7C00052C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// MEM(EA, 4) <- bswap((RS)[32:63])
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.gpr_value(i.X.RT);
|
||||
e.WriteMemory(i.address, ea, 4, v, false, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(stdbrx, 0x7C000528, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
XEINSTRNOTIMPLEMENTED();
|
||||
return 1;
|
||||
// if RA = 0 then
|
||||
// b <- 0
|
||||
// else
|
||||
// b <- (RA)
|
||||
// EA <- b + (RB)
|
||||
// MEM(EA, 8) <- bswap(RS)
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
c.add(ea, e.gpr_value(i.X.RA));
|
||||
}
|
||||
GpVar v = e.gpr_value(i.X.RT);
|
||||
e.WriteMemory(i.address, ea, 8, v, false, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1874,7 +1874,7 @@ GpVar X64Emitter::TouchMemoryAddress(uint32_t cia, GpVar& addr) {
|
|||
uint64_t X64Emitter::reserved_addr_ = 0;
|
||||
|
||||
GpVar X64Emitter::ReadMemory(
|
||||
uint32_t cia, GpVar& addr, uint32_t size, bool acquire) {
|
||||
uint32_t cia, GpVar& addr, uint32_t size, bool acquire, bool bswap) {
|
||||
X86Compiler& c = compiler_;
|
||||
|
||||
// Rebase off of memory base pointer.
|
||||
|
@ -1900,16 +1900,22 @@ GpVar X64Emitter::ReadMemory(
|
|||
case 2:
|
||||
c.mov(value.r16(), word_ptr(real_address));
|
||||
c.and_(value, imm(0xFFFF));
|
||||
c.xchg(value.r8Lo(), value.r8Hi());
|
||||
if (bswap) {
|
||||
c.xchg(value.r8Lo(), value.r8Hi());
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
c.mov(value.r32(), dword_ptr(real_address));
|
||||
// No need to and -- the mov to e*x will extend for us.
|
||||
c.bswap(value.r32());
|
||||
if (bswap) {
|
||||
c.bswap(value.r32());
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
c.mov(value, qword_ptr(real_address));
|
||||
c.bswap(value.r64());
|
||||
if (bswap) {
|
||||
c.bswap(value.r64());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
|
@ -1922,7 +1928,7 @@ GpVar X64Emitter::ReadMemory(
|
|||
|
||||
void X64Emitter::WriteMemory(
|
||||
uint32_t cia, GpVar& addr, uint32_t size, GpVar& value,
|
||||
bool release) {
|
||||
bool release, bool bswap) {
|
||||
X86Compiler& c = compiler_;
|
||||
|
||||
// Rebase off of memory base pointer.
|
||||
|
@ -1961,19 +1967,25 @@ void X64Emitter::WriteMemory(
|
|||
case 2:
|
||||
tmp = c.newGpVar();
|
||||
c.mov(tmp, value);
|
||||
c.xchg(tmp.r8Lo(), tmp.r8Hi());
|
||||
if (bswap) {
|
||||
c.xchg(tmp.r8Lo(), tmp.r8Hi());
|
||||
}
|
||||
c.mov(word_ptr(real_address), tmp.r16());
|
||||
break;
|
||||
case 4:
|
||||
tmp = c.newGpVar();
|
||||
c.mov(tmp, value);
|
||||
c.bswap(tmp.r32());
|
||||
if (bswap) {
|
||||
c.bswap(tmp.r32());
|
||||
}
|
||||
c.mov(dword_ptr(real_address), tmp.r32());
|
||||
break;
|
||||
case 8:
|
||||
tmp = c.newGpVar();
|
||||
c.mov(tmp, value);
|
||||
c.bswap(tmp.r64());
|
||||
if (bswap) {
|
||||
c.bswap(tmp.r64());
|
||||
}
|
||||
c.mov(qword_ptr(real_address), tmp.r64());
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -104,10 +104,11 @@ public:
|
|||
|
||||
AsmJit::GpVar TouchMemoryAddress(uint32_t cia, AsmJit::GpVar& addr);
|
||||
AsmJit::GpVar ReadMemory(
|
||||
uint32_t cia, AsmJit::GpVar& addr, uint32_t size, bool acquire = false);
|
||||
uint32_t cia, AsmJit::GpVar& addr, uint32_t size, bool acquire = false,
|
||||
bool bswap = true);
|
||||
void WriteMemory(
|
||||
uint32_t cia, AsmJit::GpVar& addr, uint32_t size, AsmJit::GpVar& value,
|
||||
bool release = false);
|
||||
bool release = false, bool bswap = true);
|
||||
void ByteSwapXmm(AsmJit::XmmVar& value);
|
||||
AsmJit::XmmVar ReadMemoryXmm(
|
||||
uint32_t cia, AsmJit::GpVar& addr, uint32_t alignment);
|
||||
|
|
Loading…
Reference in New Issue