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");
|
||||
}
|
||||
|
||||
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_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
// TODO: Flag optimization
|
||||
// TODO: Optimize
|
||||
|
||||
reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
void EmitSetVFlag(IR::Value* value);
|
||||
void EmitGetCarryFromOp(IR::Value* value);
|
||||
void EmitGetOverflowFromOp(IR::Value* value);
|
||||
void EmitLeastSignificantHalf(IR::Value* value);
|
||||
void EmitLeastSignificantByte(IR::Value* value);
|
||||
void EmitMostSignificantBit(IR::Value* value);
|
||||
void EmitIsZero(IR::Value* value);
|
||||
|
|
|
@ -56,7 +56,7 @@ private:
|
|||
};
|
||||
|
||||
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)
|
||||
|
||||
|
@ -98,9 +98,9 @@ static const std::array<Thumb1Matcher<V>, 32> g_thumb1_instruction_table {{
|
|||
|
||||
// Store/Load single data item instructions
|
||||
{ INST(&V::thumb1_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") },
|
||||
//{ INST(&V::thumb1_STR_rrr, "STR (rrr)", "0101000mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_STRH_rrr, "STRH (rrr)", "0101001mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_STRB_rrr, "STRB (rrr)", "0101010mmmnnnddd") },
|
||||
{ INST(&V::thumb1_STR_reg, "STR (reg)", "0101000mmmnnnttt") },
|
||||
{ INST(&V::thumb1_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") },
|
||||
{ INST(&V::thumb1_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") },
|
||||
//{ INST(&V::thumb1_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") },
|
||||
|
|
|
@ -227,6 +227,18 @@ public:
|
|||
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) {
|
||||
u32 imm32 = imm5 << 2;
|
||||
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 )
|
||||
|
||||
// Calculations
|
||||
OPCODE(LeastSignificantHalf, T::U16, T::U32 )
|
||||
OPCODE(LeastSignificantByte, T::U8, T::U32 )
|
||||
OPCODE(MostSignificantBit, 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});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::LeastSignificantHalf(IR::ValuePtr value) {
|
||||
return Inst(IR::Opcode::LeastSignificantHalf, {value});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::LeastSignificantByte(IR::ValuePtr value) {
|
||||
return Inst(IR::Opcode::LeastSignificantByte, {value});
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
void SetCFlag(IR::ValuePtr value);
|
||||
void SetVFlag(IR::ValuePtr value);
|
||||
|
||||
IR::ValuePtr LeastSignificantHalf(IR::ValuePtr value);
|
||||
IR::ValuePtr LeastSignificantByte(IR::ValuePtr value);
|
||||
IR::ValuePtr MostSignificantBit(IR::ValuePtr value);
|
||||
IR::ValuePtr IsZero(IR::ValuePtr value);
|
||||
|
|
|
@ -375,6 +375,33 @@ struct TranslatorVisitor final {
|
|||
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) {
|
||||
u32 imm32 = imm5 << 2;
|
||||
// LDR <Rt>, [<Rn>, #<imm>}
|
||||
|
|
Loading…
Reference in a new issue