blob: 1a727bf6ff2748a62cfb0162f2cdf85e6caf144b [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 Chen108d5aa2011-01-26 01:00:55 +0000224 if (BitIsSet (registers, 1u << 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 Chen108d5aa2011-01-26 01:00:55 +0000237 if (BitIsSet (registers, 1u << 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 {
348 if (BitIsSet (registers, 1u << i))
349 {
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
361 if (BitIsSet (registers, 1u << 15))
362 {
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);
768 addr_t lr; // next instruction address
769 addr_t target; // target address
770 if (!success)
771 return false;
772 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);
784 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
785 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);
801 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
802 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);
1421 addr_t target; // target address
1422 if (!success)
1423 return false;
1424 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);
1447 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) + (imm11 << 1);
1448 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);
1463 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
1464 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
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001485// LDM loads multiple registers from consecutive memory locations, using an
1486// address from a base register. Optionally the addres just above the highest of those locations
1487// can be written back to the base register.
1488bool
1489EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1490{
1491#if 0
1492 // ARM pseudo code...
1493 if ConditionPassed()
1494 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1495 address = R[n];
1496
1497 for i = 0 to 14
1498 if registers<i> == '1' then
1499 R[i] = MemA[address, 4]; address = address + 4;
1500 if registers<15> == '1' then
1501 LoadWritePC (MemA[address, 4]);
1502
1503 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1504 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1505
1506#endif
1507
1508 bool success = false;
1509 const uint32_t opcode = OpcodeAsUnsigned (&success);
1510 if (!success)
1511 return false;
1512
1513 if (ConditionPassed())
1514 {
1515 uint32_t n;
1516 uint32_t registers = 0;
1517 bool wback;
1518 const uint32_t addr_byte_size = GetAddressByteSize();
1519 switch (encoding)
1520 {
1521 case eEncodingT1:
1522 n = Bits32 (opcode, 10, 8);
1523 registers = Bits32 (opcode, 7, 0);
1524 wback = BitIsClear (registers, n);
1525 // if BitCount(registers) < 1 then UNPREDICTABLE;
1526 if (BitCount(registers) < 1)
1527 return false;
1528 break;
1529 case eEncodingT2:
1530 n = Bits32 (opcode, 19, 16);
1531 registers = Bits32 (opcode, 15, 0);
1532 wback = BitIsSet (opcode, 21);
1533 if ((n == 15)
1534 || (BitCount (registers) < 2)
1535 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1536 return false;
1537 if (BitIsSet (registers, 15)
1538 && m_it_session.InITBlock()
1539 && !m_it_session.LastInITBlock())
1540 return false;
1541 if (wback
1542 && BitIsSet (registers, n))
1543 return false;
1544 break;
1545 case eEncodingA1:
1546 n = Bits32 (opcode, 19, 16);
1547 registers = Bits32 (opcode, 15, 0);
1548 wback = BitIsSet (opcode, 21);
1549 if ((n == 15)
1550 || (BitCount (registers) < 1))
1551 return false;
1552 break;
1553 default:
1554 return false;
1555 }
1556
1557 int32_t offset = 0;
1558 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1559 if (!success)
1560 return false;
1561
1562 for (int i = 0; i < 14; ++i)
1563 {
1564 if (BitIsSet (registers, i))
1565 {
1566 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1567 eRegisterKindDWARF,
1568 dwarf_r0 + n,
1569 offset };
1570
1571 if (wback && (n == 13)) // Pop Instruction
1572 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1573
1574 // R[i] = MemA [address, 4]; address = address + 4;
1575 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1576 if (!success)
1577 return false;
1578
1579 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1580 return false;
1581
1582 offset += addr_byte_size;
1583 }
1584 }
1585
1586 if (BitIsSet (registers, 15))
1587 {
1588 //LoadWritePC (MemA [address, 4]);
1589 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1590 eRegisterKindDWARF,
1591 dwarf_r0 + n,
1592 offset };
1593
1594 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1595 if (!success)
1596 return false;
1597 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1598 return false;
1599 }
1600
1601 if (wback && BitIsClear (registers, n))
1602 {
1603 addr_t offset = addr_byte_size * BitCount (registers);
1604 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1605 eRegisterKindDWARF,
1606 dwarf_r0 + n,
1607 offset };
1608
1609 // R[n] = R[n] + 4 * BitCount (registers)
1610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1611 return false;
1612 }
1613 if (wback && BitIsSet (registers, n))
1614 // R[n] bits(32) UNKNOWN;
1615 return false; //I'm not convinced this is the right thing to do here...
1616 }
1617 return true;
1618}
1619
Caroline Tice0b29e242011-02-08 23:16:02 +00001620bool
1621EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1622{
1623#if 0
1624 // ARM pseudo code...
1625 if ConditionPassed() then
1626 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1627 address = R[n] - 4*BitCount(registers);
1628
1629 for i = 0 to 14
1630 if registers<i> == ’1’ then
1631 R[i] = MemA[address,4]; address = address + 4;
1632 if registers<15> == ’1’ then
1633 LoadWritePC(MemA[address,4]);
1634
1635 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1636 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1637#endif
1638
1639 bool success = false;
1640 const uint32_t opcode = OpcodeAsUnsigned (&success);
1641 if (!success)
1642 return false;
1643
1644 if (ConditionPassed())
1645 {
1646 uint32_t n;
1647 uint32_t registers = 0;
1648 bool wback;
1649 const uint32_t addr_byte_size = GetAddressByteSize();
1650 switch (encoding)
1651 {
1652 case eEncodingT1:
1653 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1654 n = Bits32 (opcode, 19, 16);
1655 registers = Bits32 (opcode, 15, 0);
1656 wback = BitIsSet (opcode, 21);
1657
1658 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1659 if ((n == 15)
1660 || (BitCount (registers) < 2)
1661 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1662 return false;
1663
1664 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1665 if (BitIsSet (registers, 15)
1666 && m_it_session.InITBlock()
1667 && !m_it_session.LastInITBlock())
1668 return false;
1669
1670 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1671 if (wback && BitIsSet (registers, n))
1672 return false;
1673
1674 break;
1675
1676 case eEncodingA1:
1677 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1678 n = Bits32 (opcode, 19, 16);
1679 registers = Bits32 (opcode, 15, 0);
1680 wback = BitIsSet (opcode, 21);
1681
1682 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1683 if ((n == 15) || (BitCount (registers) < 1))
1684 return false;
1685
1686 break;
1687
1688 default:
1689 return false;
1690 }
1691
1692 int32_t offset = 0;
1693 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1694 - (addr_byte_size * BitCount (registers));
1695
1696 for (int i = 0; i < 14; ++i)
1697 {
1698 if (BitIsSet (registers, i))
1699 {
1700 // R[i] = MemA[address,4]; address = address + 4;
1701 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1702 eRegisterKindDWARF,
1703 dwarf_r0 + n,
1704 offset };
1705
1706 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1707 if (!success)
1708 return false;
1709
1710 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1711 return false;
1712
1713 offset += addr_byte_size;
1714 }
1715 }
1716
1717 // if registers<15> == ’1’ then
1718 // LoadWritePC(MemA[address,4]);
1719 if (BitIsSet (registers, 15))
1720 {
1721 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1722 eRegisterKindDWARF,
1723 dwarf_r0 + n,
1724 offset };
1725
1726 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1727 if (!success)
1728 return false;
1729 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1730 return false;
1731 }
1732
1733 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1734 if (wback && BitIsClear (registers, n))
1735 {
1736 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1737 eRegisterKindDWARF,
1738 dwarf_r0 + n,
1739 offset };
1740
1741 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1742 if (!success)
1743 return false;
1744 addr = addr - (addr_byte_size * BitCount (registers));
1745 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1746 return false;
1747 }
1748
1749 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1750 if (wback && BitIsSet (registers, n))
1751 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1752 }
1753 return true;
1754}
1755
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001756EmulateInstructionARM::ARMOpcode*
1757EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001758{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001759 static ARMOpcode
1760 g_arm_opcodes[] =
1761 {
1762 //----------------------------------------------------------------------
1763 // Prologue instructions
1764 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001765
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001766 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001767 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1768 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001769
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001770 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001771 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1772 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001773 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001774 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1775 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1776 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001777
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001778 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001779 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001780
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001781 // push one register
1782 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001783 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001784
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001785 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001786 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1787 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001788
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001789 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001790 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001791 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001792
Johnny Chen9b8d7832011-02-02 01:13:56 +00001793 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1794 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1795 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1796 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001797 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1798 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001799 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001800 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1801
1802 //----------------------------------------------------------------------
1803 // Supervisor Call (previously Software Interrupt)
1804 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001805 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1806
1807 //----------------------------------------------------------------------
1808 // Branch instructions
1809 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001810 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00001811
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001812 //----------------------------------------------------------------------
1813 // Load instructions
1814 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00001815 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
1816 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001817
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001818 };
1819 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1820
1821 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1822 {
1823 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1824 return &g_arm_opcodes[i];
1825 }
1826 return NULL;
1827}
Greg Clayton64c84432011-01-21 22:02:52 +00001828
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001829
1830EmulateInstructionARM::ARMOpcode*
1831EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001832{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001833
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001834 static ARMOpcode
1835 g_thumb_opcodes[] =
1836 {
1837 //----------------------------------------------------------------------
1838 // Prologue instructions
1839 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001840
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001841 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001842 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001843 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1844 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001845 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001846 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001847
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001848 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001849 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1850 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001851
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001852 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001853 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001854
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001855 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001856 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1857 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001858 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1859 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001860
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001861 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00001862 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1863 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001864
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001865 //----------------------------------------------------------------------
1866 // Epilogue instructions
1867 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001868
Johnny Chenc28a76d2011-02-01 18:51:48 +00001869 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001870 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1871 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00001872 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1873 // J1 == J2 == 1
1874 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001875 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001876 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1877 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1878 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
1879 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001880
1881 //----------------------------------------------------------------------
1882 // Supervisor Call (previously Software Interrupt)
1883 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00001884 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
1885
1886 //----------------------------------------------------------------------
1887 // If Then makes up to four following instructions conditional.
1888 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001889 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
1890
1891 //----------------------------------------------------------------------
1892 // Branch instructions
1893 //----------------------------------------------------------------------
1894 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
1895 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
1896 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00001897 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001898 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chenb77be412011-02-04 00:40:18 +00001899
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001900
1901 //----------------------------------------------------------------------
1902 // Load instructions
1903 //----------------------------------------------------------------------
1904 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00001905 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
1906 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001907
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001908 };
1909
1910 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1911 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1912 {
1913 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1914 return &g_thumb_opcodes[i];
1915 }
1916 return NULL;
1917}
Greg Clayton64c84432011-01-21 22:02:52 +00001918
Greg Clayton31e2a382011-01-30 20:03:56 +00001919bool
1920EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1921{
1922 m_arm_isa = 0;
1923 const char *triple_cstr = triple.GetCString();
1924 if (triple_cstr)
1925 {
1926 const char *dash = ::strchr (triple_cstr, '-');
1927 if (dash)
1928 {
1929 std::string arch (triple_cstr, dash);
1930 const char *arch_cstr = arch.c_str();
1931 if (strcasecmp(arch_cstr, "armv4t") == 0)
1932 m_arm_isa = ARMv4T;
1933 else if (strcasecmp(arch_cstr, "armv4") == 0)
1934 m_arm_isa = ARMv4;
1935 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1936 m_arm_isa = ARMv5TEJ;
1937 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1938 m_arm_isa = ARMv5TE;
1939 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1940 m_arm_isa = ARMv5T;
1941 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1942 m_arm_isa = ARMv6K;
1943 else if (strcasecmp(arch_cstr, "armv6") == 0)
1944 m_arm_isa = ARMv6;
1945 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1946 m_arm_isa = ARMv6T2;
1947 else if (strcasecmp(arch_cstr, "armv7") == 0)
1948 m_arm_isa = ARMv7;
1949 else if (strcasecmp(arch_cstr, "armv8") == 0)
1950 m_arm_isa = ARMv8;
1951 }
1952 }
1953 return m_arm_isa != 0;
1954}
1955
1956
Greg Clayton64c84432011-01-21 22:02:52 +00001957bool
1958EmulateInstructionARM::ReadInstruction ()
1959{
1960 bool success = false;
1961 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1962 if (success)
1963 {
1964 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1965 if (success)
1966 {
1967 Context read_inst_context = {eContextReadOpcode, 0, 0};
1968 if (m_inst_cpsr & MASK_CPSR_T)
1969 {
1970 m_inst_mode = eModeThumb;
1971 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
1972
1973 if (success)
1974 {
1975 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
1976 {
1977 m_inst.opcode_type = eOpcode16;
1978 m_inst.opcode.inst16 = thumb_opcode;
1979 }
1980 else
1981 {
1982 m_inst.opcode_type = eOpcode32;
1983 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
1984 }
1985 }
1986 }
1987 else
1988 {
1989 m_inst_mode = eModeARM;
1990 m_inst.opcode_type = eOpcode32;
1991 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
1992 }
1993 }
1994 }
1995 if (!success)
1996 {
1997 m_inst_mode = eModeInvalid;
1998 m_inst_pc = LLDB_INVALID_ADDRESS;
1999 }
2000 return success;
2001}
2002
Greg Clayton64c84432011-01-21 22:02:52 +00002003bool
2004EmulateInstructionARM::ConditionPassed ()
2005{
2006 if (m_inst_cpsr == 0)
2007 return false;
2008
2009 const uint32_t cond = CurrentCond ();
2010
2011 if (cond == UINT32_MAX)
2012 return false;
2013
2014 bool result = false;
2015 switch (UnsignedBits(cond, 3, 1))
2016 {
2017 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2018 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2019 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2020 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2021 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2022 case 5:
2023 {
2024 bool n = (m_inst_cpsr & MASK_CPSR_N);
2025 bool v = (m_inst_cpsr & MASK_CPSR_V);
2026 result = n == v;
2027 }
2028 break;
2029 case 6:
2030 {
2031 bool n = (m_inst_cpsr & MASK_CPSR_N);
2032 bool v = (m_inst_cpsr & MASK_CPSR_V);
2033 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2034 }
2035 break;
2036 case 7:
2037 result = true;
2038 break;
2039 }
2040
2041 if (cond & 1)
2042 result = !result;
2043 return result;
2044}
2045
Johnny Chen9ee056b2011-02-08 00:06:35 +00002046uint32_t
2047EmulateInstructionARM::CurrentCond ()
2048{
2049 switch (m_inst_mode)
2050 {
2051 default:
2052 case eModeInvalid:
2053 break;
2054
2055 case eModeARM:
2056 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2057
2058 case eModeThumb:
2059 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2060 // 'cond' field of the encoding.
2061 if (m_inst.opcode_type == eOpcode16 &&
2062 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2063 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2064 {
2065 return Bits32(m_inst.opcode.inst16, 11, 7);
2066 }
2067 else if (m_inst.opcode_type == eOpcode32 &&
2068 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2069 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2070 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2071 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2072 {
2073 return Bits32(m_inst.opcode.inst32, 25, 22);
2074 }
2075
2076 return m_it_session.GetCond();
2077 }
2078 return UINT32_MAX; // Return invalid value
2079}
2080
2081// API client must pass in a context whose arg2 field contains the target instruction set.
2082bool
2083EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2084{
2085 addr_t target;
2086
2087 // Chech the target instruction set.
2088 switch (context.arg2)
2089 {
2090 default:
2091 assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
2092 return false;
2093 case eModeARM:
2094 target = addr & 0xfffffffc;
2095 break;
2096 case eModeThumb:
2097 target = addr & 0xfffffffe;
2098 break;
2099 }
2100 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
2101 return false;
2102 return false;
2103}
2104
2105// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2106bool
2107EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2108{
2109 addr_t target;
2110
2111 if (BitIsSet(addr, 0))
2112 {
2113 target = addr & 0xfffffffe;
2114 context.arg2 = eModeThumb;
2115 }
2116 else if (BitIsClear(addr, 1))
2117 {
2118 target = addr & 0xfffffffc;
2119 context.arg2 = eModeARM;
2120 }
2121 else
2122 return false; // address<1:0> == '10' => UNPREDICTABLE
2123
2124 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
2125 return false;
2126 return false;
2127}
Greg Clayton64c84432011-01-21 22:02:52 +00002128
2129bool
2130EmulateInstructionARM::EvaluateInstruction ()
2131{
Johnny Chenc315f862011-02-05 00:46:10 +00002132 // Advance the ITSTATE bits to their values for the next instruction.
2133 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2134 m_it_session.ITAdvance();
2135
Greg Clayton64c84432011-01-21 22:02:52 +00002136 return false;
2137}