Implement memory endianness. Implement Thumb SETEND instruction.
This commit is contained in:
parent
98bd7ff6a5
commit
90d317b868
9 changed files with 54 additions and 9 deletions
|
@ -651,6 +651,13 @@ void EmitX64::EmitByteReverseHalf(IR::Value* value_) {
|
|||
code->ROL(16, R(result), Imm8(8));
|
||||
}
|
||||
|
||||
void EmitX64::EmitByteReverseDual(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
|
||||
code->BSWAP(64, result);
|
||||
}
|
||||
|
||||
void EmitX64::EmitReadMemory8(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
@ -922,8 +929,6 @@ void EmitX64::EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch, Arm::Loca
|
|||
}
|
||||
|
||||
void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationDescriptor initial_location) {
|
||||
ASSERT_MSG(terminal.next.EFlag == initial_location.EFlag, "Unimplemented");
|
||||
|
||||
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.arm_pc));
|
||||
if (terminal.next.TFlag != initial_location.TFlag) {
|
||||
if (terminal.next.TFlag) {
|
||||
|
@ -932,6 +937,13 @@ void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationD
|
|||
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 5)));
|
||||
}
|
||||
}
|
||||
if (terminal.next.EFlag != initial_location.EFlag) {
|
||||
if (terminal.next.EFlag) {
|
||||
code->OR(32, MJitStateCpsr(), Imm32(1 << 9));
|
||||
} else {
|
||||
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 9)));
|
||||
}
|
||||
}
|
||||
routines->GenReturnFromRunCode(code); // TODO: Check cycles, Properly do a link
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ private:
|
|||
void EmitZeroExtendByteToWord(IR::Value* value);
|
||||
void EmitByteReverseWord(IR::Value* value);
|
||||
void EmitByteReverseHalf(IR::Value* value);
|
||||
void EmitByteReverseDual(IR::Value* value);
|
||||
void EmitReadMemory8(IR::Value* value);
|
||||
void EmitReadMemory16(IR::Value* value);
|
||||
void EmitReadMemory32(IR::Value* value);
|
||||
|
|
|
@ -129,7 +129,7 @@ boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
|
|||
INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd"), // v6
|
||||
INST(&V::thumb16_PUSH, "PUSH", "1011010Mxxxxxxxx"), // v4T
|
||||
INST(&V::thumb16_POP, "POP", "1011110Pxxxxxxxx"), // v4T
|
||||
//INST(&V::thumb16_SETEND, "SETEND", "101101100101x000"), // v6
|
||||
INST(&V::thumb16_SETEND, "SETEND", "101101100101x000"), // v6
|
||||
//INST(&V::thumb16_CPS, "CPS", "10110110011m0aif"), // v6
|
||||
INST(&V::thumb16_REV, "REV", "1011101000mmmddd"), // v6
|
||||
INST(&V::thumb16_REV16, "REV16", "1011101001mmmddd"), // v6
|
||||
|
|
|
@ -359,6 +359,10 @@ public:
|
|||
return "pop " + RegListStr(reg_list);
|
||||
}
|
||||
|
||||
std::string thumb16_SETEND(bool E) {
|
||||
return Common::StringFromFormat("setend %s", E ? "BE" : "LE");
|
||||
}
|
||||
|
||||
std::string thumb16_REV(Reg m, Reg d) {
|
||||
return Common::StringFromFormat("rev %s, %s", RegStr(d), RegStr(m));
|
||||
}
|
||||
|
|
|
@ -207,21 +207,27 @@ IR::ValuePtr IREmitter::ByteReverseHalf(IR::ValuePtr a) {
|
|||
return Inst(IR::Opcode::ByteReverseHalf, {a});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ByteReverseDual(IR::ValuePtr a) {
|
||||
return Inst(IR::Opcode::ByteReverseDual, {a});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory8(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory8, {vaddr});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory16(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory16, {vaddr});
|
||||
auto value = Inst(IR::Opcode::ReadMemory16, {vaddr});
|
||||
return current_location.EFlag ? ByteReverseHalf(value) : value;
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory32(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory32, {vaddr});
|
||||
auto value = Inst(IR::Opcode::ReadMemory32, {vaddr});
|
||||
return current_location.EFlag ? ByteReverseWord(value) : value;
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory64(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory64, {vaddr});
|
||||
auto value = Inst(IR::Opcode::ReadMemory64, {vaddr});
|
||||
return current_location.EFlag ? ByteReverseDual(value) : value;
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory8(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
|
@ -229,18 +235,26 @@ void IREmitter::WriteMemory8(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
|||
}
|
||||
|
||||
void IREmitter::WriteMemory16(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
if (current_location.EFlag) {
|
||||
value = ByteReverseHalf(value);
|
||||
}
|
||||
Inst(IR::Opcode::WriteMemory16, {vaddr, value});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory32(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
if (current_location.EFlag) {
|
||||
value = ByteReverseWord(value);
|
||||
}
|
||||
Inst(IR::Opcode::WriteMemory32, {vaddr, value});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory64(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
if (current_location.EFlag) {
|
||||
value = ByteReverseDual(value);
|
||||
}
|
||||
Inst(IR::Opcode::WriteMemory64, {vaddr, value});
|
||||
}
|
||||
|
||||
|
||||
void IREmitter::SetTerm(const IR::Terminal& terminal) {
|
||||
ASSERT_MSG(block.terminal.which() == 0, "Terminal has already been set.");
|
||||
block.terminal = terminal;
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
IR::ValuePtr ZeroExtendByteToWord(IR::ValuePtr a);
|
||||
IR::ValuePtr ByteReverseWord(IR::ValuePtr a);
|
||||
IR::ValuePtr ByteReverseHalf(IR::ValuePtr a);
|
||||
IR::ValuePtr ByteReverseDual(IR::ValuePtr a);
|
||||
|
||||
IR::ValuePtr ReadMemory8(IR::ValuePtr vaddr);
|
||||
IR::ValuePtr ReadMemory16(IR::ValuePtr vaddr);
|
||||
|
|
|
@ -45,6 +45,7 @@ OPCODE(ZeroExtendHalfToWord, T::U32, T::U16
|
|||
OPCODE(ZeroExtendByteToWord, T::U32, T::U8 )
|
||||
OPCODE(ByteReverseWord, T::U32, T::U32 )
|
||||
OPCODE(ByteReverseHalf, T::U16, T::U16 )
|
||||
OPCODE(ByteReverseDual, T::U64, T::U64 )
|
||||
|
||||
// Memory access
|
||||
OPCODE(ReadMemory8, T::U8, T::U32 )
|
||||
|
|
|
@ -676,6 +676,18 @@ struct ThumbTranslatorVisitor final {
|
|||
}
|
||||
}
|
||||
|
||||
bool thumb16_SETEND(bool E) {
|
||||
// SETEND <endianness>
|
||||
if (E == ir.current_location.EFlag) {
|
||||
return true;
|
||||
}
|
||||
auto next_location = ir.current_location;
|
||||
next_location.arm_pc += 2;
|
||||
next_location.EFlag = E;
|
||||
ir.SetTerm(IR::Term::LinkBlock{next_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool thumb16_REV(Reg m, Reg d) {
|
||||
// REV <Rd>, <Rm>
|
||||
// Rd cannot encode R15.
|
||||
|
|
|
@ -247,7 +247,7 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
|
|||
}
|
||||
|
||||
TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") {
|
||||
const std::array<ThumbInstGen, 24> instructions = {{
|
||||
const std::array<ThumbInstGen, 25> instructions = {{
|
||||
ThumbInstGen("00000xxxxxxxxxxx"), // LSL <Rd>, <Rm>, #<imm5>
|
||||
ThumbInstGen("00001xxxxxxxxxxx"), // LSR <Rd>, <Rm>, #<imm5>
|
||||
ThumbInstGen("00010xxxxxxxxxxx"), // ASR <Rd>, <Rm>, #<imm5>
|
||||
|
@ -276,7 +276,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") {
|
|||
ThumbInstGen("10111100xxxxxxxx", // POP (P = 0)
|
||||
[](u16 inst){ return Dynarmic::Common::Bits<0, 7>(inst) != 0; }), // Empty reg_list is UNPREDICTABLE
|
||||
ThumbInstGen("1100xxxxxxxxxxxx"), // STMIA/LDMIA
|
||||
//ThumbInstGen("101101100101x000"), // SETEND
|
||||
ThumbInstGen("101101100101x000"), // SETEND
|
||||
}};
|
||||
|
||||
auto instruction_select = [&]() -> u16 {
|
||||
|
|
Loading…
Reference in a new issue