Implement thumb16_{SXTH,SXTB,UXTH,UXTB,REV,REV16,REVSH}
This commit is contained in:
parent
866dce0f23
commit
3720da4e19
8 changed files with 194 additions and 8 deletions
|
@ -602,6 +602,59 @@ void EmitX64::EmitNot(IR::Value* value_) {
|
||||||
code->NOT(32, R(result));
|
code->NOT(32, R(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitSignExtendHalfToWord(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
// TODO: Remove unnecessary mov that may occur here
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->MOVSX(32, 16, result, R(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitSignExtendByteToWord(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
// TODO: Remove unnecessary mov that may occur here
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->MOVSX(32, 8, result, R(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitZeroExtendHalfToWord(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
// TODO: Remove unnecessary mov that may occur here
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->MOVZX(32, 16, result, R(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitZeroExtendByteToWord(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
// TODO: Remove unnecessary mov that may occur here
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->MOVZX(32, 8, result, R(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitByteReverseWord(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->BSWAP(32, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitByteReverseHalf(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
|
||||||
|
code->ROL(16, R(result), Imm8(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EmitX64::EmitReadMemory8(IR::Value* value_) {
|
void EmitX64::EmitReadMemory8(IR::Value* value_) {
|
||||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,12 @@ private:
|
||||||
void EmitEor(IR::Value* value);
|
void EmitEor(IR::Value* value);
|
||||||
void EmitOr(IR::Value* value);
|
void EmitOr(IR::Value* value);
|
||||||
void EmitNot(IR::Value* value);
|
void EmitNot(IR::Value* value);
|
||||||
|
void EmitSignExtendHalfToWord(IR::Value* value);
|
||||||
|
void EmitSignExtendByteToWord(IR::Value* value);
|
||||||
|
void EmitZeroExtendHalfToWord(IR::Value* value);
|
||||||
|
void EmitZeroExtendByteToWord(IR::Value* value);
|
||||||
|
void EmitByteReverseWord(IR::Value* value);
|
||||||
|
void EmitByteReverseHalf(IR::Value* value);
|
||||||
void EmitReadMemory8(IR::Value* value);
|
void EmitReadMemory8(IR::Value* value);
|
||||||
void EmitReadMemory16(IR::Value* value);
|
void EmitReadMemory16(IR::Value* value);
|
||||||
void EmitReadMemory32(IR::Value* value);
|
void EmitReadMemory32(IR::Value* value);
|
||||||
|
|
|
@ -56,7 +56,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
const std::array<Thumb16Matcher<V>, 36> g_thumb16_instruction_table = {
|
const std::array<Thumb16Matcher<V>, 43> g_thumb16_instruction_table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<Thumb16Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
#define INST(fn, name, bitstring) detail::detail<Thumb16Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
||||||
|
|
||||||
|
@ -119,17 +119,17 @@ const std::array<Thumb16Matcher<V>, 36> g_thumb16_instruction_table = {
|
||||||
// Miscellaneous 16-bit instructions
|
// Miscellaneous 16-bit instructions
|
||||||
//INST(&V::thumb16_ADD_spsp, "ADD (imm to SP)", "101100000vvvvvvv"), // v4T
|
//INST(&V::thumb16_ADD_spsp, "ADD (imm to SP)", "101100000vvvvvvv"), // v4T
|
||||||
//INST(&V::thumb16_SUB_spsp, "SUB (imm from SP)", "101100001vvvvvvv"), // v4T
|
//INST(&V::thumb16_SUB_spsp, "SUB (imm from SP)", "101100001vvvvvvv"), // v4T
|
||||||
//INST(&V::thumb16_SXTH, "SXTH", "1011001000mmmddd"), // v6
|
INST(&V::thumb16_SXTH, "SXTH", "1011001000mmmddd"), // v6
|
||||||
//INST(&V::thumb16_SXTB, "SXTB", "1011001001mmmddd"), // v6
|
INST(&V::thumb16_SXTB, "SXTB", "1011001001mmmddd"), // v6
|
||||||
//INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd"), // v6
|
INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd"), // v6
|
||||||
//INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd"), // v6
|
INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd"), // v6
|
||||||
//INST(&V::thumb16_PUSH, "PUSH", "1011010rxxxxxxxx"), // v4T
|
//INST(&V::thumb16_PUSH, "PUSH", "1011010rxxxxxxxx"), // v4T
|
||||||
//INST(&V::thumb16_POP, "POP", "1011110rxxxxxxxx"), // v4T
|
//INST(&V::thumb16_POP, "POP", "1011110rxxxxxxxx"), // 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_CPS, "CPS", "10110110011m0aif"), // v6
|
||||||
//INST(&V::thumb16_REV, "REV", "1011101000nnnddd"), // v6
|
INST(&V::thumb16_REV, "REV", "1011101000mmmddd"), // v6
|
||||||
//INST(&V::thumb16_REV16, "REV16", "1011101001nnnddd"), // v6
|
INST(&V::thumb16_REV16, "REV16", "1011101001mmmddd"), // v6
|
||||||
//INST(&V::thumb16_REVSH, "REVSH", "1011101011nnnddd"), // v6
|
INST(&V::thumb16_REVSH, "REVSH", "1011101011mmmddd"), // v6
|
||||||
//INST(&V::thumb16_BKPT, "BKPT", "10111110xxxxxxxx"), // v5
|
//INST(&V::thumb16_BKPT, "BKPT", "10111110xxxxxxxx"), // v5
|
||||||
|
|
||||||
// Store/Load multiple registers
|
// Store/Load multiple registers
|
||||||
|
|
|
@ -244,6 +244,34 @@ public:
|
||||||
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string thumb16_SXTH(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("sxth %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_SXTB(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("sxtb %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_UXTH(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("uxth %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_UXTB(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("uxtb %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_REV(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("rev %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_REV16(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("rev16 %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb16_REVSH(Reg m, Reg d) {
|
||||||
|
return Common::StringFromFormat("revsh %s, %s", RegStr(d), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
std::string thumb16_UDF() {
|
std::string thumb16_UDF() {
|
||||||
return Common::StringFromFormat("udf");
|
return Common::StringFromFormat("udf");
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,31 @@ IR::ValuePtr IREmitter::Not(IR::ValuePtr a) {
|
||||||
return Inst(IR::Opcode::Not, {a});
|
return Inst(IR::Opcode::Not, {a});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::SignExtendHalfToWord(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::SignExtendHalfToWord, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::SignExtendByteToWord(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::SignExtendByteToWord, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::ZeroExtendHalfToWord(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::ZeroExtendHalfToWord, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::ZeroExtendByteToWord(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::ZeroExtendByteToWord, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::ByteReverseWord(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::ByteReverseWord, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::ByteReverseHalf(IR::ValuePtr a) {
|
||||||
|
return Inst(IR::Opcode::ByteReverseHalf, {a});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IR::ValuePtr IREmitter::ReadMemory8(IR::ValuePtr vaddr) {
|
IR::ValuePtr IREmitter::ReadMemory8(IR::ValuePtr vaddr) {
|
||||||
return Inst(IR::Opcode::ReadMemory8, {vaddr});
|
return Inst(IR::Opcode::ReadMemory8, {vaddr});
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,12 @@ public:
|
||||||
IR::ValuePtr Eor(IR::ValuePtr a, IR::ValuePtr b);
|
IR::ValuePtr Eor(IR::ValuePtr a, IR::ValuePtr b);
|
||||||
IR::ValuePtr Or(IR::ValuePtr a, IR::ValuePtr b);
|
IR::ValuePtr Or(IR::ValuePtr a, IR::ValuePtr b);
|
||||||
IR::ValuePtr Not(IR::ValuePtr a);
|
IR::ValuePtr Not(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr SignExtendHalfToWord(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr SignExtendByteToWord(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr ZeroExtendHalfToWord(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr ZeroExtendByteToWord(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr ByteReverseWord(IR::ValuePtr a);
|
||||||
|
IR::ValuePtr ByteReverseHalf(IR::ValuePtr a);
|
||||||
|
|
||||||
IR::ValuePtr ReadMemory8(IR::ValuePtr vaddr);
|
IR::ValuePtr ReadMemory8(IR::ValuePtr vaddr);
|
||||||
IR::ValuePtr ReadMemory16(IR::ValuePtr vaddr);
|
IR::ValuePtr ReadMemory16(IR::ValuePtr vaddr);
|
||||||
|
|
|
@ -39,6 +39,12 @@ OPCODE(And, T::U32, T::U32, T::U32
|
||||||
OPCODE(Eor, T::U32, T::U32, T::U32 )
|
OPCODE(Eor, T::U32, T::U32, T::U32 )
|
||||||
OPCODE(Or, T::U32, T::U32, T::U32 )
|
OPCODE(Or, T::U32, T::U32, T::U32 )
|
||||||
OPCODE(Not, T::U32, T::U32 )
|
OPCODE(Not, T::U32, T::U32 )
|
||||||
|
OPCODE(SignExtendHalfToWord, T::U32, T::U16 )
|
||||||
|
OPCODE(SignExtendByteToWord, T::U32, T::U8 )
|
||||||
|
OPCODE(ZeroExtendHalfToWord, T::U32, T::U16 )
|
||||||
|
OPCODE(ZeroExtendByteToWord, T::U32, T::U8 )
|
||||||
|
OPCODE(ByteReverseWord, T::U32, T::U32 )
|
||||||
|
OPCODE(ByteReverseHalf, T::U16, T::U16 )
|
||||||
|
|
||||||
// Memory access
|
// Memory access
|
||||||
OPCODE(ReadMemory8, T::U8, T::U32 )
|
OPCODE(ReadMemory8, T::U8, T::U32 )
|
||||||
|
|
|
@ -440,6 +440,68 @@ struct ThumbTranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool thumb16_SXTH(Reg m, Reg d) {
|
||||||
|
// SXTH <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
auto half = ir.LeastSignificantHalf(ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, ir.SignExtendHalfToWord(half));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_SXTB(Reg m, Reg d) {
|
||||||
|
// SXTB <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
auto byte = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, ir.SignExtendByteToWord(byte));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_UXTH(Reg m, Reg d) {
|
||||||
|
// UXTH <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
auto half = ir.LeastSignificantHalf(ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, ir.ZeroExtendHalfToWord(half));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_UXTB(Reg m, Reg d) {
|
||||||
|
// UXTB <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
auto byte = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, ir.ZeroExtendByteToWord(byte));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_REV(Reg m, Reg d) {
|
||||||
|
// REV <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
ir.SetRegister(d, ir.ByteReverseWord(ir.GetRegister(m)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_REV16(Reg m, Reg d) {
|
||||||
|
// REV16 <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
// TODO: Consider optimizing
|
||||||
|
auto Rm = ir.GetRegister(m);
|
||||||
|
auto upper_half = ir.LeastSignificantHalf(ir.LogicalShiftRight(Rm, ir.Imm8(16), ir.Imm1(0)).result);
|
||||||
|
auto lower_half = ir.LeastSignificantHalf(Rm);
|
||||||
|
auto rev_upper_half = ir.ZeroExtendHalfToWord(ir.ByteReverseHalf(upper_half));
|
||||||
|
auto rev_lower_half = ir.ZeroExtendHalfToWord(ir.ByteReverseHalf(lower_half));
|
||||||
|
auto result = ir.Or(ir.LogicalShiftLeft(rev_upper_half, ir.Imm8(16), ir.Imm1(0)).result,
|
||||||
|
rev_lower_half);
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb16_REVSH(Reg m, Reg d) {
|
||||||
|
// REVSH <Rd>, <Rm>
|
||||||
|
// Rd cannot encode R15.
|
||||||
|
auto rev_half = ir.ByteReverseHalf(ir.LeastSignificantHalf(ir.GetRegister(m)));
|
||||||
|
ir.SetRegister(d, ir.SignExtendHalfToWord(rev_half));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool thumb16_UDF() {
|
bool thumb16_UDF() {
|
||||||
return InterpretThisInstruction();
|
return InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue