blob: 2f6cdc881ded60db28470ec0bf1bb3e9e0f7e837 [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"
Greg Clayton8482ded2011-02-01 00:04:43 +000011#include "lldb/Core/ConstString.h"
12
Johnny Chen8584c922011-01-26 01:18:52 +000013#include "ARMDefines.h"
Johnny Chen4baf2e32011-01-24 18:24:53 +000014#include "ARMUtils.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000015#include "ARM_DWARF_Registers.h"
Johnny Chen9b8d7832011-02-02 01:13:56 +000016#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000017 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000018
19using namespace lldb;
20using namespace lldb_private;
21
Johnny Chend6c13f02011-02-08 20:36:34 +000022static inline uint32_t Align(uint32_t val, uint32_t alignment)
23{
24 return alignment * (val / alignment);
25}
26
Johnny Chen93070472011-02-04 23:02:47 +000027// A8.6.50
28// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
29static unsigned short CountITSize(unsigned ITMask) {
30 // First count the trailing zeros of the IT mask.
31 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
32 if (TZ > 3)
33 {
34 printf("Encoding error: IT Mask '0000'\n");
35 return 0;
36 }
37 return (4 - TZ);
38}
39
40// Init ITState. Note that at least one bit is always 1 in mask.
41bool ITSession::InitIT(unsigned short bits7_0)
42{
43 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
44 if (ITCounter == 0)
45 return false;
46
47 // A8.6.50 IT
48 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
49 if (FirstCond == 0xF)
50 {
51 printf("Encoding error: IT FirstCond '1111'\n");
52 return false;
53 }
54 if (FirstCond == 0xE && ITCounter != 1)
55 {
56 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
57 return false;
58 }
59
60 ITState = bits7_0;
61 return true;
62}
63
64// Update ITState if necessary.
65void ITSession::ITAdvance()
66{
67 assert(ITCounter);
68 --ITCounter;
69 if (ITCounter == 0)
70 ITState = 0;
71 else
72 {
73 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
74 SetBits32(ITState, 4, 0, NewITState4_0);
75 }
76}
77
78// Return true if we're inside an IT Block.
79bool ITSession::InITBlock()
80{
81 return ITCounter != 0;
82}
83
Johnny Chenc315f862011-02-05 00:46:10 +000084// Return true if we're the last instruction inside an IT Block.
85bool ITSession::LastInITBlock()
86{
87 return ITCounter == 1;
88}
89
Johnny Chen93070472011-02-04 23:02:47 +000090// Get condition bits for the current thumb instruction.
91uint32_t ITSession::GetCond()
92{
Johnny Chenc315f862011-02-05 00:46:10 +000093 if (InITBlock())
94 return Bits32(ITState, 7, 4);
95 else
96 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000097}
98
Greg Clayton64c84432011-01-21 22:02:52 +000099// ARM constants used during decoding
100#define REG_RD 0
101#define LDM_REGLIST 1
102#define PC_REG 15
103#define PC_REGLIST_BIT 0x8000
104
Johnny Chen251af6a2011-01-21 22:47:25 +0000105#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000106#define ARMv4T (1u << 1)
107#define ARMv5T (1u << 2)
108#define ARMv5TE (1u << 3)
109#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000110#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000111#define ARMv6K (1u << 6)
112#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000113#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000114#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMvAll (0xffffffffu)
116
Johnny Chen9b8d7832011-02-02 01:13:56 +0000117#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
118#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
119#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000120
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000121void
122EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000123{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000124}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000125
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000126void
127EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000128{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000129}
130
Johnny Chen08c25e82011-01-31 18:02:28 +0000131// Push Multiple Registers stores multiple registers to the stack, storing to
132// consecutive memory locations ending just below the address in SP, and updates
133// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000134bool
135EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000136{
137#if 0
138 // ARM pseudo code...
139 if (ConditionPassed())
140 {
141 EncodingSpecificOperations();
142 NullCheckIfThumbEE(13);
143 address = SP - 4*BitCount(registers);
144
145 for (i = 0 to 14)
146 {
147 if (registers<i> == ’1’)
148 {
149 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
150 MemA[address,4] = bits(32) UNKNOWN;
151 else
152 MemA[address,4] = R[i];
153 address = address + 4;
154 }
155 }
156
157 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
158 MemA[address,4] = PCStoreValue();
159
160 SP = SP - 4*BitCount(registers);
161 }
162#endif
163
164 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000165 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000166 if (!success)
167 return false;
168
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000169 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000170 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000171 const uint32_t addr_byte_size = GetAddressByteSize();
172 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000173 if (!success)
174 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000175 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000176 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000177 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000178 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000179 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000180 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000181 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000182 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000183 // if BitCount(registers) < 1 then UNPREDICTABLE;
184 if (BitCount(registers) < 1)
185 return false;
186 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000187 case eEncodingT2:
188 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000189 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000190 // if BitCount(registers) < 2 then UNPREDICTABLE;
191 if (BitCount(registers) < 2)
192 return false;
193 break;
194 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000195 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000196 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000197 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000198 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000199 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000200 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000201 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000202 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000203 // Instead of return false, let's handle the following case as well,
204 // which amounts to pushing one reg onto the full descending stacks.
205 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000206 break;
207 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000208 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000209 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000210 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000211 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000212 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000213 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000214 default:
215 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000216 }
Johnny Chence1ca772011-01-25 01:13:00 +0000217 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 addr_t addr = sp - sp_offset;
219 uint32_t i;
220
221 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
222 for (i=0; i<15; ++i)
223 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000224 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000225 {
226 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
227 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000231 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000232 return false;
233 addr += addr_byte_size;
234 }
235 }
236
Johnny Chen7c1bf922011-02-08 23:49:37 +0000237 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000238 {
239 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000240 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000241 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000242 if (!success)
243 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000244 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000245 return false;
246 }
247
248 context.type = EmulateInstruction::eContextAdjustStackPointer;
249 context.arg0 = eRegisterKindGeneric;
250 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000251 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000252
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000253 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000254 return false;
255 }
256 return true;
257}
258
Johnny Chenef85e912011-01-31 23:07:40 +0000259// Pop Multiple Registers loads multiple registers from the stack, loading from
260// consecutive memory locations staring at the address in SP, and updates
261// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000262bool
263EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000264{
265#if 0
266 // ARM pseudo code...
267 if (ConditionPassed())
268 {
269 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
270 address = SP;
271 for i = 0 to 14
272 if registers<i> == ‘1’ then
273 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
274 if registers<15> == ‘1’ then
275 if UnalignedAllowed then
276 LoadWritePC(MemU[address,4]);
277 else
278 LoadWritePC(MemA[address,4]);
279 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
280 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
281 }
282#endif
283
284 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000286 if (!success)
287 return false;
288
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000289 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000290 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000291 const uint32_t addr_byte_size = GetAddressByteSize();
292 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000293 if (!success)
294 return false;
295 uint32_t registers = 0;
296 uint32_t Rt; // the destination register
297 switch (encoding) {
298 case eEncodingT1:
299 registers = Bits32(opcode, 7, 0);
300 // The P bit represents PC.
301 if (Bits32(opcode, 8, 8))
302 registers |= (1u << 15);
303 // if BitCount(registers) < 1 then UNPREDICTABLE;
304 if (BitCount(registers) < 1)
305 return false;
306 break;
307 case eEncodingT2:
308 // Ignore bit 13.
309 registers = Bits32(opcode, 15, 0) & ~0x2000;
310 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
311 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
312 return false;
313 break;
314 case eEncodingT3:
315 Rt = Bits32(opcode, 15, 12);
316 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
317 if (Rt == dwarf_sp)
318 return false;
319 registers = (1u << Rt);
320 break;
321 case eEncodingA1:
322 registers = Bits32(opcode, 15, 0);
323 // Instead of return false, let's handle the following case as well,
324 // which amounts to popping one reg from the full descending stacks.
325 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
326
327 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
328 if (Bits32(opcode, 13, 13))
329 return false;
330 break;
331 case eEncodingA2:
332 Rt = Bits32(opcode, 15, 12);
333 // if t == 13 then UNPREDICTABLE;
334 if (Rt == dwarf_sp)
335 return false;
336 registers = (1u << Rt);
337 break;
338 default:
339 return false;
340 }
341 addr_t sp_offset = addr_byte_size * BitCount (registers);
342 addr_t addr = sp;
343 uint32_t i, data;
344
345 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
346 for (i=0; i<15; ++i)
347 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000348 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000349 {
350 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
351 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000353 if (!success)
354 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000355 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 return false;
357 addr += addr_byte_size;
358 }
359 }
360
Johnny Chen7c1bf922011-02-08 23:49:37 +0000361 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000362 {
363 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
364 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000365 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000366 if (!success)
367 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000368 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
370 addr += addr_byte_size;
371 }
372
373 context.type = EmulateInstruction::eContextAdjustStackPointer;
374 context.arg0 = eRegisterKindGeneric;
375 context.arg1 = LLDB_REGNUM_GENERIC_SP;
376 context.arg2 = sp_offset;
377
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000378 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000379 return false;
380 }
381 return true;
382}
383
Johnny Chen5b442b72011-01-27 19:34:30 +0000384// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000385// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000386bool
387EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000388{
389#if 0
390 // ARM pseudo code...
391 if (ConditionPassed())
392 {
393 EncodingSpecificOperations();
394 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
395 if d == 15 then
396 ALUWritePC(result); // setflags is always FALSE here
397 else
398 R[d] = result;
399 if setflags then
400 APSR.N = result<31>;
401 APSR.Z = IsZeroBit(result);
402 APSR.C = carry;
403 APSR.V = overflow;
404 }
405#endif
406
407 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000408 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000409 if (!success)
410 return false;
411
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000412 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000413 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000415 if (!success)
416 return false;
417 uint32_t Rd; // the destination register
418 uint32_t imm32;
419 switch (encoding) {
420 case eEncodingT1:
421 Rd = 7;
422 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
423 break;
424 case eEncodingA1:
425 Rd = Bits32(opcode, 15, 12);
426 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
427 break;
428 default:
429 return false;
430 }
431 addr_t sp_offset = imm32;
432 addr_t addr = sp + sp_offset; // a pointer to the stack area
433
434 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
435 eRegisterKindGeneric,
436 LLDB_REGNUM_GENERIC_SP,
437 sp_offset };
438
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000440 return false;
441 }
442 return true;
443}
444
Johnny Chen2ccad832011-01-28 19:57:25 +0000445// Set r7 or ip to the current stack pointer.
446// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000447bool
448EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000449{
450#if 0
451 // ARM pseudo code...
452 if (ConditionPassed())
453 {
454 EncodingSpecificOperations();
455 result = R[m];
456 if d == 15 then
457 ALUWritePC(result); // setflags is always FALSE here
458 else
459 R[d] = result;
460 if setflags then
461 APSR.N = result<31>;
462 APSR.Z = IsZeroBit(result);
463 // APSR.C unchanged
464 // APSR.V unchanged
465 }
466#endif
467
468 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000470 //if (!success)
471 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000472
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000474 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000475 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000476 if (!success)
477 return false;
478 uint32_t Rd; // the destination register
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 break;
483 case eEncodingA1:
484 Rd = 12;
485 break;
486 default:
487 return false;
488 }
489 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
490 eRegisterKindGeneric,
491 LLDB_REGNUM_GENERIC_SP,
492 0 };
493
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000495 return false;
496 }
497 return true;
498}
499
Johnny Chen1c13b622011-01-29 00:11:15 +0000500// Move from high register (r8-r15) to low register (r0-r7).
501// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502bool
503EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000504{
505#if 0
506 // ARM pseudo code...
507 if (ConditionPassed())
508 {
509 EncodingSpecificOperations();
510 result = R[m];
511 if d == 15 then
512 ALUWritePC(result); // setflags is always FALSE here
513 else
514 R[d] = result;
515 if setflags then
516 APSR.N = result<31>;
517 APSR.Z = IsZeroBit(result);
518 // APSR.C unchanged
519 // APSR.V unchanged
520 }
521#endif
522
523 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 if (!success)
526 return false;
527
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000528 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000529 {
530 uint32_t Rm; // the source register
531 uint32_t Rd; // the destination register
532 switch (encoding) {
533 case eEncodingT1:
534 Rm = Bits32(opcode, 6, 3);
535 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
536 break;
537 default:
538 return false;
539 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 if (!success)
542 return false;
543
544 // The context specifies that Rm is to be moved into Rd.
545 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
546 eRegisterKindDWARF,
547 dwarf_r0 + Rm,
548 0 };
549
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000551 return false;
552 }
553 return true;
554}
555
Johnny Chen788e0552011-01-27 22:52:23 +0000556// PC relative immediate load into register, possibly followed by ADD (SP plus register).
557// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000558bool
559EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000560{
561#if 0
562 // ARM pseudo code...
563 if (ConditionPassed())
564 {
565 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
566 base = Align(PC,4);
567 address = if add then (base + imm32) else (base - imm32);
568 data = MemU[address,4];
569 if t == 15 then
570 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
571 elsif UnalignedSupport() || address<1:0> = ‘00’ then
572 R[t] = data;
573 else // Can only apply before ARMv7
574 if CurrentInstrSet() == InstrSet_ARM then
575 R[t] = ROR(data, 8*UInt(address<1:0>));
576 else
577 R[t] = bits(32) UNKNOWN;
578 }
579#endif
580
581 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000582 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000583 if (!success)
584 return false;
585
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000586 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000587 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000588 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000589 if (!success)
590 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000591
592 // PC relative immediate load context
593 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
594 eRegisterKindGeneric,
595 LLDB_REGNUM_GENERIC_PC,
596 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000597 uint32_t Rd; // the destination register
598 uint32_t imm32; // immediate offset from the PC
599 addr_t addr; // the PC relative address
600 uint32_t data; // the literal data value from the PC relative load
601 switch (encoding) {
602 case eEncodingT1:
603 Rd = Bits32(opcode, 10, 8);
604 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
605 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000606 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000607 break;
608 default:
609 return false;
610 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000611 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000612 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000613 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000615 return false;
616 }
617 return true;
618}
619
Johnny Chen5b442b72011-01-27 19:34:30 +0000620// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000621// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000622bool
623EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000624{
625#if 0
626 // ARM pseudo code...
627 if (ConditionPassed())
628 {
629 EncodingSpecificOperations();
630 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
631 if d == 15 then // Can only occur for ARM encoding
632 ALUWritePC(result); // setflags is always FALSE here
633 else
634 R[d] = result;
635 if setflags then
636 APSR.N = result<31>;
637 APSR.Z = IsZeroBit(result);
638 APSR.C = carry;
639 APSR.V = overflow;
640 }
641#endif
642
643 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000644 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000645 if (!success)
646 return false;
647
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000648 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000649 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000650 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000651 if (!success)
652 return false;
653 uint32_t imm32; // the immediate operand
654 switch (encoding) {
655 case eEncodingT2:
656 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
657 break;
658 default:
659 return false;
660 }
661 addr_t sp_offset = imm32;
662 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
663
664 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
665 eRegisterKindGeneric,
666 LLDB_REGNUM_GENERIC_SP,
667 sp_offset };
668
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000669 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000670 return false;
671 }
672 return true;
673}
674
675// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000676// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000677bool
678EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000679{
680#if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
686 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
687 if d == 15 then
688 ALUWritePC(result); // setflags is always FALSE here
689 else
690 R[d] = result;
691 if setflags then
692 APSR.N = result<31>;
693 APSR.Z = IsZeroBit(result);
694 APSR.C = carry;
695 APSR.V = overflow;
696 }
697#endif
698
699 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000700 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000701 if (!success)
702 return false;
703
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000704 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000705 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000706 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000707 if (!success)
708 return false;
709 uint32_t Rm; // the second operand
710 switch (encoding) {
711 case eEncodingT2:
712 Rm = Bits32(opcode, 6, 3);
713 break;
714 default:
715 return false;
716 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000717 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000718 if (!success)
719 return false;
720
721 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
722
723 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
724 eRegisterKindGeneric,
725 LLDB_REGNUM_GENERIC_SP,
726 reg_value };
727
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000729 return false;
730 }
731 return true;
732}
733
Johnny Chen9b8d7832011-02-02 01:13:56 +0000734// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
735// at a PC-relative address, and changes instruction set from ARM to Thumb, or
736// from Thumb to ARM.
737// BLX (immediate)
738bool
739EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
740{
741#if 0
742 // ARM pseudo code...
743 if (ConditionPassed())
744 {
745 EncodingSpecificOperations();
746 if CurrentInstrSet() == InstrSet_ARM then
747 LR = PC - 4;
748 else
749 LR = PC<31:1> : '1';
750 if targetInstrSet == InstrSet_ARM then
751 targetAddress = Align(PC,4) + imm32;
752 else
753 targetAddress = PC + imm32;
754 SelectInstrSet(targetInstrSet);
755 BranchWritePC(targetAddress);
756 }
757#endif
758
759 bool success = false;
760 const uint32_t opcode = OpcodeAsUnsigned (&success);
761 if (!success)
762 return false;
763
764 if (ConditionPassed())
765 {
766 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
767 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000768 if (!success)
769 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000770 addr_t lr; // next instruction address
771 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000772 int32_t imm32; // PC-relative offset
773 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000774 case eEncodingT1:
775 {
776 lr = (pc + 4) | 1u; // return address
777 uint32_t S = Bits32(opcode, 26, 26);
778 uint32_t imm10 = Bits32(opcode, 25, 16);
779 uint32_t J1 = Bits32(opcode, 13, 13);
780 uint32_t J2 = Bits32(opcode, 11, 11);
781 uint32_t imm11 = Bits32(opcode, 10, 0);
782 uint32_t I1 = !(J1 ^ S);
783 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000784 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000785 imm32 = llvm::SignExtend32<25>(imm25);
786 target = pc + 4 + imm32;
787 context.arg1 = 4 + imm32; // signed offset
788 context.arg2 = eModeThumb; // target instruction set
789 break;
790 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000791 case eEncodingT2:
792 {
793 lr = (pc + 4) | 1u; // return address
794 uint32_t S = Bits32(opcode, 26, 26);
795 uint32_t imm10H = Bits32(opcode, 25, 16);
796 uint32_t J1 = Bits32(opcode, 13, 13);
797 uint32_t J2 = Bits32(opcode, 11, 11);
798 uint32_t imm10L = Bits32(opcode, 10, 1);
799 uint32_t I1 = !(J1 ^ S);
800 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000801 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000802 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000803 target = Align(pc + 4, 4) + imm32;
804 context.arg1 = 4 + imm32; // signed offset
805 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000806 break;
807 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000808 case eEncodingA1:
809 lr = pc + 4; // return address
810 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000811 target = Align(pc + 8, 4) + imm32;
812 context.arg1 = 8 + imm32; // signed offset
813 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000814 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000815 case eEncodingA2:
816 lr = pc + 4; // return address
817 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
818 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000819 context.arg1 = 8 + imm32; // signed offset
820 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000821 break;
822 default:
823 return false;
824 }
825 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
826 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000827 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000828 return false;
829 }
830 return true;
831}
832
833// Branch with Link and Exchange (register) calls a subroutine at an address and
834// instruction set specified by a register.
835// BLX (register)
836bool
837EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
838{
839#if 0
840 // ARM pseudo code...
841 if (ConditionPassed())
842 {
843 EncodingSpecificOperations();
844 target = R[m];
845 if CurrentInstrSet() == InstrSet_ARM then
846 next_instr_addr = PC - 4;
847 LR = next_instr_addr;
848 else
849 next_instr_addr = PC - 2;
850 LR = next_instr_addr<31:1> : ‘1’;
851 BXWritePC(target);
852 }
853#endif
854
855 bool success = false;
856 const uint32_t opcode = OpcodeAsUnsigned (&success);
857 if (!success)
858 return false;
859
860 if (ConditionPassed())
861 {
862 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
863 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
864 addr_t lr; // next instruction address
865 addr_t target; // target address
866 if (!success)
867 return false;
868 uint32_t Rm; // the register with the target address
869 switch (encoding) {
870 case eEncodingT1:
871 lr = (pc + 2) | 1u; // return address
872 Rm = Bits32(opcode, 6, 3);
873 // if m == 15 then UNPREDICTABLE;
874 if (Rm == 15)
875 return false;
876 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
877 break;
878 case eEncodingA1:
879 lr = pc + 4; // return address
880 Rm = Bits32(opcode, 3, 0);
881 // if m == 15 then UNPREDICTABLE;
882 if (Rm == 15)
883 return false;
884 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000885 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000886 default:
887 return false;
888 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000889 context.arg0 = eRegisterKindDWARF;
890 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000891 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
892 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000893 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000894 return false;
895 }
896 return true;
897}
898
Johnny Chen0d0148e2011-01-28 02:26:08 +0000899// Set r7 to point to some ip offset.
900// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000901bool
902EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000903{
904#if 0
905 // ARM pseudo code...
906 if (ConditionPassed())
907 {
908 EncodingSpecificOperations();
909 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
910 if d == 15 then // Can only occur for ARM encoding
911 ALUWritePC(result); // setflags is always FALSE here
912 else
913 R[d] = result;
914 if setflags then
915 APSR.N = result<31>;
916 APSR.Z = IsZeroBit(result);
917 APSR.C = carry;
918 APSR.V = overflow;
919 }
920#endif
921
922 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000923 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000924 if (!success)
925 return false;
926
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000928 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000929 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000930 if (!success)
931 return false;
932 uint32_t imm32;
933 switch (encoding) {
934 case eEncodingA1:
935 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
936 break;
937 default:
938 return false;
939 }
940 addr_t ip_offset = imm32;
941 addr_t addr = ip - ip_offset; // the adjusted ip value
942
943 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
944 eRegisterKindDWARF,
945 dwarf_r12,
946 -ip_offset };
947
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000948 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000949 return false;
950 }
951 return true;
952}
953
954// Set ip to point to some stack offset.
955// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956bool
957EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000958{
959#if 0
960 // ARM pseudo code...
961 if (ConditionPassed())
962 {
963 EncodingSpecificOperations();
964 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
965 if d == 15 then // Can only occur for ARM encoding
966 ALUWritePC(result); // setflags is always FALSE here
967 else
968 R[d] = result;
969 if setflags then
970 APSR.N = result<31>;
971 APSR.Z = IsZeroBit(result);
972 APSR.C = carry;
973 APSR.V = overflow;
974 }
975#endif
976
977 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000978 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000979 if (!success)
980 return false;
981
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000982 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000983 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000984 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000985 if (!success)
986 return false;
987 uint32_t imm32;
988 switch (encoding) {
989 case eEncodingA1:
990 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
991 break;
992 default:
993 return false;
994 }
995 addr_t sp_offset = imm32;
996 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
997
998 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
999 eRegisterKindGeneric,
1000 LLDB_REGNUM_GENERIC_SP,
1001 -sp_offset };
1002
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001004 return false;
1005 }
1006 return true;
1007}
1008
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001009// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001010bool
1011EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001012{
1013#if 0
1014 // ARM pseudo code...
1015 if (ConditionPassed())
1016 {
1017 EncodingSpecificOperations();
1018 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1019 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001020 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001021 else
1022 R[d] = result;
1023 if setflags then
1024 APSR.N = result<31>;
1025 APSR.Z = IsZeroBit(result);
1026 APSR.C = carry;
1027 APSR.V = overflow;
1028 }
1029#endif
1030
1031 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001032 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001033 if (!success)
1034 return false;
1035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001037 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001039 if (!success)
1040 return false;
1041 uint32_t imm32;
1042 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001043 case eEncodingT1:
1044 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001045 case eEncodingT2:
1046 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1047 break;
1048 case eEncodingT3:
1049 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1050 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001051 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001052 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001053 break;
1054 default:
1055 return false;
1056 }
1057 addr_t sp_offset = imm32;
1058 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1059
1060 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1061 eRegisterKindGeneric,
1062 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001063 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001064
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001065 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001066 return false;
1067 }
1068 return true;
1069}
1070
Johnny Chen08c25e82011-01-31 18:02:28 +00001071// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001072bool
1073EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001074{
1075#if 0
1076 // ARM pseudo code...
1077 if (ConditionPassed())
1078 {
1079 EncodingSpecificOperations();
1080 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1081 address = if index then offset_addr else R[n];
1082 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1083 if wback then R[n] = offset_addr;
1084 }
1085#endif
1086
1087 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001088 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001089 if (!success)
1090 return false;
1091
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001092 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001093 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001094 const uint32_t addr_byte_size = GetAddressByteSize();
1095 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001096 if (!success)
1097 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001098 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001099 uint32_t imm12;
1100 switch (encoding) {
1101 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001102 Rt = Bits32(opcode, 15, 12);
1103 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001104 break;
1105 default:
1106 return false;
1107 }
1108 addr_t sp_offset = imm12;
1109 addr_t addr = sp - sp_offset;
1110
1111 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001112 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001113 {
Johnny Chen91d99862011-01-25 19:07:04 +00001114 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1115 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001116 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001117 if (!success)
1118 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001119 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001120 return false;
1121 }
1122 else
1123 {
1124 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1125 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001126 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001127 if (!success)
1128 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001129 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001130 return false;
1131 }
1132
1133 context.type = EmulateInstruction::eContextAdjustStackPointer;
1134 context.arg0 = eRegisterKindGeneric;
1135 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001136 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001137
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001139 return false;
1140 }
1141 return true;
1142}
1143
Johnny Chen08c25e82011-01-31 18:02:28 +00001144// Vector Push stores multiple extension registers to the stack.
1145// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001146bool
1147EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001148{
1149#if 0
1150 // ARM pseudo code...
1151 if (ConditionPassed())
1152 {
1153 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1154 address = SP - imm32;
1155 SP = SP - imm32;
1156 if single_regs then
1157 for r = 0 to regs-1
1158 MemA[address,4] = S[d+r]; address = address+4;
1159 else
1160 for r = 0 to regs-1
1161 // Store as two word-aligned words in the correct order for current endianness.
1162 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1163 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1164 address = address+8;
1165 }
1166#endif
1167
1168 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001169 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001170 if (!success)
1171 return false;
1172
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001173 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001174 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001175 const uint32_t addr_byte_size = GetAddressByteSize();
1176 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001177 if (!success)
1178 return false;
1179 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001180 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001181 uint32_t imm32; // stack offset
1182 uint32_t regs; // number of registers
1183 switch (encoding) {
1184 case eEncodingT1:
1185 case eEncodingA1:
1186 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001187 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001188 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1189 // If UInt(imm8) is odd, see "FSTMX".
1190 regs = Bits32(opcode, 7, 0) / 2;
1191 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1192 if (regs == 0 || regs > 16 || (d + regs) > 32)
1193 return false;
1194 break;
1195 case eEncodingT2:
1196 case eEncodingA2:
1197 single_regs = true;
1198 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1199 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1200 regs = Bits32(opcode, 7, 0);
1201 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1202 if (regs == 0 || regs > 16 || (d + regs) > 32)
1203 return false;
1204 break;
1205 default:
1206 return false;
1207 }
1208 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1209 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1210 addr_t sp_offset = imm32;
1211 addr_t addr = sp - sp_offset;
1212 uint32_t i;
1213
1214 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1215 for (i=d; i<regs; ++i)
1216 {
1217 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1218 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1219 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001221 if (!success)
1222 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001223 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001224 return false;
1225 addr += reg_byte_size;
1226 }
1227
1228 context.type = EmulateInstruction::eContextAdjustStackPointer;
1229 context.arg0 = eRegisterKindGeneric;
1230 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001231 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001232
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001233 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001234 return false;
1235 }
1236 return true;
1237}
1238
Johnny Chen587a0a42011-02-01 18:35:28 +00001239// Vector Pop loads multiple extension registers from the stack.
1240// It also updates SP to point just above the loaded data.
1241bool
1242EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1243{
1244#if 0
1245 // ARM pseudo code...
1246 if (ConditionPassed())
1247 {
1248 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1249 address = SP;
1250 SP = SP + imm32;
1251 if single_regs then
1252 for r = 0 to regs-1
1253 S[d+r] = MemA[address,4]; address = address+4;
1254 else
1255 for r = 0 to regs-1
1256 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1257 // Combine the word-aligned words in the correct order for current endianness.
1258 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1259 }
1260#endif
1261
1262 bool success = false;
1263 const uint32_t opcode = OpcodeAsUnsigned (&success);
1264 if (!success)
1265 return false;
1266
1267 if (ConditionPassed())
1268 {
1269 const uint32_t addr_byte_size = GetAddressByteSize();
1270 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1271 if (!success)
1272 return false;
1273 bool single_regs;
1274 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1275 uint32_t imm32; // stack offset
1276 uint32_t regs; // number of registers
1277 switch (encoding) {
1278 case eEncodingT1:
1279 case eEncodingA1:
1280 single_regs = false;
1281 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1282 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1283 // If UInt(imm8) is odd, see "FLDMX".
1284 regs = Bits32(opcode, 7, 0) / 2;
1285 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1286 if (regs == 0 || regs > 16 || (d + regs) > 32)
1287 return false;
1288 break;
1289 case eEncodingT2:
1290 case eEncodingA2:
1291 single_regs = true;
1292 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1293 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1294 regs = Bits32(opcode, 7, 0);
1295 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1296 if (regs == 0 || regs > 16 || (d + regs) > 32)
1297 return false;
1298 break;
1299 default:
1300 return false;
1301 }
1302 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1303 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1304 addr_t sp_offset = imm32;
1305 addr_t addr = sp;
1306 uint32_t i;
1307 uint64_t data; // uint64_t to accomodate 64-bit registers.
1308
1309 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1310 for (i=d; i<regs; ++i)
1311 {
1312 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1313 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1314 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1315 if (!success)
1316 return false;
1317 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1318 return false;
1319 addr += reg_byte_size;
1320 }
1321
1322 context.type = EmulateInstruction::eContextAdjustStackPointer;
1323 context.arg0 = eRegisterKindGeneric;
1324 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1325 context.arg2 = sp_offset;
1326
1327 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1328 return false;
1329 }
1330 return true;
1331}
1332
Johnny Chenb77be412011-02-04 00:40:18 +00001333// SVC (previously SWI)
1334bool
1335EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1336{
1337#if 0
1338 // ARM pseudo code...
1339 if (ConditionPassed())
1340 {
1341 EncodingSpecificOperations();
1342 CallSupervisor();
1343 }
1344#endif
1345
1346 bool success = false;
1347 const uint32_t opcode = OpcodeAsUnsigned (&success);
1348 if (!success)
1349 return false;
1350
1351 if (ConditionPassed())
1352 {
1353 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1354 addr_t lr; // next instruction address
1355 if (!success)
1356 return false;
1357 uint32_t imm32; // the immediate constant
1358 uint32_t mode; // ARM or Thumb mode
1359 switch (encoding) {
1360 case eEncodingT1:
1361 lr = (pc + 2) | 1u; // return address
1362 imm32 = Bits32(opcode, 7, 0);
1363 mode = eModeThumb;
1364 break;
1365 case eEncodingA1:
1366 lr = pc + 4; // return address
1367 imm32 = Bits32(opcode, 23, 0);
1368 mode = eModeARM;
1369 break;
1370 default:
1371 return false;
1372 }
1373 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1374 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1375 return false;
1376 }
1377 return true;
1378}
1379
Johnny Chenc315f862011-02-05 00:46:10 +00001380// If Then makes up to four following instructions (the IT block) conditional.
1381bool
1382EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1383{
1384#if 0
1385 // ARM pseudo code...
1386 EncodingSpecificOperations();
1387 ITSTATE.IT<7:0> = firstcond:mask;
1388#endif
1389
1390 bool success = false;
1391 const uint32_t opcode = OpcodeAsUnsigned (&success);
1392 if (!success)
1393 return false;
1394
1395 m_it_session.InitIT(Bits32(opcode, 7, 0));
1396 return true;
1397}
1398
Johnny Chen3b620b32011-02-07 20:11:47 +00001399// Branch causes a branch to a target address.
1400bool
1401EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1402{
1403#if 0
1404 // ARM pseudo code...
1405 if (ConditionPassed())
1406 {
1407 EncodingSpecificOperations();
1408 BranchWritePC(PC + imm32);
1409 }
1410#endif
1411
1412 bool success = false;
1413 const uint32_t opcode = OpcodeAsUnsigned (&success);
1414 if (!success)
1415 return false;
1416
Johnny Chen9ee056b2011-02-08 00:06:35 +00001417 if (ConditionPassed())
1418 {
1419 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1420 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001421 if (!success)
1422 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001423 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001424 int32_t imm32; // PC-relative offset
1425 switch (encoding) {
1426 case eEncodingT1:
1427 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1428 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1429 target = pc + 4 + imm32;
1430 context.arg1 = 4 + imm32; // signed offset
1431 context.arg2 = eModeThumb; // target instruction set
1432 break;
1433 case eEncodingT2:
1434 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1435 target = pc + 4 + imm32;
1436 context.arg1 = 4 + imm32; // signed offset
1437 context.arg2 = eModeThumb; // target instruction set
1438 break;
1439 case eEncodingT3:
1440 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1441 {
1442 uint32_t S = Bits32(opcode, 26, 26);
1443 uint32_t imm6 = Bits32(opcode, 21, 16);
1444 uint32_t J1 = Bits32(opcode, 13, 13);
1445 uint32_t J2 = Bits32(opcode, 11, 11);
1446 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001447 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001448 imm32 = llvm::SignExtend32<21>(imm21);
1449 target = pc + 4 + imm32;
1450 context.arg1 = eModeThumb; // target instruction set
1451 context.arg2 = 4 + imm32; // signed offset
1452 break;
1453 }
1454 case eEncodingT4:
1455 {
1456 uint32_t S = Bits32(opcode, 26, 26);
1457 uint32_t imm10 = Bits32(opcode, 25, 16);
1458 uint32_t J1 = Bits32(opcode, 13, 13);
1459 uint32_t J2 = Bits32(opcode, 11, 11);
1460 uint32_t imm11 = Bits32(opcode, 10, 0);
1461 uint32_t I1 = !(J1 ^ S);
1462 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001463 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001464 imm32 = llvm::SignExtend32<25>(imm25);
1465 target = pc + 4 + imm32;
1466 context.arg1 = eModeThumb; // target instruction set
1467 context.arg2 = 4 + imm32; // signed offset
1468 break;
1469 }
1470 case eEncodingA1:
1471 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1472 target = pc + 8 + imm32;
1473 context.arg1 = eModeARM; // target instruction set
1474 context.arg2 = 8 + imm32; // signed offset
1475 break;
1476 default:
1477 return false;
1478 }
1479 if (!BranchWritePC(context, target))
1480 return false;
1481 }
1482 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001483}
1484
Johnny Chen53ebab72011-02-08 23:21:57 +00001485// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1486// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1487// CBNZ, CBZ
1488bool
1489EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1490{
1491#if 0
1492 // ARM pseudo code...
1493 EncodingSpecificOperations();
1494 if nonzero ^ IsZero(R[n]) then
1495 BranchWritePC(PC + imm32);
1496#endif
1497
1498 bool success = false;
1499 const uint32_t opcode = OpcodeAsUnsigned (&success);
1500 if (!success)
1501 return false;
1502
1503 // Read the register value from the operand register Rn.
1504 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1505 if (!success)
1506 return false;
1507
1508 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1509 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1510 if (!success)
1511 return false;
1512
1513 addr_t target; // target address
1514 uint32_t imm32; // PC-relative offset to branch forward
1515 bool nonzero;
1516 switch (encoding) {
1517 case eEncodingT1:
1518 imm32 = Bits32(opcode, 9, 9) << 6 | Bits32(opcode, 7, 3) << 1;
1519 nonzero = BitIsSet(opcode, 11);
1520 target = pc + 4 + imm32;
1521 context.arg1 = 4 + imm32; // signed offset
1522 context.arg2 = eModeThumb; // target instruction set
1523 break;
1524 default:
1525 return false;
1526 }
1527 if (nonzero ^ (reg_val == 0))
1528 if (!BranchWritePC(context, target))
1529 return false;
1530
1531 return true;
1532}
1533
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001534// LDM loads multiple registers from consecutive memory locations, using an
1535// address from a base register. Optionally the addres just above the highest of those locations
1536// can be written back to the base register.
1537bool
1538EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1539{
1540#if 0
1541 // ARM pseudo code...
1542 if ConditionPassed()
1543 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1544 address = R[n];
1545
1546 for i = 0 to 14
1547 if registers<i> == '1' then
1548 R[i] = MemA[address, 4]; address = address + 4;
1549 if registers<15> == '1' then
1550 LoadWritePC (MemA[address, 4]);
1551
1552 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1553 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1554
1555#endif
1556
1557 bool success = false;
1558 const uint32_t opcode = OpcodeAsUnsigned (&success);
1559 if (!success)
1560 return false;
1561
1562 if (ConditionPassed())
1563 {
1564 uint32_t n;
1565 uint32_t registers = 0;
1566 bool wback;
1567 const uint32_t addr_byte_size = GetAddressByteSize();
1568 switch (encoding)
1569 {
1570 case eEncodingT1:
1571 n = Bits32 (opcode, 10, 8);
1572 registers = Bits32 (opcode, 7, 0);
1573 wback = BitIsClear (registers, n);
1574 // if BitCount(registers) < 1 then UNPREDICTABLE;
1575 if (BitCount(registers) < 1)
1576 return false;
1577 break;
1578 case eEncodingT2:
1579 n = Bits32 (opcode, 19, 16);
1580 registers = Bits32 (opcode, 15, 0);
1581 wback = BitIsSet (opcode, 21);
1582 if ((n == 15)
1583 || (BitCount (registers) < 2)
1584 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1585 return false;
1586 if (BitIsSet (registers, 15)
1587 && m_it_session.InITBlock()
1588 && !m_it_session.LastInITBlock())
1589 return false;
1590 if (wback
1591 && BitIsSet (registers, n))
1592 return false;
1593 break;
1594 case eEncodingA1:
1595 n = Bits32 (opcode, 19, 16);
1596 registers = Bits32 (opcode, 15, 0);
1597 wback = BitIsSet (opcode, 21);
1598 if ((n == 15)
1599 || (BitCount (registers) < 1))
1600 return false;
1601 break;
1602 default:
1603 return false;
1604 }
1605
1606 int32_t offset = 0;
1607 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1608 if (!success)
1609 return false;
1610
1611 for (int i = 0; i < 14; ++i)
1612 {
1613 if (BitIsSet (registers, i))
1614 {
1615 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1616 eRegisterKindDWARF,
1617 dwarf_r0 + n,
1618 offset };
1619
1620 if (wback && (n == 13)) // Pop Instruction
1621 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1622
1623 // R[i] = MemA [address, 4]; address = address + 4;
1624 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1625 if (!success)
1626 return false;
1627
1628 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1629 return false;
1630
1631 offset += addr_byte_size;
1632 }
1633 }
1634
1635 if (BitIsSet (registers, 15))
1636 {
1637 //LoadWritePC (MemA [address, 4]);
1638 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1639 eRegisterKindDWARF,
1640 dwarf_r0 + n,
1641 offset };
1642
1643 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1644 if (!success)
1645 return false;
1646 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1647 return false;
1648 }
1649
1650 if (wback && BitIsClear (registers, n))
1651 {
1652 addr_t offset = addr_byte_size * BitCount (registers);
1653 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1654 eRegisterKindDWARF,
1655 dwarf_r0 + n,
1656 offset };
1657
1658 // R[n] = R[n] + 4 * BitCount (registers)
1659 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1660 return false;
1661 }
1662 if (wback && BitIsSet (registers, n))
1663 // R[n] bits(32) UNKNOWN;
1664 return false; //I'm not convinced this is the right thing to do here...
1665 }
1666 return true;
1667}
1668
Caroline Tice0b29e242011-02-08 23:16:02 +00001669bool
1670EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1671{
1672#if 0
1673 // ARM pseudo code...
1674 if ConditionPassed() then
1675 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1676 address = R[n] - 4*BitCount(registers);
1677
1678 for i = 0 to 14
1679 if registers<i> == ’1’ then
1680 R[i] = MemA[address,4]; address = address + 4;
1681 if registers<15> == ’1’ then
1682 LoadWritePC(MemA[address,4]);
1683
1684 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1685 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1686#endif
1687
1688 bool success = false;
1689 const uint32_t opcode = OpcodeAsUnsigned (&success);
1690 if (!success)
1691 return false;
1692
1693 if (ConditionPassed())
1694 {
1695 uint32_t n;
1696 uint32_t registers = 0;
1697 bool wback;
1698 const uint32_t addr_byte_size = GetAddressByteSize();
1699 switch (encoding)
1700 {
1701 case eEncodingT1:
1702 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1703 n = Bits32 (opcode, 19, 16);
1704 registers = Bits32 (opcode, 15, 0);
1705 wback = BitIsSet (opcode, 21);
1706
1707 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1708 if ((n == 15)
1709 || (BitCount (registers) < 2)
1710 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1711 return false;
1712
1713 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1714 if (BitIsSet (registers, 15)
1715 && m_it_session.InITBlock()
1716 && !m_it_session.LastInITBlock())
1717 return false;
1718
1719 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1720 if (wback && BitIsSet (registers, n))
1721 return false;
1722
1723 break;
1724
1725 case eEncodingA1:
1726 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1727 n = Bits32 (opcode, 19, 16);
1728 registers = Bits32 (opcode, 15, 0);
1729 wback = BitIsSet (opcode, 21);
1730
1731 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1732 if ((n == 15) || (BitCount (registers) < 1))
1733 return false;
1734
1735 break;
1736
1737 default:
1738 return false;
1739 }
1740
1741 int32_t offset = 0;
1742 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1743 - (addr_byte_size * BitCount (registers));
1744
1745 for (int i = 0; i < 14; ++i)
1746 {
1747 if (BitIsSet (registers, i))
1748 {
1749 // R[i] = MemA[address,4]; address = address + 4;
1750 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1751 eRegisterKindDWARF,
1752 dwarf_r0 + n,
1753 offset };
1754
1755 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1756 if (!success)
1757 return false;
1758
1759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1760 return false;
1761
1762 offset += addr_byte_size;
1763 }
1764 }
1765
1766 // if registers<15> == ’1’ then
1767 // LoadWritePC(MemA[address,4]);
1768 if (BitIsSet (registers, 15))
1769 {
1770 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1771 eRegisterKindDWARF,
1772 dwarf_r0 + n,
1773 offset };
1774
1775 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1776 if (!success)
1777 return false;
1778 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1779 return false;
1780 }
1781
1782 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1783 if (wback && BitIsClear (registers, n))
1784 {
1785 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1786 eRegisterKindDWARF,
1787 dwarf_r0 + n,
1788 offset };
1789
1790 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1791 if (!success)
1792 return false;
1793 addr = addr - (addr_byte_size * BitCount (registers));
1794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1795 return false;
1796 }
1797
1798 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1799 if (wback && BitIsSet (registers, n))
1800 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1801 }
1802 return true;
1803}
1804
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001805EmulateInstructionARM::ARMOpcode*
1806EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001807{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001808 static ARMOpcode
1809 g_arm_opcodes[] =
1810 {
1811 //----------------------------------------------------------------------
1812 // Prologue instructions
1813 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001814
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001815 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001816 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1817 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001818
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001819 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001820 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1821 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001822 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001823 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1824 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1825 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001826
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001827 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001828 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001829
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001830 // push one register
1831 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001832 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001833
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001834 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001835 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1836 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001837
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001838 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001839 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001840 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001841
Johnny Chen9b8d7832011-02-02 01:13:56 +00001842 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1843 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1844 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1845 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001846 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1847 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001848 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001849 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1850
1851 //----------------------------------------------------------------------
1852 // Supervisor Call (previously Software Interrupt)
1853 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001854 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1855
1856 //----------------------------------------------------------------------
1857 // Branch instructions
1858 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001859 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00001860
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001861 //----------------------------------------------------------------------
1862 // Load instructions
1863 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00001864 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
1865 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001866
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001867 };
1868 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1869
1870 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1871 {
1872 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1873 return &g_arm_opcodes[i];
1874 }
1875 return NULL;
1876}
Greg Clayton64c84432011-01-21 22:02:52 +00001877
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001878
1879EmulateInstructionARM::ARMOpcode*
1880EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001881{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001882
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001883 static ARMOpcode
1884 g_thumb_opcodes[] =
1885 {
1886 //----------------------------------------------------------------------
1887 // Prologue instructions
1888 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001889
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001890 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001891 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001892 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1893 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001894 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001895 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001896
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001897 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001898 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1899 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001900
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001901 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001902 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001903
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001904 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001905 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1906 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001907 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1908 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001909
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001910 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00001911 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1912 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001913
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001914 //----------------------------------------------------------------------
1915 // Epilogue instructions
1916 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001917
Johnny Chenc28a76d2011-02-01 18:51:48 +00001918 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001919 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1920 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00001921 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1922 // J1 == J2 == 1
1923 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001924 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001925 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1926 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1927 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
1928 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001929
1930 //----------------------------------------------------------------------
1931 // Supervisor Call (previously Software Interrupt)
1932 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00001933 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
1934
1935 //----------------------------------------------------------------------
1936 // If Then makes up to four following instructions conditional.
1937 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001938 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
1939
1940 //----------------------------------------------------------------------
1941 // Branch instructions
1942 //----------------------------------------------------------------------
1943 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
1944 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
1945 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00001946 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001947 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen53ebab72011-02-08 23:21:57 +00001948 // compare and branch
1949 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001950
1951 //----------------------------------------------------------------------
1952 // Load instructions
1953 //----------------------------------------------------------------------
1954 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00001955 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
1956 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001957
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001958 };
1959
1960 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1961 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1962 {
1963 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1964 return &g_thumb_opcodes[i];
1965 }
1966 return NULL;
1967}
Greg Clayton64c84432011-01-21 22:02:52 +00001968
Greg Clayton31e2a382011-01-30 20:03:56 +00001969bool
1970EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1971{
1972 m_arm_isa = 0;
1973 const char *triple_cstr = triple.GetCString();
1974 if (triple_cstr)
1975 {
1976 const char *dash = ::strchr (triple_cstr, '-');
1977 if (dash)
1978 {
1979 std::string arch (triple_cstr, dash);
1980 const char *arch_cstr = arch.c_str();
1981 if (strcasecmp(arch_cstr, "armv4t") == 0)
1982 m_arm_isa = ARMv4T;
1983 else if (strcasecmp(arch_cstr, "armv4") == 0)
1984 m_arm_isa = ARMv4;
1985 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1986 m_arm_isa = ARMv5TEJ;
1987 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1988 m_arm_isa = ARMv5TE;
1989 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1990 m_arm_isa = ARMv5T;
1991 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1992 m_arm_isa = ARMv6K;
1993 else if (strcasecmp(arch_cstr, "armv6") == 0)
1994 m_arm_isa = ARMv6;
1995 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1996 m_arm_isa = ARMv6T2;
1997 else if (strcasecmp(arch_cstr, "armv7") == 0)
1998 m_arm_isa = ARMv7;
1999 else if (strcasecmp(arch_cstr, "armv8") == 0)
2000 m_arm_isa = ARMv8;
2001 }
2002 }
2003 return m_arm_isa != 0;
2004}
2005
2006
Greg Clayton64c84432011-01-21 22:02:52 +00002007bool
2008EmulateInstructionARM::ReadInstruction ()
2009{
2010 bool success = false;
2011 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2012 if (success)
2013 {
2014 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2015 if (success)
2016 {
2017 Context read_inst_context = {eContextReadOpcode, 0, 0};
2018 if (m_inst_cpsr & MASK_CPSR_T)
2019 {
2020 m_inst_mode = eModeThumb;
2021 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2022
2023 if (success)
2024 {
2025 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2026 {
2027 m_inst.opcode_type = eOpcode16;
2028 m_inst.opcode.inst16 = thumb_opcode;
2029 }
2030 else
2031 {
2032 m_inst.opcode_type = eOpcode32;
2033 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2034 }
2035 }
2036 }
2037 else
2038 {
2039 m_inst_mode = eModeARM;
2040 m_inst.opcode_type = eOpcode32;
2041 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2042 }
2043 }
2044 }
2045 if (!success)
2046 {
2047 m_inst_mode = eModeInvalid;
2048 m_inst_pc = LLDB_INVALID_ADDRESS;
2049 }
2050 return success;
2051}
2052
Greg Clayton64c84432011-01-21 22:02:52 +00002053bool
2054EmulateInstructionARM::ConditionPassed ()
2055{
2056 if (m_inst_cpsr == 0)
2057 return false;
2058
2059 const uint32_t cond = CurrentCond ();
2060
2061 if (cond == UINT32_MAX)
2062 return false;
2063
2064 bool result = false;
2065 switch (UnsignedBits(cond, 3, 1))
2066 {
2067 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2068 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2069 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2070 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2071 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2072 case 5:
2073 {
2074 bool n = (m_inst_cpsr & MASK_CPSR_N);
2075 bool v = (m_inst_cpsr & MASK_CPSR_V);
2076 result = n == v;
2077 }
2078 break;
2079 case 6:
2080 {
2081 bool n = (m_inst_cpsr & MASK_CPSR_N);
2082 bool v = (m_inst_cpsr & MASK_CPSR_V);
2083 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2084 }
2085 break;
2086 case 7:
2087 result = true;
2088 break;
2089 }
2090
2091 if (cond & 1)
2092 result = !result;
2093 return result;
2094}
2095
Johnny Chen9ee056b2011-02-08 00:06:35 +00002096uint32_t
2097EmulateInstructionARM::CurrentCond ()
2098{
2099 switch (m_inst_mode)
2100 {
2101 default:
2102 case eModeInvalid:
2103 break;
2104
2105 case eModeARM:
2106 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2107
2108 case eModeThumb:
2109 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2110 // 'cond' field of the encoding.
2111 if (m_inst.opcode_type == eOpcode16 &&
2112 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2113 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2114 {
2115 return Bits32(m_inst.opcode.inst16, 11, 7);
2116 }
2117 else if (m_inst.opcode_type == eOpcode32 &&
2118 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2119 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2120 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2121 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2122 {
2123 return Bits32(m_inst.opcode.inst32, 25, 22);
2124 }
2125
2126 return m_it_session.GetCond();
2127 }
2128 return UINT32_MAX; // Return invalid value
2129}
2130
2131// API client must pass in a context whose arg2 field contains the target instruction set.
2132bool
2133EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2134{
2135 addr_t target;
2136
2137 // Chech the target instruction set.
2138 switch (context.arg2)
2139 {
2140 default:
2141 assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
2142 return false;
2143 case eModeARM:
2144 target = addr & 0xfffffffc;
2145 break;
2146 case eModeThumb:
2147 target = addr & 0xfffffffe;
2148 break;
2149 }
2150 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002151 return false;
2152
2153 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002154}
2155
2156// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2157bool
2158EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2159{
2160 addr_t target;
2161
2162 if (BitIsSet(addr, 0))
2163 {
2164 target = addr & 0xfffffffe;
2165 context.arg2 = eModeThumb;
2166 }
2167 else if (BitIsClear(addr, 1))
2168 {
2169 target = addr & 0xfffffffc;
2170 context.arg2 = eModeARM;
2171 }
2172 else
2173 return false; // address<1:0> == '10' => UNPREDICTABLE
2174
2175 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002176 return false;
2177
2178 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002179}
Greg Clayton64c84432011-01-21 22:02:52 +00002180
2181bool
2182EmulateInstructionARM::EvaluateInstruction ()
2183{
Johnny Chenc315f862011-02-05 00:46:10 +00002184 // Advance the ITSTATE bits to their values for the next instruction.
2185 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2186 m_it_session.ITAdvance();
2187
Greg Clayton64c84432011-01-21 22:02:52 +00002188 return false;
2189}