Implement thumb1_STR_reg, thumb1_STRH_reg, thumb1_STRB_reg

This commit is contained in:
MerryMage 2016-07-11 23:06:35 +01:00
parent e7922e4fef
commit 1410221b47
9 changed files with 60 additions and 6 deletions

View file

@ -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);
} }

View file

@ -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);

View file

@ -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") },

View file

@ -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);

View file

@ -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 )

View file

@ -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});
} }

View file

@ -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);

View file

@ -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>}

View file

@ -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);
} }