Implement thumb1_STR_reg, thumb1_STRH_reg, thumb1_STRB_reg
This commit is contained in:
parent
e7922e4fef
commit
1410221b47
9 changed files with 60 additions and 6 deletions
|
@ -223,10 +223,18 @@ void EmitX64::EmitGetOverflowFromOp(IR::Value*) {
|
||||||
ASSERT_MSG(0, "should never happen");
|
ASSERT_MSG(0, "should never happen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitLeastSignificantHalf(IR::Value* value_) {
|
||||||
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
|
// TODO: Optimize
|
||||||
|
|
||||||
|
reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitX64::EmitLeastSignificantByte(IR::Value* value_) {
|
void EmitX64::EmitLeastSignificantByte(IR::Value* value_) {
|
||||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||||
|
|
||||||
// TODO: Flag optimization
|
// TODO: Optimize
|
||||||
|
|
||||||
reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
void EmitSetVFlag(IR::Value* value);
|
void EmitSetVFlag(IR::Value* value);
|
||||||
void EmitGetCarryFromOp(IR::Value* value);
|
void EmitGetCarryFromOp(IR::Value* value);
|
||||||
void EmitGetOverflowFromOp(IR::Value* value);
|
void EmitGetOverflowFromOp(IR::Value* value);
|
||||||
|
void EmitLeastSignificantHalf(IR::Value* value);
|
||||||
void EmitLeastSignificantByte(IR::Value* value);
|
void EmitLeastSignificantByte(IR::Value* value);
|
||||||
void EmitMostSignificantBit(IR::Value* value);
|
void EmitMostSignificantBit(IR::Value* value);
|
||||||
void EmitIsZero(IR::Value* value);
|
void EmitIsZero(IR::Value* value);
|
||||||
|
|
|
@ -56,7 +56,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
static const std::array<Thumb1Matcher<V>, 32> g_thumb1_instruction_table {{
|
static const std::array<Thumb1Matcher<V>, 35> g_thumb1_instruction_table {{
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<Thumb1Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
#define INST(fn, name, bitstring) detail::detail<Thumb1Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
||||||
|
|
||||||
|
@ -98,9 +98,9 @@ static const std::array<Thumb1Matcher<V>, 32> g_thumb1_instruction_table {{
|
||||||
|
|
||||||
// Store/Load single data item instructions
|
// Store/Load single data item instructions
|
||||||
{ INST(&V::thumb1_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") },
|
{ INST(&V::thumb1_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") },
|
||||||
//{ INST(&V::thumb1_STR_rrr, "STR (rrr)", "0101000mmmnnnddd") },
|
{ INST(&V::thumb1_STR_reg, "STR (reg)", "0101000mmmnnnttt") },
|
||||||
//{ INST(&V::thumb1_STRH_rrr, "STRH (rrr)", "0101001mmmnnnddd") },
|
{ INST(&V::thumb1_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") },
|
||||||
//{ INST(&V::thumb1_STRB_rrr, "STRB (rrr)", "0101010mmmnnnddd") },
|
{ INST(&V::thumb1_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") },
|
||||||
//{ INST(&V::thumb1_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") },
|
//{ INST(&V::thumb1_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") },
|
||||||
//{ INST(&V::thumb1_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") },
|
//{ INST(&V::thumb1_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") },
|
||||||
//{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") },
|
//{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") },
|
||||||
|
|
|
@ -227,6 +227,18 @@ public:
|
||||||
return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32);
|
return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string thumb1_STR_reg(Reg m, Reg n, Reg t) {
|
||||||
|
return Common::StringFromFormat("str %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb1_STRH_reg(Reg m, Reg n, Reg t) {
|
||||||
|
return Common::StringFromFormat("strh %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string thumb1_STRB_reg(Reg m, Reg n, Reg t) {
|
||||||
|
return Common::StringFromFormat("strb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m));
|
||||||
|
}
|
||||||
|
|
||||||
std::string thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
std::string thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 2;
|
u32 imm32 = imm5 << 2;
|
||||||
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
||||||
|
|
|
@ -23,6 +23,7 @@ OPCODE(GetCarryFromOp, T::U1, T::U32
|
||||||
OPCODE(GetOverflowFromOp, T::U1, T::U32 )
|
OPCODE(GetOverflowFromOp, T::U1, T::U32 )
|
||||||
|
|
||||||
// Calculations
|
// Calculations
|
||||||
|
OPCODE(LeastSignificantHalf, T::U16, T::U32 )
|
||||||
OPCODE(LeastSignificantByte, T::U8, T::U32 )
|
OPCODE(LeastSignificantByte, T::U8, T::U32 )
|
||||||
OPCODE(MostSignificantBit, T::U1, T::U32 )
|
OPCODE(MostSignificantBit, T::U1, T::U32 )
|
||||||
OPCODE(IsZero, T::U1, T::U32 )
|
OPCODE(IsZero, T::U1, T::U32 )
|
||||||
|
|
|
@ -79,6 +79,10 @@ void IREmitter::SetVFlag(IR::ValuePtr value) {
|
||||||
Inst(IR::Opcode::SetVFlag, {value});
|
Inst(IR::Opcode::SetVFlag, {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IR::ValuePtr IREmitter::LeastSignificantHalf(IR::ValuePtr value) {
|
||||||
|
return Inst(IR::Opcode::LeastSignificantHalf, {value});
|
||||||
|
}
|
||||||
|
|
||||||
IR::ValuePtr IREmitter::LeastSignificantByte(IR::ValuePtr value) {
|
IR::ValuePtr IREmitter::LeastSignificantByte(IR::ValuePtr value) {
|
||||||
return Inst(IR::Opcode::LeastSignificantByte, {value});
|
return Inst(IR::Opcode::LeastSignificantByte, {value});
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
void SetCFlag(IR::ValuePtr value);
|
void SetCFlag(IR::ValuePtr value);
|
||||||
void SetVFlag(IR::ValuePtr value);
|
void SetVFlag(IR::ValuePtr value);
|
||||||
|
|
||||||
|
IR::ValuePtr LeastSignificantHalf(IR::ValuePtr value);
|
||||||
IR::ValuePtr LeastSignificantByte(IR::ValuePtr value);
|
IR::ValuePtr LeastSignificantByte(IR::ValuePtr value);
|
||||||
IR::ValuePtr MostSignificantBit(IR::ValuePtr value);
|
IR::ValuePtr MostSignificantBit(IR::ValuePtr value);
|
||||||
IR::ValuePtr IsZero(IR::ValuePtr value);
|
IR::ValuePtr IsZero(IR::ValuePtr value);
|
||||||
|
|
|
@ -375,6 +375,33 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool thumb1_STR_reg(Reg m, Reg n, Reg t) {
|
||||||
|
// STR <Rt>, [<Rn>, <Rm>]
|
||||||
|
// Rt cannot encode R15.
|
||||||
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
auto data = ir.GetRegister(t);
|
||||||
|
ir.WriteMemory32(address, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb1_STRH_reg(Reg m, Reg n, Reg t) {
|
||||||
|
// STRH <Rt>, [<Rn>, <Rm>]
|
||||||
|
// Rt cannot encode R15.
|
||||||
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
auto data = ir.LeastSignificantHalf(ir.GetRegister(t));
|
||||||
|
ir.WriteMemory16(address, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumb1_STRB_reg(Reg m, Reg n, Reg t) {
|
||||||
|
// STRB <Rt>, [<Rn>, <Rm>]
|
||||||
|
// Rt cannot encode R15.
|
||||||
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
auto data = ir.LeastSignificantByte(ir.GetRegister(t));
|
||||||
|
ir.WriteMemory8(address, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
bool thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 2;
|
u32 imm32 = imm5 << 2;
|
||||||
// LDR <Rt>, [<Rn>, #<imm>}
|
// LDR <Rt>, [<Rn>, #<imm>}
|
||||||
|
|
|
@ -267,7 +267,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") {
|
||||||
SECTION("short blocks") {
|
SECTION("short blocks") {
|
||||||
FuzzJitThumb(5, 6, 3000, instruction_select);
|
FuzzJitThumb(5, 6, 3000, instruction_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("long blocks") {
|
SECTION("long blocks") {
|
||||||
FuzzJitThumb(1024, 1025, 25, instruction_select);
|
FuzzJitThumb(1024, 1025, 25, instruction_select);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue