mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-03-08 03:52:57 +00:00
Implement thumb1_LDR_literal, thumb1_LDR_imm_t1
This commit is contained in:
@@ -56,7 +56,7 @@ private:
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
static const std::array<Thumb1Matcher<V>, 30> g_thumb1_instruction_table {{
|
||||
static const std::array<Thumb1Matcher<V>, 32> g_thumb1_instruction_table {{
|
||||
|
||||
#define INST(fn, name, bitstring) detail::detail<Thumb1Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
||||
|
||||
@@ -97,7 +97,7 @@ static const std::array<Thumb1Matcher<V>, 30> g_thumb1_instruction_table {{
|
||||
{ INST(&V::thumb1_MOV_reg, "MOV (reg)", "01000110Dmmmmddd") }, // v4T, Low regs: v6
|
||||
|
||||
// Store/Load single data item instructions
|
||||
//{ INST(&V::thumb1_LDR_lit, "LDR (literal)", "01001dddvvvvvvvv") },
|
||||
{ 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") },
|
||||
@@ -106,6 +106,7 @@ static const std::array<Thumb1Matcher<V>, 30> g_thumb1_instruction_table {{
|
||||
//{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_LDRB_rrr, "LDRB (rrr)", "0101110mmmnnnddd") },
|
||||
//{ INST(&V::thumb1_LDRSH_rrr, "LDRSH (rrr)", "0101111mmmnnnddd") },
|
||||
{ INST(&V::thumb1_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt") },
|
||||
//{ INST(&V::thumb1_STRH_rri, "STRH (rri)", "10000vvvvvnnnddd") },
|
||||
//{ INST(&V::thumb1_LDRH_rri, "LDRH (rri)", "10001vvvvvnnnddd") },
|
||||
//{ INST(&V::thumb1_STR_sp, "STR (SP)", "10010dddvvvvvvvv") },
|
||||
|
||||
@@ -222,6 +222,16 @@ public:
|
||||
return Common::StringFromFormat("mov %s, %s", RegStr(d), RegStr(m));
|
||||
}
|
||||
|
||||
std::string thumb1_LDR_literal(Reg t, Imm8 imm8) {
|
||||
u32 imm32 = imm8 << 2;
|
||||
return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string thumb1_UDF() {
|
||||
return Common::StringFromFormat("udf");
|
||||
}
|
||||
|
||||
@@ -36,3 +36,13 @@ OPCODE(And, T::U32, T::U32, T::U32
|
||||
OPCODE(Eor, T::U32, T::U32, T::U32 )
|
||||
OPCODE(Or, T::U32, T::U32, T::U32 )
|
||||
OPCODE(Not, T::U32, T::U32 )
|
||||
|
||||
// Memory access
|
||||
OPCODE(ReadMemory8, T::U8, T::U32 )
|
||||
OPCODE(ReadMemory16, T::U16, T::U32 )
|
||||
OPCODE(ReadMemory32, T::U32, T::U32 )
|
||||
OPCODE(ReadMemory64, T::U64, T::U32 )
|
||||
OPCODE(WriteMemory8, T::Void, T::U32, T::U8 )
|
||||
OPCODE(WriteMemory16, T::Void, T::U32, T::U16 )
|
||||
OPCODE(WriteMemory32, T::Void, T::U32, T::U32 )
|
||||
OPCODE(WriteMemory64, T::Void, T::U32, T::U64 )
|
||||
|
||||
@@ -14,6 +14,16 @@ void IREmitter::Unimplemented() {
|
||||
|
||||
}
|
||||
|
||||
u32 IREmitter::PC() {
|
||||
u32 offset = current_location.TFlag ? 4 : 8;
|
||||
return current_location.arm_pc + offset;
|
||||
}
|
||||
|
||||
u32 IREmitter::AlignPC(size_t alignment) {
|
||||
u32 pc = PC();
|
||||
return static_cast<u32>(pc - pc % alignment);
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::Imm1(bool value) {
|
||||
auto imm1 = std::make_shared<IR::ImmU1>(value);
|
||||
AddToBlock(imm1);
|
||||
@@ -34,13 +44,13 @@ IR::ValuePtr IREmitter::Imm32(u32 i) {
|
||||
|
||||
IR::ValuePtr IREmitter::GetRegister(Reg reg) {
|
||||
if (reg == Reg::PC) {
|
||||
u32 offset = current_location.TFlag ? 4 : 8;
|
||||
return Imm32(current_location.arm_pc + offset);
|
||||
return Imm32(PC());
|
||||
}
|
||||
return Inst(IR::Opcode::GetRegister, { RegRef(reg) });
|
||||
}
|
||||
|
||||
void IREmitter::SetRegister(const Reg reg, IR::ValuePtr value) {
|
||||
ASSERT(reg != Reg::PC);
|
||||
Inst(IR::Opcode::SetRegister, { RegRef(reg), value });
|
||||
}
|
||||
|
||||
@@ -112,6 +122,10 @@ IREmitter::ResultAndCarryAndOverflow IREmitter::AddWithCarry(IR::ValuePtr a, IR:
|
||||
return {result, carry_out, overflow};
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::Add(IR::ValuePtr a, IR::ValuePtr b) {
|
||||
return Inst(IR::Opcode::AddWithCarry, {a, b, Imm1(0)});
|
||||
}
|
||||
|
||||
IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in) {
|
||||
// This is equivalent to AddWithCarry(a, Not(b), carry_in).
|
||||
auto result = Inst(IR::Opcode::SubWithCarry, {a, b, carry_in});
|
||||
@@ -136,6 +150,39 @@ IR::ValuePtr IREmitter::Not(IR::ValuePtr a) {
|
||||
return Inst(IR::Opcode::Not, {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});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory32(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory32, {vaddr});
|
||||
}
|
||||
|
||||
IR::ValuePtr IREmitter::ReadMemory64(IR::ValuePtr vaddr) {
|
||||
return Inst(IR::Opcode::ReadMemory64, {vaddr});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory8(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
Inst(IR::Opcode::WriteMemory8, {vaddr, value});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory16(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
Inst(IR::Opcode::WriteMemory16, {vaddr, value});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory32(IR::ValuePtr vaddr, IR::ValuePtr value) {
|
||||
Inst(IR::Opcode::WriteMemory32, {vaddr, value});
|
||||
}
|
||||
|
||||
void IREmitter::WriteMemory64(IR::ValuePtr vaddr, IR::ValuePtr 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;
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
};
|
||||
|
||||
void Unimplemented();
|
||||
u32 PC();
|
||||
u32 AlignPC(size_t alignment);
|
||||
|
||||
IR::ValuePtr Imm1(bool value);
|
||||
IR::ValuePtr Imm8(u8 value);
|
||||
@@ -57,12 +59,22 @@ public:
|
||||
ResultAndCarry ArithmeticShiftRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
||||
ResultAndCarry RotateRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
||||
ResultAndCarryAndOverflow AddWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
|
||||
IR::ValuePtr Add(IR::ValuePtr a, IR::ValuePtr b);
|
||||
ResultAndCarryAndOverflow SubWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
|
||||
IR::ValuePtr And(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 Not(IR::ValuePtr a);
|
||||
|
||||
IR::ValuePtr ReadMemory8(IR::ValuePtr vaddr);
|
||||
IR::ValuePtr ReadMemory16(IR::ValuePtr vaddr);
|
||||
IR::ValuePtr ReadMemory32(IR::ValuePtr vaddr);
|
||||
IR::ValuePtr ReadMemory64(IR::ValuePtr vaddr);
|
||||
void WriteMemory8(IR::ValuePtr vaddr, IR::ValuePtr value);
|
||||
void WriteMemory16(IR::ValuePtr vaddr, IR::ValuePtr value);
|
||||
void WriteMemory32(IR::ValuePtr vaddr, IR::ValuePtr value);
|
||||
void WriteMemory64(IR::ValuePtr vaddr, IR::ValuePtr value);
|
||||
|
||||
void SetTerm(const IR::Terminal& terminal);
|
||||
|
||||
private:
|
||||
|
||||
@@ -365,6 +365,26 @@ struct TranslatorVisitor final {
|
||||
}
|
||||
}
|
||||
|
||||
bool thumb1_LDR_literal(Reg t, Imm8 imm8) {
|
||||
u32 imm32 = imm8 << 2;
|
||||
// LDR <Rt>, <label>
|
||||
// Rt cannot encode R15.
|
||||
u32 address = ir.AlignPC(4) + imm32;
|
||||
auto data = ir.ReadMemory32(ir.Imm32(address));
|
||||
ir.SetRegister(t, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
||||
u32 imm32 = imm5 << 2;
|
||||
// LDR <Rt>, [<Rn>, #<imm>}
|
||||
// Rt cannot encode R15.
|
||||
auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32));
|
||||
auto data = ir.ReadMemory32(address);
|
||||
ir.SetRegister(t, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool thumb1_UDF() {
|
||||
return TranslateThisInstruction();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user