blob: 7055d5d828f01ea5a79e4cf7224c4c734aa75f6c [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "EmulateInstructionARM.h"
11
12using namespace lldb;
13using namespace lldb_private;
14
15// ARM constants used during decoding
16#define REG_RD 0
17#define LDM_REGLIST 1
18#define PC_REG 15
19#define PC_REGLIST_BIT 0x8000
20
21// ARM conditions
22#define COND_EQ 0x0
23#define COND_NE 0x1
24#define COND_CS 0x2
25#define COND_HS 0x2
26#define COND_CC 0x3
27#define COND_LO 0x3
28#define COND_MI 0x4
29#define COND_PL 0x5
30#define COND_VS 0x6
31#define COND_VC 0x7
32#define COND_HI 0x8
33#define COND_LS 0x9
34#define COND_GE 0xA
35#define COND_LT 0xB
36#define COND_GT 0xC
37#define COND_LE 0xD
38#define COND_AL 0xE
39#define COND_UNCOND 0xF
40
41
42#define MASK_CPSR_MODE_MASK (0x0000001fu)
43#define MASK_CPSR_T (1u << 5)
44#define MASK_CPSR_F (1u << 6)
45#define MASK_CPSR_I (1u << 7)
46#define MASK_CPSR_A (1u << 8)
47#define MASK_CPSR_E (1u << 9)
48#define MASK_CPSR_GE_MASK (0x000f0000u)
49#define MASK_CPSR_J (1u << 24)
50#define MASK_CPSR_Q (1u << 27)
51#define MASK_CPSR_V (1u << 28)
52#define MASK_CPSR_C (1u << 29)
53#define MASK_CPSR_Z (1u << 30)
54#define MASK_CPSR_N (1u << 31)
55
56
57#define ARMv4 (1u << 0)
58#define ARMv4T (1u << 1)
59#define ARMv5T (1u << 2)
60#define ARMv5TE (1u << 3)
61#define ARMv5TEJ (1u << 4)
62#define ARMv6 (1u << 5)
63#define ARMv6K (1u << 6)
64#define ARMv6T2 (1u << 7)
65#define ARMv7 (1u << 8)
66#define ARMv8 (1u << 8)
67#define ARMvAll (0xffffffffu)
68
69typedef bool (*EmulateCallback) (EmulateInstructionARM *emulator);
70
71
72typedef enum ARMEncoding
73{
74 eEncodingA1,
75 eEncodingA2,
76 eEncodingA3,
77 eEncodingA4,
78 eEncodingA5,
79 eEncodingT1,
80 eEncodingT2,
81 eEncodingT3,
82 eEncodingT4,
83 eEncodingT5,
84} ARMEncoding;
85
86
87typedef struct ARMOpcode
88{
89 uint32_t mask;
90 uint32_t value;
91 uint32_t variants;
92 ARMEncoding encoding;
93 const char *name;
94 EmulateCallback callback;
95};
96
97static bool
98EmulateARMPushEncodingA1 (EmulateInstructionARM *emulator)
99{
100#if 0
101 // ARM pseudo code...
102 if (ConditionPassed())
103 {
104 EncodingSpecificOperations();
105 NullCheckIfThumbEE(13);
106 address = SP - 4*BitCount(registers);
107
108 for (i = 0 to 14)
109 {
110 if (registers<i> == 1’)
111 {
112 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
113 MemA[address,4] = bits(32) UNKNOWN;
114 else
115 MemA[address,4] = R[i];
116 address = address + 4;
117 }
118 }
119
120 if (registers<15> == 1’) // Only possible for encoding A1 or A2
121 MemA[address,4] = PCStoreValue();
122
123 SP = SP - 4*BitCount(registers);
124 }
125#endif
126
127 bool success = false;
128 const uint32_t opcode = emulator->OpcodeAsUnsigned (&success);
129 if (!success)
130 return false;
131
132 if (emulator->ConditionPassed())
133 {
134 const uint32_t addr_byte_size = emulator->GetAddressByteSize();
135 const addr_t sp = emulator->ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
136 if (!success)
137 return false;
138 const uint32_t registers = EmulateInstruction::UnsignedBits (opcode, 15, 0);
139 addr_t sp_offset = addr_byte_size * EmulateInstruction::BitCount (registers);
140 addr_t addr = sp - sp_offset;
141 uint32_t i;
142
143 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
144 for (i=0; i<15; ++i)
145 {
146 if (EmulateInstruction::BitIsSet (registers, 1u << i))
147 {
148 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
149 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
150 uint32_t reg_value = emulator->ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
151 if (!success)
152 return false;
153 if (!emulator->WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
154 return false;
155 addr += addr_byte_size;
156 }
157 }
158
159 if (EmulateInstruction::BitIsSet (registers, 1u << 15))
160 {
161 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
162 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
163 const uint32_t pc = emulator->ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
164 if (!success)
165 return false;
166 if (!emulator->WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
167 return false;
168 }
169
170 context.type = EmulateInstruction::eContextAdjustStackPointer;
171 context.arg0 = eRegisterKindGeneric;
172 context.arg1 = LLDB_REGNUM_GENERIC_SP;
173 context.arg2 = sp_offset;
174
175 if (!emulator->WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
176 return false;
177 }
178 return true;
179}
180
181static ARMOpcode g_arm_opcodes[] =
182{
183 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, "PUSH<c> <registers>", EmulateARMPushEncodingA1 }
184};
185
186static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
187
188bool
189EmulateInstructionARM::ReadInstruction ()
190{
191 bool success = false;
192 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
193 if (success)
194 {
195 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
196 if (success)
197 {
198 Context read_inst_context = {eContextReadOpcode, 0, 0};
199 if (m_inst_cpsr & MASK_CPSR_T)
200 {
201 m_inst_mode = eModeThumb;
202 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
203
204 if (success)
205 {
206 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
207 {
208 m_inst.opcode_type = eOpcode16;
209 m_inst.opcode.inst16 = thumb_opcode;
210 }
211 else
212 {
213 m_inst.opcode_type = eOpcode32;
214 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
215 }
216 }
217 }
218 else
219 {
220 m_inst_mode = eModeARM;
221 m_inst.opcode_type = eOpcode32;
222 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
223 }
224 }
225 }
226 if (!success)
227 {
228 m_inst_mode = eModeInvalid;
229 m_inst_pc = LLDB_INVALID_ADDRESS;
230 }
231 return success;
232}
233
234uint32_t
235EmulateInstructionARM::CurrentCond ()
236{
237 switch (m_inst_mode)
238 {
239 default:
240 case eModeInvalid:
241 break;
242
243 case eModeARM:
244 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
245
246 case eModeThumb:
247 return 0x0000000Eu; // Return always for now, we need to handl IT instructions later
248 }
249 return UINT32_MAX; // Return invalid value
250}
251bool
252EmulateInstructionARM::ConditionPassed ()
253{
254 if (m_inst_cpsr == 0)
255 return false;
256
257 const uint32_t cond = CurrentCond ();
258
259 if (cond == UINT32_MAX)
260 return false;
261
262 bool result = false;
263 switch (UnsignedBits(cond, 3, 1))
264 {
265 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
266 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
267 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
268 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
269 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
270 case 5:
271 {
272 bool n = (m_inst_cpsr & MASK_CPSR_N);
273 bool v = (m_inst_cpsr & MASK_CPSR_V);
274 result = n == v;
275 }
276 break;
277 case 6:
278 {
279 bool n = (m_inst_cpsr & MASK_CPSR_N);
280 bool v = (m_inst_cpsr & MASK_CPSR_V);
281 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
282 }
283 break;
284 case 7:
285 result = true;
286 break;
287 }
288
289 if (cond & 1)
290 result = !result;
291 return result;
292}
293
294
295bool
296EmulateInstructionARM::EvaluateInstruction ()
297{
298 return false;
299}