1 //===-- EmulationStateARM.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "EmulationStateARM.h"
11 #include "lldb/Interpreter/OptionValueArray.h"
12 #include "lldb/Interpreter/OptionValueDictionary.h"
13 #include "lldb/Target/RegisterContext.h"
14 #include "lldb/Target/StackFrame.h"
15 #include "lldb/Utility/RegisterValue.h"
16 #include "lldb/Utility/Scalar.h"
18 #include "Utility/ARM_DWARF_Registers.h"
21 using namespace lldb_private
;
23 EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24 ClearPseudoRegisters();
27 EmulationStateARM::~EmulationStateARM() = default;
29 bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num
,
31 if (reg_num
<= dwarf_cpsr
)
32 m_gpr
[reg_num
- dwarf_r0
] = (uint32_t)value
;
33 else if ((dwarf_s0
<= reg_num
) && (reg_num
<= dwarf_s31
)) {
34 uint32_t idx
= reg_num
- dwarf_s0
;
35 m_vfp_regs
.s_regs
[idx
] = (uint32_t)value
;
36 } else if ((dwarf_d0
<= reg_num
) && (reg_num
<= dwarf_d31
)) {
37 uint32_t idx
= reg_num
- dwarf_d0
;
39 m_vfp_regs
.s_regs
[idx
* 2] = (uint32_t)value
;
40 m_vfp_regs
.s_regs
[idx
* 2 + 1] = (uint32_t)(value
>> 32);
42 m_vfp_regs
.d_regs
[idx
- 16] = value
;
49 uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num
,
54 if (reg_num
<= dwarf_cpsr
)
55 value
= m_gpr
[reg_num
- dwarf_r0
];
56 else if ((dwarf_s0
<= reg_num
) && (reg_num
<= dwarf_s31
)) {
57 uint32_t idx
= reg_num
- dwarf_s0
;
58 value
= m_vfp_regs
.s_regs
[idx
];
59 } else if ((dwarf_d0
<= reg_num
) && (reg_num
<= dwarf_d31
)) {
60 uint32_t idx
= reg_num
- dwarf_d0
;
62 value
= (uint64_t)m_vfp_regs
.s_regs
[idx
* 2] |
63 ((uint64_t)m_vfp_regs
.s_regs
[idx
* 2 + 1] << 32);
65 value
= m_vfp_regs
.d_regs
[idx
- 16];
72 void EmulationStateARM::ClearPseudoRegisters() {
73 for (int i
= 0; i
< 17; ++i
)
76 for (int i
= 0; i
< 32; ++i
)
77 m_vfp_regs
.s_regs
[i
] = 0;
79 for (int i
= 0; i
< 16; ++i
)
80 m_vfp_regs
.d_regs
[i
] = 0;
83 void EmulationStateARM::ClearPseudoMemory() { m_memory
.clear(); }
85 bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address
,
87 m_memory
[p_address
] = value
;
91 uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address
,
93 std::map
<lldb::addr_t
, uint32_t>::iterator pos
;
97 pos
= m_memory
.find(p_address
);
98 if (pos
!= m_memory
.end())
99 ret_val
= pos
->second
;
106 size_t EmulationStateARM::ReadPseudoMemory(
107 EmulateInstruction
*instruction
, void *baton
,
108 const EmulateInstruction::Context
&context
, lldb::addr_t addr
, void *dst
,
114 EmulationStateARM
*pseudo_state
= (EmulationStateARM
*)baton
;
116 uint32_t value
= pseudo_state
->ReadFromPseudoAddress(addr
, success
);
120 if (endian::InlHostByteOrder() == lldb::eByteOrderBig
)
121 value
= llvm::byteswap
<uint32_t>(value
);
122 *((uint32_t *)dst
) = value
;
123 } else if (length
== 8) {
124 uint32_t value1
= pseudo_state
->ReadFromPseudoAddress(addr
, success
);
128 uint32_t value2
= pseudo_state
->ReadFromPseudoAddress(addr
+ 4, success
);
132 if (endian::InlHostByteOrder() == lldb::eByteOrderBig
) {
133 value1
= llvm::byteswap
<uint32_t>(value1
);
134 value2
= llvm::byteswap
<uint32_t>(value2
);
136 ((uint32_t *)dst
)[0] = value1
;
137 ((uint32_t *)dst
)[1] = value2
;
147 size_t EmulationStateARM::WritePseudoMemory(
148 EmulateInstruction
*instruction
, void *baton
,
149 const EmulateInstruction::Context
&context
, lldb::addr_t addr
,
150 const void *dst
, size_t length
) {
154 EmulationStateARM
*pseudo_state
= (EmulationStateARM
*)baton
;
158 memcpy (&value
, dst
, sizeof (uint32_t));
159 if (endian::InlHostByteOrder() == lldb::eByteOrderBig
)
160 value
= llvm::byteswap
<uint32_t>(value
);
162 pseudo_state
->StoreToPseudoAddress(addr
, value
);
164 } else if (length
== 8) {
167 memcpy (&value1
, dst
, sizeof (uint32_t));
168 memcpy(&value2
, static_cast<const uint8_t *>(dst
) + sizeof(uint32_t),
170 if (endian::InlHostByteOrder() == lldb::eByteOrderBig
) {
171 value1
= llvm::byteswap
<uint32_t>(value1
);
172 value2
= llvm::byteswap
<uint32_t>(value2
);
175 pseudo_state
->StoreToPseudoAddress(addr
, value1
);
176 pseudo_state
->StoreToPseudoAddress(addr
+ 4, value2
);
183 bool EmulationStateARM::ReadPseudoRegister(
184 EmulateInstruction
*instruction
, void *baton
,
185 const lldb_private::RegisterInfo
*reg_info
,
186 lldb_private::RegisterValue
®_value
) {
187 if (!baton
|| !reg_info
)
191 EmulationStateARM
*pseudo_state
= (EmulationStateARM
*)baton
;
192 const uint32_t dwarf_reg_num
= reg_info
->kinds
[eRegisterKindDWARF
];
193 assert(dwarf_reg_num
!= LLDB_INVALID_REGNUM
);
195 pseudo_state
->ReadPseudoRegisterValue(dwarf_reg_num
, success
);
198 success
= reg_value
.SetUInt(reg_uval
, reg_info
->byte_size
);
202 bool EmulationStateARM::WritePseudoRegister(
203 EmulateInstruction
*instruction
, void *baton
,
204 const EmulateInstruction::Context
&context
,
205 const lldb_private::RegisterInfo
*reg_info
,
206 const lldb_private::RegisterValue
®_value
) {
207 if (!baton
|| !reg_info
)
210 EmulationStateARM
*pseudo_state
= (EmulationStateARM
*)baton
;
211 const uint32_t dwarf_reg_num
= reg_info
->kinds
[eRegisterKindDWARF
];
212 assert(dwarf_reg_num
!= LLDB_INVALID_REGNUM
);
213 return pseudo_state
->StorePseudoRegisterValue(dwarf_reg_num
,
214 reg_value
.GetAsUInt64());
217 bool EmulationStateARM::CompareState(EmulationStateARM
&other_state
,
218 Stream
&out_stream
) {
221 for (int i
= 0; match
&& i
< 17; ++i
) {
222 if (m_gpr
[i
] != other_state
.m_gpr
[i
]) {
224 out_stream
.Printf("r%d: 0x%x != 0x%x\n", i
, m_gpr
[i
],
225 other_state
.m_gpr
[i
]);
229 for (int i
= 0; match
&& i
< 32; ++i
) {
230 if (m_vfp_regs
.s_regs
[i
] != other_state
.m_vfp_regs
.s_regs
[i
]) {
232 out_stream
.Printf("s%d: 0x%x != 0x%x\n", i
, m_vfp_regs
.s_regs
[i
],
233 other_state
.m_vfp_regs
.s_regs
[i
]);
237 for (int i
= 0; match
&& i
< 16; ++i
) {
238 if (m_vfp_regs
.d_regs
[i
] != other_state
.m_vfp_regs
.d_regs
[i
]) {
240 out_stream
.Printf("d%d: 0x%" PRIx64
" != 0x%" PRIx64
"\n", i
+ 16,
241 m_vfp_regs
.d_regs
[i
], other_state
.m_vfp_regs
.d_regs
[i
]);
245 // other_state is the expected state. If it has memory, check it.
246 if (!other_state
.m_memory
.empty() && m_memory
!= other_state
.m_memory
) {
248 out_stream
.Printf("memory does not match\n");
249 out_stream
.Printf("got memory:\n");
250 for (auto p
: m_memory
)
251 out_stream
.Printf("0x%08" PRIx64
": 0x%08x\n", p
.first
, p
.second
);
252 out_stream
.Printf("expected memory:\n");
253 for (auto p
: other_state
.m_memory
)
254 out_stream
.Printf("0x%08" PRIx64
": 0x%08x\n", p
.first
, p
.second
);
260 bool EmulationStateARM::LoadRegistersStateFromDictionary(
261 OptionValueDictionary
*reg_dict
, char kind
, int first_reg
, int num
) {
263 for (int i
= 0; i
< num
; ++i
) {
265 sstr
.Printf("%c%d", kind
, i
);
266 OptionValueSP value_sp
= reg_dict
->GetValueForKey(sstr
.GetString());
267 if (value_sp
.get() == nullptr)
269 uint64_t reg_value
= value_sp
->GetValueAs
<uint64_t>().value_or(0);
270 StorePseudoRegisterValue(first_reg
+ i
, reg_value
);
276 bool EmulationStateARM::LoadStateFromDictionary(
277 OptionValueDictionary
*test_data
) {
278 static constexpr llvm::StringLiteral
memory_key("memory");
279 static constexpr llvm::StringLiteral
registers_key("registers");
284 OptionValueSP value_sp
= test_data
->GetValueForKey(memory_key
);
286 // Load memory, if present.
288 if (value_sp
.get() != nullptr) {
289 static constexpr llvm::StringLiteral
address_key("address");
290 static constexpr llvm::StringLiteral
data_key("data");
291 uint64_t start_address
= 0;
293 OptionValueDictionary
*mem_dict
= value_sp
->GetAsDictionary();
294 value_sp
= mem_dict
->GetValueForKey(address_key
);
295 if (value_sp
.get() == nullptr)
298 start_address
= value_sp
->GetValueAs
<uint64_t>().value_or(0);
300 value_sp
= mem_dict
->GetValueForKey(data_key
);
301 OptionValueArray
*mem_array
= value_sp
->GetAsArray();
305 uint32_t num_elts
= mem_array
->GetSize();
306 uint32_t address
= (uint32_t)start_address
;
308 for (uint32_t i
= 0; i
< num_elts
; ++i
) {
309 value_sp
= mem_array
->GetValueAtIndex(i
);
310 if (value_sp
.get() == nullptr)
312 uint64_t value
= value_sp
->GetValueAs
<uint64_t>().value_or(0);
313 StoreToPseudoAddress(address
, value
);
314 address
= address
+ 4;
318 value_sp
= test_data
->GetValueForKey(registers_key
);
319 if (value_sp
.get() == nullptr)
322 // Load General Registers
324 OptionValueDictionary
*reg_dict
= value_sp
->GetAsDictionary();
325 if (!LoadRegistersStateFromDictionary(reg_dict
, 'r', dwarf_r0
, 16))
328 static constexpr llvm::StringLiteral
cpsr_name("cpsr");
329 value_sp
= reg_dict
->GetValueForKey(cpsr_name
);
330 if (value_sp
.get() == nullptr)
332 StorePseudoRegisterValue(dwarf_cpsr
,
333 value_sp
->GetValueAs
<uint64_t>().value_or(0));
335 // Load s/d Registers
336 // To prevent you giving both types in a state and overwriting
337 // one or the other, we'll expect to get either all S registers,
338 // or all D registers. Not a mix of the two.
339 bool found_s_registers
=
340 LoadRegistersStateFromDictionary(reg_dict
, 's', dwarf_s0
, 32);
341 bool found_d_registers
=
342 LoadRegistersStateFromDictionary(reg_dict
, 'd', dwarf_d0
, 32);
344 return found_s_registers
!= found_d_registers
;