blob: 8ae3054647c66cfacb5a293d43ef5005fdf1478b [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
Johnny Chen251af6a2011-01-21 22:47:25 +000042#define MASK_CPSR_MODE_MASK (0x0000001fu)
Greg Clayton64c84432011-01-21 22:02:52 +000043#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
Johnny Chen251af6a2011-01-21 22:47:25 +000057#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +000058#define ARMv4T (1u << 1)
59#define ARMv5T (1u << 2)
60#define ARMv5TE (1u << 3)
61#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +000062#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +000063#define ARMv6K (1u << 6)
64#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +000065#define ARMv7 (1u << 8)
66#define ARMv8 (1u << 8)
Greg Clayton64c84432011-01-21 22:02:52 +000067#define ARMvAll (0xffffffffu)
68
Greg Clayton64c84432011-01-21 22:02:52 +000069typedef enum ARMEncoding
70{
71 eEncodingA1,
72 eEncodingA2,
73 eEncodingA3,
74 eEncodingA4,
75 eEncodingA5,
76 eEncodingT1,
77 eEncodingT2,
78 eEncodingT3,
79 eEncodingT4,
80 eEncodingT5,
81} ARMEncoding;
82
Johnny Chen3c75c762011-01-22 00:47:08 +000083// Pass along (ARMEncoding)encoding as the callback data.
84typedef bool (*EmulateCallback) (EmulateInstructionARM *emulator, ARMEncoding encoding);
85
Greg Clayton64c84432011-01-21 22:02:52 +000086typedef struct ARMOpcode
87{
88 uint32_t mask;
89 uint32_t value;
90 uint32_t variants;
91 ARMEncoding encoding;
Greg Clayton64c84432011-01-21 22:02:52 +000092 EmulateCallback callback;
Johnny Chen4bee8ce2011-01-22 00:59:07 +000093 const char *name;
Greg Clayton64c84432011-01-21 22:02:52 +000094};
95
96static bool
Johnny Chen3c75c762011-01-22 00:47:08 +000097EmulateARMPushEncoding (EmulateInstructionARM *emulator, ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +000098{
99#if 0
100 // ARM pseudo code...
101 if (ConditionPassed())
102 {
103 EncodingSpecificOperations();
104 NullCheckIfThumbEE(13);
105 address = SP - 4*BitCount(registers);
106
107 for (i = 0 to 14)
108 {
109 if (registers<i> == 1’)
110 {
111 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
112 MemA[address,4] = bits(32) UNKNOWN;
113 else
114 MemA[address,4] = R[i];
115 address = address + 4;
116 }
117 }
118
119 if (registers<15> == 1’) // Only possible for encoding A1 or A2
120 MemA[address,4] = PCStoreValue();
121
122 SP = SP - 4*BitCount(registers);
123 }
124#endif
125
126 bool success = false;
127 const uint32_t opcode = emulator->OpcodeAsUnsigned (&success);
128 if (!success)
129 return false;
130
131 if (emulator->ConditionPassed())
132 {
133 const uint32_t addr_byte_size = emulator->GetAddressByteSize();
134 const addr_t sp = emulator->ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
135 if (!success)
136 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000137 uint32_t registers = 0;
138 switch (encoding) {
139 case eEncodingA1:
140 registers = EmulateInstruction::UnsignedBits (opcode, 15, 0);
141 break;
142 case eEncodingA2:
143 const uint32_t Rt = EmulateInstruction::UnsignedBits (opcode, 15, 12);
144 // if t == 13 then UNPREDICTABLE
145 if (Rt == dwarf_sp)
146 return false;
147 registers = (1u << Rt);
148 break;
149 }
Greg Clayton64c84432011-01-21 22:02:52 +0000150 addr_t sp_offset = addr_byte_size * EmulateInstruction::BitCount (registers);
151 addr_t addr = sp - sp_offset;
152 uint32_t i;
153
154 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
155 for (i=0; i<15; ++i)
156 {
157 if (EmulateInstruction::BitIsSet (registers, 1u << i))
158 {
159 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
160 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
161 uint32_t reg_value = emulator->ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
162 if (!success)
163 return false;
164 if (!emulator->WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
165 return false;
166 addr += addr_byte_size;
167 }
168 }
169
170 if (EmulateInstruction::BitIsSet (registers, 1u << 15))
171 {
172 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000173 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton64c84432011-01-21 22:02:52 +0000174 const uint32_t pc = emulator->ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
175 if (!success)
176 return false;
177 if (!emulator->WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
178 return false;
179 }
180
181 context.type = EmulateInstruction::eContextAdjustStackPointer;
182 context.arg0 = eRegisterKindGeneric;
183 context.arg1 = LLDB_REGNUM_GENERIC_SP;
184 context.arg2 = sp_offset;
185
186 if (!emulator->WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
187 return false;
188 }
189 return true;
190}
191
192static ARMOpcode g_arm_opcodes[] =
193{
Johnny Chen4bee8ce2011-01-22 00:59:07 +0000194 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, EmulateARMPushEncoding,
195 "PUSH<c> <registers> ; <registers> contains more than one register" },
196 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, EmulateARMPushEncoding,
197 "PUSH<c> <registers> ; <registers> contains one register, <Rt>" }
Greg Clayton64c84432011-01-21 22:02:52 +0000198};
199
200static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
201
202bool
203EmulateInstructionARM::ReadInstruction ()
204{
205 bool success = false;
206 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
207 if (success)
208 {
209 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
210 if (success)
211 {
212 Context read_inst_context = {eContextReadOpcode, 0, 0};
213 if (m_inst_cpsr & MASK_CPSR_T)
214 {
215 m_inst_mode = eModeThumb;
216 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
217
218 if (success)
219 {
220 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
221 {
222 m_inst.opcode_type = eOpcode16;
223 m_inst.opcode.inst16 = thumb_opcode;
224 }
225 else
226 {
227 m_inst.opcode_type = eOpcode32;
228 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
229 }
230 }
231 }
232 else
233 {
234 m_inst_mode = eModeARM;
235 m_inst.opcode_type = eOpcode32;
236 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
237 }
238 }
239 }
240 if (!success)
241 {
242 m_inst_mode = eModeInvalid;
243 m_inst_pc = LLDB_INVALID_ADDRESS;
244 }
245 return success;
246}
247
248uint32_t
249EmulateInstructionARM::CurrentCond ()
250{
251 switch (m_inst_mode)
252 {
253 default:
254 case eModeInvalid:
255 break;
256
257 case eModeARM:
258 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
259
260 case eModeThumb:
261 return 0x0000000Eu; // Return always for now, we need to handl IT instructions later
262 }
263 return UINT32_MAX; // Return invalid value
264}
265bool
266EmulateInstructionARM::ConditionPassed ()
267{
268 if (m_inst_cpsr == 0)
269 return false;
270
271 const uint32_t cond = CurrentCond ();
272
273 if (cond == UINT32_MAX)
274 return false;
275
276 bool result = false;
277 switch (UnsignedBits(cond, 3, 1))
278 {
279 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
280 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
281 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
282 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
283 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
284 case 5:
285 {
286 bool n = (m_inst_cpsr & MASK_CPSR_N);
287 bool v = (m_inst_cpsr & MASK_CPSR_V);
288 result = n == v;
289 }
290 break;
291 case 6:
292 {
293 bool n = (m_inst_cpsr & MASK_CPSR_N);
294 bool v = (m_inst_cpsr & MASK_CPSR_V);
295 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
296 }
297 break;
298 case 7:
299 result = true;
300 break;
301 }
302
303 if (cond & 1)
304 result = !result;
305 return result;
306}
307
308
309bool
310EmulateInstructionARM::EvaluateInstruction ()
311{
312 return false;
313}