lhbrx/lwbrx/ldbrx/sthbrx/stwbrx/stdbrx

This commit is contained in:
Ben Vanik 2013-10-19 21:05:06 -07:00
parent d60cf676c3
commit d62e8aaf78
4 changed files with 181 additions and 34 deletions

View File

@ -413,33 +413,75 @@ XEDISASMR(stwx, 0x7C00012E, X )(InstrData& i, InstrDisasm& d) {
// Integer load and store with byte reverse (A-1 // Integer load and store with byte reverse (A-1
XEDISASMR(lhbrx, 0x7C00062C, X )(InstrData& i, InstrDisasm& d) { XEDISASMR(lhbrx, 0x7C00062C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("lhbrx", "Load Halfword Byte-Reverse Indexed", 0);
return 1; 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) { XEDISASMR(lwbrx, 0x7C00042C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("lwbrx", "Load Word Byte-Reverse Indexed", 0);
return 1; 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) { XEDISASMR(ldbrx, 0x7C000428, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("ldbrx", "Load Doubleword Byte-Reverse Indexed", 0);
return 1; 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) { XEDISASMR(sthbrx, 0x7C00072C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("sthbrx", "Store Halfword Byte-Reverse Indexed", 0);
return 1; 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) { XEDISASMR(stwbrx, 0x7C00052C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("stwbrx", "Store Word Byte-Reverse Indexed", 0);
return 1; 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) { XEDISASMR(stdbrx, 0x7C000528, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED(); d.Init("stdbrx", "Store Doubleword Byte-Reverse Indexed", 0);
return 1; 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();
} }

View File

@ -911,33 +911,125 @@ XEEMITTER(stwx, 0x7C00012E, X )(X64Emitter& e, X86Compiler& c, InstrDat
// Integer load and store with byte reverse (A-1 // Integer load and store with byte reverse (A-1
XEEMITTER(lhbrx, 0x7C00062C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { XEEMITTER(lhbrx, 0x7C00062C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(lwbrx, 0x7C00042C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(ldbrx, 0x7C000428, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(sthbrx, 0x7C00072C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stwbrx, 0x7C00052C, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stdbrx, 0x7C000528, X )(X64Emitter& e, X86Compiler& c, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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;
} }

View File

@ -1874,7 +1874,7 @@ GpVar X64Emitter::TouchMemoryAddress(uint32_t cia, GpVar& addr) {
uint64_t X64Emitter::reserved_addr_ = 0; uint64_t X64Emitter::reserved_addr_ = 0;
GpVar X64Emitter::ReadMemory( 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_; X86Compiler& c = compiler_;
// Rebase off of memory base pointer. // Rebase off of memory base pointer.
@ -1900,16 +1900,22 @@ GpVar X64Emitter::ReadMemory(
case 2: case 2:
c.mov(value.r16(), word_ptr(real_address)); c.mov(value.r16(), word_ptr(real_address));
c.and_(value, imm(0xFFFF)); c.and_(value, imm(0xFFFF));
if (bswap) {
c.xchg(value.r8Lo(), value.r8Hi()); c.xchg(value.r8Lo(), value.r8Hi());
}
break; break;
case 4: case 4:
c.mov(value.r32(), dword_ptr(real_address)); c.mov(value.r32(), dword_ptr(real_address));
// No need to and -- the mov to e*x will extend for us. // No need to and -- the mov to e*x will extend for us.
if (bswap) {
c.bswap(value.r32()); c.bswap(value.r32());
}
break; break;
case 8: case 8:
c.mov(value, qword_ptr(real_address)); c.mov(value, qword_ptr(real_address));
if (bswap) {
c.bswap(value.r64()); c.bswap(value.r64());
}
break; break;
default: default:
XEASSERTALWAYS(); XEASSERTALWAYS();
@ -1922,7 +1928,7 @@ GpVar X64Emitter::ReadMemory(
void X64Emitter::WriteMemory( void X64Emitter::WriteMemory(
uint32_t cia, GpVar& addr, uint32_t size, GpVar& value, uint32_t cia, GpVar& addr, uint32_t size, GpVar& value,
bool release) { bool release, bool bswap) {
X86Compiler& c = compiler_; X86Compiler& c = compiler_;
// Rebase off of memory base pointer. // Rebase off of memory base pointer.
@ -1961,19 +1967,25 @@ void X64Emitter::WriteMemory(
case 2: case 2:
tmp = c.newGpVar(); tmp = c.newGpVar();
c.mov(tmp, value); c.mov(tmp, value);
if (bswap) {
c.xchg(tmp.r8Lo(), tmp.r8Hi()); c.xchg(tmp.r8Lo(), tmp.r8Hi());
}
c.mov(word_ptr(real_address), tmp.r16()); c.mov(word_ptr(real_address), tmp.r16());
break; break;
case 4: case 4:
tmp = c.newGpVar(); tmp = c.newGpVar();
c.mov(tmp, value); c.mov(tmp, value);
if (bswap) {
c.bswap(tmp.r32()); c.bswap(tmp.r32());
}
c.mov(dword_ptr(real_address), tmp.r32()); c.mov(dword_ptr(real_address), tmp.r32());
break; break;
case 8: case 8:
tmp = c.newGpVar(); tmp = c.newGpVar();
c.mov(tmp, value); c.mov(tmp, value);
if (bswap) {
c.bswap(tmp.r64()); c.bswap(tmp.r64());
}
c.mov(qword_ptr(real_address), tmp.r64()); c.mov(qword_ptr(real_address), tmp.r64());
break; break;
default: default:

View File

@ -104,10 +104,11 @@ public:
AsmJit::GpVar TouchMemoryAddress(uint32_t cia, AsmJit::GpVar& addr); AsmJit::GpVar TouchMemoryAddress(uint32_t cia, AsmJit::GpVar& addr);
AsmJit::GpVar ReadMemory( 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( void WriteMemory(
uint32_t cia, AsmJit::GpVar& addr, uint32_t size, AsmJit::GpVar& value, 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); void ByteSwapXmm(AsmJit::XmmVar& value);
AsmJit::XmmVar ReadMemoryXmm( AsmJit::XmmVar ReadMemoryXmm(
uint32_t cia, AsmJit::GpVar& addr, uint32_t alignment); uint32_t cia, AsmJit::GpVar& addr, uint32_t alignment);