blob: bfc6827ad7f22cd1ba5ae5ada8622ce6cb9fcb8c [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
Greg Claytonf29a08f2011-02-09 17:41:27 +000013#include "Plugins/Process/Utility/ARMDefines.h"
14#include "Plugins/Process/Utility/ARMUtils.h"
15#include "Utility/ARM_DWARF_Registers.h"
16
Johnny Chen9b8d7832011-02-02 01:13:56 +000017#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000018 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000019
20using namespace lldb;
21using namespace lldb_private;
22
Johnny Chend6c13f02011-02-08 20:36:34 +000023static inline uint32_t Align(uint32_t val, uint32_t alignment)
24{
25 return alignment * (val / alignment);
26}
27
Johnny Chen93070472011-02-04 23:02:47 +000028// A8.6.50
29// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
30static unsigned short CountITSize(unsigned ITMask) {
31 // First count the trailing zeros of the IT mask.
32 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
33 if (TZ > 3)
34 {
35 printf("Encoding error: IT Mask '0000'\n");
36 return 0;
37 }
38 return (4 - TZ);
39}
40
41// Init ITState. Note that at least one bit is always 1 in mask.
42bool ITSession::InitIT(unsigned short bits7_0)
43{
44 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
45 if (ITCounter == 0)
46 return false;
47
48 // A8.6.50 IT
49 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
50 if (FirstCond == 0xF)
51 {
52 printf("Encoding error: IT FirstCond '1111'\n");
53 return false;
54 }
55 if (FirstCond == 0xE && ITCounter != 1)
56 {
57 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
58 return false;
59 }
60
61 ITState = bits7_0;
62 return true;
63}
64
65// Update ITState if necessary.
66void ITSession::ITAdvance()
67{
68 assert(ITCounter);
69 --ITCounter;
70 if (ITCounter == 0)
71 ITState = 0;
72 else
73 {
74 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
75 SetBits32(ITState, 4, 0, NewITState4_0);
76 }
77}
78
79// Return true if we're inside an IT Block.
80bool ITSession::InITBlock()
81{
82 return ITCounter != 0;
83}
84
Johnny Chenc315f862011-02-05 00:46:10 +000085// Return true if we're the last instruction inside an IT Block.
86bool ITSession::LastInITBlock()
87{
88 return ITCounter == 1;
89}
90
Johnny Chen93070472011-02-04 23:02:47 +000091// Get condition bits for the current thumb instruction.
92uint32_t ITSession::GetCond()
93{
Johnny Chenc315f862011-02-05 00:46:10 +000094 if (InITBlock())
95 return Bits32(ITState, 7, 4);
96 else
97 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000098}
99
Greg Clayton64c84432011-01-21 22:02:52 +0000100// ARM constants used during decoding
101#define REG_RD 0
102#define LDM_REGLIST 1
103#define PC_REG 15
104#define PC_REGLIST_BIT 0x8000
105
Johnny Chen251af6a2011-01-21 22:47:25 +0000106#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000107#define ARMv4T (1u << 1)
108#define ARMv5T (1u << 2)
109#define ARMv5TE (1u << 3)
110#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000111#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000112#define ARMv6K (1u << 6)
113#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000115#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000116#define ARMvAll (0xffffffffu)
117
Johnny Chen9b8d7832011-02-02 01:13:56 +0000118#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
119#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
120#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000121
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000122void
123EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000124{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000125}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000126
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000127void
128EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000129{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000130}
131
Johnny Chen08c25e82011-01-31 18:02:28 +0000132// Push Multiple Registers stores multiple registers to the stack, storing to
133// consecutive memory locations ending just below the address in SP, and updates
134// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000135bool
136EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000137{
138#if 0
139 // ARM pseudo code...
140 if (ConditionPassed())
141 {
142 EncodingSpecificOperations();
143 NullCheckIfThumbEE(13);
144 address = SP - 4*BitCount(registers);
145
146 for (i = 0 to 14)
147 {
148 if (registers<i> == ’1’)
149 {
150 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
151 MemA[address,4] = bits(32) UNKNOWN;
152 else
153 MemA[address,4] = R[i];
154 address = address + 4;
155 }
156 }
157
158 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
159 MemA[address,4] = PCStoreValue();
160
161 SP = SP - 4*BitCount(registers);
162 }
163#endif
164
165 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000167 if (!success)
168 return false;
169
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000170 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000171 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000172 const uint32_t addr_byte_size = GetAddressByteSize();
173 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000174 if (!success)
175 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000176 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000177 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000178 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000179 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000180 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000181 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000182 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000183 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000184 // if BitCount(registers) < 1 then UNPREDICTABLE;
185 if (BitCount(registers) < 1)
186 return false;
187 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000188 case eEncodingT2:
189 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000190 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000191 // if BitCount(registers) < 2 then UNPREDICTABLE;
192 if (BitCount(registers) < 2)
193 return false;
194 break;
195 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000196 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000197 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000198 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000199 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000200 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000201 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000202 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000203 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000204 // Instead of return false, let's handle the following case as well,
205 // which amounts to pushing one reg onto the full descending stacks.
206 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000207 break;
208 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000209 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000210 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000211 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000212 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000213 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000214 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000215 default:
216 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000217 }
Johnny Chence1ca772011-01-25 01:13:00 +0000218 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000219 addr_t addr = sp - sp_offset;
220 uint32_t i;
221
222 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
223 for (i=0; i<15; ++i)
224 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000225 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
227 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
228 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000229 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000230 if (!success)
231 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000232 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000233 return false;
234 addr += addr_byte_size;
235 }
236 }
237
Johnny Chen7c1bf922011-02-08 23:49:37 +0000238 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000239 {
240 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000241 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000242 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000243 if (!success)
244 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000245 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000246 return false;
247 }
248
249 context.type = EmulateInstruction::eContextAdjustStackPointer;
250 context.arg0 = eRegisterKindGeneric;
251 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000252 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000253
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000254 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000255 return false;
256 }
257 return true;
258}
259
Johnny Chenef85e912011-01-31 23:07:40 +0000260// Pop Multiple Registers loads multiple registers from the stack, loading from
261// consecutive memory locations staring at the address in SP, and updates
262// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000263bool
264EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000265{
266#if 0
267 // ARM pseudo code...
268 if (ConditionPassed())
269 {
270 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
271 address = SP;
272 for i = 0 to 14
273 if registers<i> == ‘1’ then
274 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
275 if registers<15> == ‘1’ then
276 if UnalignedAllowed then
277 LoadWritePC(MemU[address,4]);
278 else
279 LoadWritePC(MemA[address,4]);
280 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
281 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
282 }
283#endif
284
285 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000286 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000287 if (!success)
288 return false;
289
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000290 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000291 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000292 const uint32_t addr_byte_size = GetAddressByteSize();
293 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000294 if (!success)
295 return false;
296 uint32_t registers = 0;
297 uint32_t Rt; // the destination register
298 switch (encoding) {
299 case eEncodingT1:
300 registers = Bits32(opcode, 7, 0);
301 // The P bit represents PC.
302 if (Bits32(opcode, 8, 8))
303 registers |= (1u << 15);
304 // if BitCount(registers) < 1 then UNPREDICTABLE;
305 if (BitCount(registers) < 1)
306 return false;
307 break;
308 case eEncodingT2:
309 // Ignore bit 13.
310 registers = Bits32(opcode, 15, 0) & ~0x2000;
311 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
312 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
313 return false;
314 break;
315 case eEncodingT3:
316 Rt = Bits32(opcode, 15, 12);
317 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
318 if (Rt == dwarf_sp)
319 return false;
320 registers = (1u << Rt);
321 break;
322 case eEncodingA1:
323 registers = Bits32(opcode, 15, 0);
324 // Instead of return false, let's handle the following case as well,
325 // which amounts to popping one reg from the full descending stacks.
326 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
327
328 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
329 if (Bits32(opcode, 13, 13))
330 return false;
331 break;
332 case eEncodingA2:
333 Rt = Bits32(opcode, 15, 12);
334 // if t == 13 then UNPREDICTABLE;
335 if (Rt == dwarf_sp)
336 return false;
337 registers = (1u << Rt);
338 break;
339 default:
340 return false;
341 }
342 addr_t sp_offset = addr_byte_size * BitCount (registers);
343 addr_t addr = sp;
344 uint32_t i, data;
345
346 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
347 for (i=0; i<15; ++i)
348 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000349 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000350 {
351 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
352 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000353 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000354 if (!success)
355 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000356 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000357 return false;
358 addr += addr_byte_size;
359 }
360 }
361
Johnny Chen7c1bf922011-02-08 23:49:37 +0000362 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000363 {
364 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
365 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000366 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000367 if (!success)
368 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000369 // In ARMv5T and above, this is an interworking branch.
370 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000371 return false;
372 addr += addr_byte_size;
373 }
374
375 context.type = EmulateInstruction::eContextAdjustStackPointer;
376 context.arg0 = eRegisterKindGeneric;
377 context.arg1 = LLDB_REGNUM_GENERIC_SP;
378 context.arg2 = sp_offset;
379
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000380 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000381 return false;
382 }
383 return true;
384}
385
Johnny Chen5b442b72011-01-27 19:34:30 +0000386// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000387// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000388bool
389EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000390{
391#if 0
392 // ARM pseudo code...
393 if (ConditionPassed())
394 {
395 EncodingSpecificOperations();
396 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
397 if d == 15 then
398 ALUWritePC(result); // setflags is always FALSE here
399 else
400 R[d] = result;
401 if setflags then
402 APSR.N = result<31>;
403 APSR.Z = IsZeroBit(result);
404 APSR.C = carry;
405 APSR.V = overflow;
406 }
407#endif
408
409 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000410 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000411 if (!success)
412 return false;
413
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000415 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000416 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000417 if (!success)
418 return false;
419 uint32_t Rd; // the destination register
420 uint32_t imm32;
421 switch (encoding) {
422 case eEncodingT1:
423 Rd = 7;
424 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
425 break;
426 case eEncodingA1:
427 Rd = Bits32(opcode, 15, 12);
428 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
429 break;
430 default:
431 return false;
432 }
433 addr_t sp_offset = imm32;
434 addr_t addr = sp + sp_offset; // a pointer to the stack area
435
436 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
437 eRegisterKindGeneric,
438 LLDB_REGNUM_GENERIC_SP,
439 sp_offset };
440
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000441 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000442 return false;
443 }
444 return true;
445}
446
Johnny Chen2ccad832011-01-28 19:57:25 +0000447// Set r7 or ip to the current stack pointer.
448// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000449bool
450EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000451{
452#if 0
453 // ARM pseudo code...
454 if (ConditionPassed())
455 {
456 EncodingSpecificOperations();
457 result = R[m];
458 if d == 15 then
459 ALUWritePC(result); // setflags is always FALSE here
460 else
461 R[d] = result;
462 if setflags then
463 APSR.N = result<31>;
464 APSR.Z = IsZeroBit(result);
465 // APSR.C unchanged
466 // APSR.V unchanged
467 }
468#endif
469
470 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000471 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000472 //if (!success)
473 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000474
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000475 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000476 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000477 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000478 if (!success)
479 return false;
480 uint32_t Rd; // the destination register
481 switch (encoding) {
482 case eEncodingT1:
483 Rd = 7;
484 break;
485 case eEncodingA1:
486 Rd = 12;
487 break;
488 default:
489 return false;
490 }
491 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
492 eRegisterKindGeneric,
493 LLDB_REGNUM_GENERIC_SP,
494 0 };
495
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000497 return false;
498 }
499 return true;
500}
501
Johnny Chen1c13b622011-01-29 00:11:15 +0000502// Move from high register (r8-r15) to low register (r0-r7).
503// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504bool
505EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000506{
507#if 0
508 // ARM pseudo code...
509 if (ConditionPassed())
510 {
511 EncodingSpecificOperations();
512 result = R[m];
513 if d == 15 then
514 ALUWritePC(result); // setflags is always FALSE here
515 else
516 R[d] = result;
517 if setflags then
518 APSR.N = result<31>;
519 APSR.Z = IsZeroBit(result);
520 // APSR.C unchanged
521 // APSR.V unchanged
522 }
523#endif
524
525 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000526 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000527 if (!success)
528 return false;
529
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000531 {
532 uint32_t Rm; // the source register
533 uint32_t Rd; // the destination register
534 switch (encoding) {
535 case eEncodingT1:
536 Rm = Bits32(opcode, 6, 3);
537 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
538 break;
539 default:
540 return false;
541 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000542 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000543 if (!success)
544 return false;
545
546 // The context specifies that Rm is to be moved into Rd.
547 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
548 eRegisterKindDWARF,
549 dwarf_r0 + Rm,
550 0 };
551
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000552 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000553 return false;
554 }
555 return true;
556}
557
Johnny Chen788e0552011-01-27 22:52:23 +0000558// PC relative immediate load into register, possibly followed by ADD (SP plus register).
559// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000560bool
561EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000562{
563#if 0
564 // ARM pseudo code...
565 if (ConditionPassed())
566 {
567 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
568 base = Align(PC,4);
569 address = if add then (base + imm32) else (base - imm32);
570 data = MemU[address,4];
571 if t == 15 then
572 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
573 elsif UnalignedSupport() || address<1:0> = ‘00’ then
574 R[t] = data;
575 else // Can only apply before ARMv7
576 if CurrentInstrSet() == InstrSet_ARM then
577 R[t] = ROR(data, 8*UInt(address<1:0>));
578 else
579 R[t] = bits(32) UNKNOWN;
580 }
581#endif
582
583 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000584 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000585 if (!success)
586 return false;
587
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000588 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000589 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000590 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000591 if (!success)
592 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000593
594 // PC relative immediate load context
595 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
596 eRegisterKindGeneric,
597 LLDB_REGNUM_GENERIC_PC,
598 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000599 uint32_t Rd; // the destination register
600 uint32_t imm32; // immediate offset from the PC
601 addr_t addr; // the PC relative address
602 uint32_t data; // the literal data value from the PC relative load
603 switch (encoding) {
604 case eEncodingT1:
605 Rd = Bits32(opcode, 10, 8);
606 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
607 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000608 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000609 break;
610 default:
611 return false;
612 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000613 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000614 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000615 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000616 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000617 return false;
618 }
619 return true;
620}
621
Johnny Chen5b442b72011-01-27 19:34:30 +0000622// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000623// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000624bool
625EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000626{
627#if 0
628 // ARM pseudo code...
629 if (ConditionPassed())
630 {
631 EncodingSpecificOperations();
632 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
633 if d == 15 then // Can only occur for ARM encoding
634 ALUWritePC(result); // setflags is always FALSE here
635 else
636 R[d] = result;
637 if setflags then
638 APSR.N = result<31>;
639 APSR.Z = IsZeroBit(result);
640 APSR.C = carry;
641 APSR.V = overflow;
642 }
643#endif
644
645 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000646 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000647 if (!success)
648 return false;
649
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000650 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000651 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000652 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000653 if (!success)
654 return false;
655 uint32_t imm32; // the immediate operand
656 switch (encoding) {
657 case eEncodingT2:
658 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
659 break;
660 default:
661 return false;
662 }
663 addr_t sp_offset = imm32;
664 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
665
666 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
667 eRegisterKindGeneric,
668 LLDB_REGNUM_GENERIC_SP,
669 sp_offset };
670
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000671 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000672 return false;
673 }
674 return true;
675}
676
677// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000678// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000679bool
680EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000681{
682#if 0
683 // ARM pseudo code...
684 if (ConditionPassed())
685 {
686 EncodingSpecificOperations();
687 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
688 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
689 if d == 15 then
690 ALUWritePC(result); // setflags is always FALSE here
691 else
692 R[d] = result;
693 if setflags then
694 APSR.N = result<31>;
695 APSR.Z = IsZeroBit(result);
696 APSR.C = carry;
697 APSR.V = overflow;
698 }
699#endif
700
701 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000702 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000703 if (!success)
704 return false;
705
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000706 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000707 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000708 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000709 if (!success)
710 return false;
711 uint32_t Rm; // the second operand
712 switch (encoding) {
713 case eEncodingT2:
714 Rm = Bits32(opcode, 6, 3);
715 break;
716 default:
717 return false;
718 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000719 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000720 if (!success)
721 return false;
722
723 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
724
725 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
726 eRegisterKindGeneric,
727 LLDB_REGNUM_GENERIC_SP,
728 reg_value };
729
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000730 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000731 return false;
732 }
733 return true;
734}
735
Johnny Chen9b8d7832011-02-02 01:13:56 +0000736// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
737// at a PC-relative address, and changes instruction set from ARM to Thumb, or
738// from Thumb to ARM.
739// BLX (immediate)
740bool
741EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
742{
743#if 0
744 // ARM pseudo code...
745 if (ConditionPassed())
746 {
747 EncodingSpecificOperations();
748 if CurrentInstrSet() == InstrSet_ARM then
749 LR = PC - 4;
750 else
751 LR = PC<31:1> : '1';
752 if targetInstrSet == InstrSet_ARM then
753 targetAddress = Align(PC,4) + imm32;
754 else
755 targetAddress = PC + imm32;
756 SelectInstrSet(targetInstrSet);
757 BranchWritePC(targetAddress);
758 }
759#endif
760
761 bool success = false;
762 const uint32_t opcode = OpcodeAsUnsigned (&success);
763 if (!success)
764 return false;
765
766 if (ConditionPassed())
767 {
768 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
769 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000770 if (!success)
771 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000772 addr_t lr; // next instruction address
773 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000774 int32_t imm32; // PC-relative offset
775 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000776 case eEncodingT1:
777 {
778 lr = (pc + 4) | 1u; // return address
779 uint32_t S = Bits32(opcode, 26, 26);
780 uint32_t imm10 = Bits32(opcode, 25, 16);
781 uint32_t J1 = Bits32(opcode, 13, 13);
782 uint32_t J2 = Bits32(opcode, 11, 11);
783 uint32_t imm11 = Bits32(opcode, 10, 0);
784 uint32_t I1 = !(J1 ^ S);
785 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000786 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000787 imm32 = llvm::SignExtend32<25>(imm25);
788 target = pc + 4 + imm32;
789 context.arg1 = 4 + imm32; // signed offset
790 context.arg2 = eModeThumb; // target instruction set
791 break;
792 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000793 case eEncodingT2:
794 {
795 lr = (pc + 4) | 1u; // return address
796 uint32_t S = Bits32(opcode, 26, 26);
797 uint32_t imm10H = Bits32(opcode, 25, 16);
798 uint32_t J1 = Bits32(opcode, 13, 13);
799 uint32_t J2 = Bits32(opcode, 11, 11);
800 uint32_t imm10L = Bits32(opcode, 10, 1);
801 uint32_t I1 = !(J1 ^ S);
802 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000803 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000804 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000805 target = Align(pc + 4, 4) + imm32;
806 context.arg1 = 4 + imm32; // signed offset
807 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000808 break;
809 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000810 case eEncodingA1:
811 lr = pc + 4; // return address
812 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000813 target = Align(pc + 8, 4) + imm32;
814 context.arg1 = 8 + imm32; // signed offset
815 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000816 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000817 case eEncodingA2:
818 lr = pc + 4; // return address
819 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
820 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000821 context.arg1 = 8 + imm32; // signed offset
822 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000823 break;
824 default:
825 return false;
826 }
827 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
828 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000829 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000830 return false;
831 }
832 return true;
833}
834
835// Branch with Link and Exchange (register) calls a subroutine at an address and
836// instruction set specified by a register.
837// BLX (register)
838bool
839EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
840{
841#if 0
842 // ARM pseudo code...
843 if (ConditionPassed())
844 {
845 EncodingSpecificOperations();
846 target = R[m];
847 if CurrentInstrSet() == InstrSet_ARM then
848 next_instr_addr = PC - 4;
849 LR = next_instr_addr;
850 else
851 next_instr_addr = PC - 2;
852 LR = next_instr_addr<31:1> : ‘1’;
853 BXWritePC(target);
854 }
855#endif
856
857 bool success = false;
858 const uint32_t opcode = OpcodeAsUnsigned (&success);
859 if (!success)
860 return false;
861
862 if (ConditionPassed())
863 {
864 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
865 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
866 addr_t lr; // next instruction address
867 addr_t target; // target address
868 if (!success)
869 return false;
870 uint32_t Rm; // the register with the target address
871 switch (encoding) {
872 case eEncodingT1:
873 lr = (pc + 2) | 1u; // return address
874 Rm = Bits32(opcode, 6, 3);
875 // if m == 15 then UNPREDICTABLE;
876 if (Rm == 15)
877 return false;
878 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
879 break;
880 case eEncodingA1:
881 lr = pc + 4; // return address
882 Rm = Bits32(opcode, 3, 0);
883 // if m == 15 then UNPREDICTABLE;
884 if (Rm == 15)
885 return false;
886 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000887 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000888 default:
889 return false;
890 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000891 context.arg0 = eRegisterKindDWARF;
892 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000893 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
894 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000895 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000896 return false;
897 }
898 return true;
899}
900
Johnny Chen0d0148e2011-01-28 02:26:08 +0000901// Set r7 to point to some ip offset.
902// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000903bool
904EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000905{
906#if 0
907 // ARM pseudo code...
908 if (ConditionPassed())
909 {
910 EncodingSpecificOperations();
911 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
912 if d == 15 then // Can only occur for ARM encoding
913 ALUWritePC(result); // setflags is always FALSE here
914 else
915 R[d] = result;
916 if setflags then
917 APSR.N = result<31>;
918 APSR.Z = IsZeroBit(result);
919 APSR.C = carry;
920 APSR.V = overflow;
921 }
922#endif
923
924 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000925 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000926 if (!success)
927 return false;
928
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000929 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000930 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000931 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000932 if (!success)
933 return false;
934 uint32_t imm32;
935 switch (encoding) {
936 case eEncodingA1:
937 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
938 break;
939 default:
940 return false;
941 }
942 addr_t ip_offset = imm32;
943 addr_t addr = ip - ip_offset; // the adjusted ip value
944
945 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
946 eRegisterKindDWARF,
947 dwarf_r12,
948 -ip_offset };
949
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000950 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000951 return false;
952 }
953 return true;
954}
955
956// Set ip to point to some stack offset.
957// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000958bool
959EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000960{
961#if 0
962 // ARM pseudo code...
963 if (ConditionPassed())
964 {
965 EncodingSpecificOperations();
966 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
967 if d == 15 then // Can only occur for ARM encoding
968 ALUWritePC(result); // setflags is always FALSE here
969 else
970 R[d] = result;
971 if setflags then
972 APSR.N = result<31>;
973 APSR.Z = IsZeroBit(result);
974 APSR.C = carry;
975 APSR.V = overflow;
976 }
977#endif
978
979 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000980 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000981 if (!success)
982 return false;
983
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000984 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000985 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000986 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000987 if (!success)
988 return false;
989 uint32_t imm32;
990 switch (encoding) {
991 case eEncodingA1:
992 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
993 break;
994 default:
995 return false;
996 }
997 addr_t sp_offset = imm32;
998 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
999
1000 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1001 eRegisterKindGeneric,
1002 LLDB_REGNUM_GENERIC_SP,
1003 -sp_offset };
1004
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001005 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001006 return false;
1007 }
1008 return true;
1009}
1010
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001011// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001012bool
1013EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001014{
1015#if 0
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1018 {
1019 EncodingSpecificOperations();
1020 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1021 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001022 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001023 else
1024 R[d] = result;
1025 if setflags then
1026 APSR.N = result<31>;
1027 APSR.Z = IsZeroBit(result);
1028 APSR.C = carry;
1029 APSR.V = overflow;
1030 }
1031#endif
1032
1033 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001034 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001035 if (!success)
1036 return false;
1037
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001039 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001040 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001041 if (!success)
1042 return false;
1043 uint32_t imm32;
1044 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001045 case eEncodingT1:
1046 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001047 case eEncodingT2:
1048 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1049 break;
1050 case eEncodingT3:
1051 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1052 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001053 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001054 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001055 break;
1056 default:
1057 return false;
1058 }
1059 addr_t sp_offset = imm32;
1060 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1061
1062 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1063 eRegisterKindGeneric,
1064 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001065 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001066
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001067 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001068 return false;
1069 }
1070 return true;
1071}
1072
Johnny Chen08c25e82011-01-31 18:02:28 +00001073// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001074bool
1075EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001076{
1077#if 0
1078 // ARM pseudo code...
1079 if (ConditionPassed())
1080 {
1081 EncodingSpecificOperations();
1082 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1083 address = if index then offset_addr else R[n];
1084 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1085 if wback then R[n] = offset_addr;
1086 }
1087#endif
1088
1089 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001090 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001091 if (!success)
1092 return false;
1093
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001094 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001095 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001096 const uint32_t addr_byte_size = GetAddressByteSize();
1097 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001098 if (!success)
1099 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001100 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001101 uint32_t imm12;
1102 switch (encoding) {
1103 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001104 Rt = Bits32(opcode, 15, 12);
1105 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001106 break;
1107 default:
1108 return false;
1109 }
1110 addr_t sp_offset = imm12;
1111 addr_t addr = sp - sp_offset;
1112
1113 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001114 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001115 {
Johnny Chen91d99862011-01-25 19:07:04 +00001116 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1117 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001118 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001119 if (!success)
1120 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001121 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001122 return false;
1123 }
1124 else
1125 {
1126 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1127 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001128 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001129 if (!success)
1130 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001131 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001132 return false;
1133 }
1134
1135 context.type = EmulateInstruction::eContextAdjustStackPointer;
1136 context.arg0 = eRegisterKindGeneric;
1137 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001138 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001139
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001141 return false;
1142 }
1143 return true;
1144}
1145
Johnny Chen08c25e82011-01-31 18:02:28 +00001146// Vector Push stores multiple extension registers to the stack.
1147// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001148bool
1149EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001150{
1151#if 0
1152 // ARM pseudo code...
1153 if (ConditionPassed())
1154 {
1155 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1156 address = SP - imm32;
1157 SP = SP - imm32;
1158 if single_regs then
1159 for r = 0 to regs-1
1160 MemA[address,4] = S[d+r]; address = address+4;
1161 else
1162 for r = 0 to regs-1
1163 // Store as two word-aligned words in the correct order for current endianness.
1164 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1165 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1166 address = address+8;
1167 }
1168#endif
1169
1170 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001171 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001172 if (!success)
1173 return false;
1174
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001175 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001176 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001177 const uint32_t addr_byte_size = GetAddressByteSize();
1178 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001179 if (!success)
1180 return false;
1181 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001182 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001183 uint32_t imm32; // stack offset
1184 uint32_t regs; // number of registers
1185 switch (encoding) {
1186 case eEncodingT1:
1187 case eEncodingA1:
1188 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001189 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001190 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1191 // If UInt(imm8) is odd, see "FSTMX".
1192 regs = Bits32(opcode, 7, 0) / 2;
1193 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1194 if (regs == 0 || regs > 16 || (d + regs) > 32)
1195 return false;
1196 break;
1197 case eEncodingT2:
1198 case eEncodingA2:
1199 single_regs = true;
1200 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1201 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1202 regs = Bits32(opcode, 7, 0);
1203 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1204 if (regs == 0 || regs > 16 || (d + regs) > 32)
1205 return false;
1206 break;
1207 default:
1208 return false;
1209 }
1210 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1211 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1212 addr_t sp_offset = imm32;
1213 addr_t addr = sp - sp_offset;
1214 uint32_t i;
1215
1216 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1217 for (i=d; i<regs; ++i)
1218 {
1219 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1220 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1221 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001222 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001223 if (!success)
1224 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001225 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001226 return false;
1227 addr += reg_byte_size;
1228 }
1229
1230 context.type = EmulateInstruction::eContextAdjustStackPointer;
1231 context.arg0 = eRegisterKindGeneric;
1232 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001233 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001234
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001235 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001236 return false;
1237 }
1238 return true;
1239}
1240
Johnny Chen587a0a42011-02-01 18:35:28 +00001241// Vector Pop loads multiple extension registers from the stack.
1242// It also updates SP to point just above the loaded data.
1243bool
1244EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1245{
1246#if 0
1247 // ARM pseudo code...
1248 if (ConditionPassed())
1249 {
1250 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1251 address = SP;
1252 SP = SP + imm32;
1253 if single_regs then
1254 for r = 0 to regs-1
1255 S[d+r] = MemA[address,4]; address = address+4;
1256 else
1257 for r = 0 to regs-1
1258 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1259 // Combine the word-aligned words in the correct order for current endianness.
1260 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1261 }
1262#endif
1263
1264 bool success = false;
1265 const uint32_t opcode = OpcodeAsUnsigned (&success);
1266 if (!success)
1267 return false;
1268
1269 if (ConditionPassed())
1270 {
1271 const uint32_t addr_byte_size = GetAddressByteSize();
1272 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1273 if (!success)
1274 return false;
1275 bool single_regs;
1276 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1277 uint32_t imm32; // stack offset
1278 uint32_t regs; // number of registers
1279 switch (encoding) {
1280 case eEncodingT1:
1281 case eEncodingA1:
1282 single_regs = false;
1283 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1284 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1285 // If UInt(imm8) is odd, see "FLDMX".
1286 regs = Bits32(opcode, 7, 0) / 2;
1287 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1288 if (regs == 0 || regs > 16 || (d + regs) > 32)
1289 return false;
1290 break;
1291 case eEncodingT2:
1292 case eEncodingA2:
1293 single_regs = true;
1294 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1295 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1296 regs = Bits32(opcode, 7, 0);
1297 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1298 if (regs == 0 || regs > 16 || (d + regs) > 32)
1299 return false;
1300 break;
1301 default:
1302 return false;
1303 }
1304 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1305 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1306 addr_t sp_offset = imm32;
1307 addr_t addr = sp;
1308 uint32_t i;
1309 uint64_t data; // uint64_t to accomodate 64-bit registers.
1310
1311 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1312 for (i=d; i<regs; ++i)
1313 {
1314 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1315 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1316 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1317 if (!success)
1318 return false;
1319 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1320 return false;
1321 addr += reg_byte_size;
1322 }
1323
1324 context.type = EmulateInstruction::eContextAdjustStackPointer;
1325 context.arg0 = eRegisterKindGeneric;
1326 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1327 context.arg2 = sp_offset;
1328
1329 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1330 return false;
1331 }
1332 return true;
1333}
1334
Johnny Chenb77be412011-02-04 00:40:18 +00001335// SVC (previously SWI)
1336bool
1337EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1338{
1339#if 0
1340 // ARM pseudo code...
1341 if (ConditionPassed())
1342 {
1343 EncodingSpecificOperations();
1344 CallSupervisor();
1345 }
1346#endif
1347
1348 bool success = false;
1349 const uint32_t opcode = OpcodeAsUnsigned (&success);
1350 if (!success)
1351 return false;
1352
1353 if (ConditionPassed())
1354 {
1355 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1356 addr_t lr; // next instruction address
1357 if (!success)
1358 return false;
1359 uint32_t imm32; // the immediate constant
1360 uint32_t mode; // ARM or Thumb mode
1361 switch (encoding) {
1362 case eEncodingT1:
1363 lr = (pc + 2) | 1u; // return address
1364 imm32 = Bits32(opcode, 7, 0);
1365 mode = eModeThumb;
1366 break;
1367 case eEncodingA1:
1368 lr = pc + 4; // return address
1369 imm32 = Bits32(opcode, 23, 0);
1370 mode = eModeARM;
1371 break;
1372 default:
1373 return false;
1374 }
1375 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1376 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1377 return false;
1378 }
1379 return true;
1380}
1381
Johnny Chenc315f862011-02-05 00:46:10 +00001382// If Then makes up to four following instructions (the IT block) conditional.
1383bool
1384EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1385{
1386#if 0
1387 // ARM pseudo code...
1388 EncodingSpecificOperations();
1389 ITSTATE.IT<7:0> = firstcond:mask;
1390#endif
1391
1392 bool success = false;
1393 const uint32_t opcode = OpcodeAsUnsigned (&success);
1394 if (!success)
1395 return false;
1396
1397 m_it_session.InitIT(Bits32(opcode, 7, 0));
1398 return true;
1399}
1400
Johnny Chen3b620b32011-02-07 20:11:47 +00001401// Branch causes a branch to a target address.
1402bool
1403EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1404{
1405#if 0
1406 // ARM pseudo code...
1407 if (ConditionPassed())
1408 {
1409 EncodingSpecificOperations();
1410 BranchWritePC(PC + imm32);
1411 }
1412#endif
1413
1414 bool success = false;
1415 const uint32_t opcode = OpcodeAsUnsigned (&success);
1416 if (!success)
1417 return false;
1418
Johnny Chen9ee056b2011-02-08 00:06:35 +00001419 if (ConditionPassed())
1420 {
1421 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1422 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001423 if (!success)
1424 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001425 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001426 int32_t imm32; // PC-relative offset
1427 switch (encoding) {
1428 case eEncodingT1:
1429 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1430 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1431 target = pc + 4 + imm32;
1432 context.arg1 = 4 + imm32; // signed offset
1433 context.arg2 = eModeThumb; // target instruction set
1434 break;
1435 case eEncodingT2:
1436 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1437 target = pc + 4 + imm32;
1438 context.arg1 = 4 + imm32; // signed offset
1439 context.arg2 = eModeThumb; // target instruction set
1440 break;
1441 case eEncodingT3:
1442 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1443 {
1444 uint32_t S = Bits32(opcode, 26, 26);
1445 uint32_t imm6 = Bits32(opcode, 21, 16);
1446 uint32_t J1 = Bits32(opcode, 13, 13);
1447 uint32_t J2 = Bits32(opcode, 11, 11);
1448 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001449 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001450 imm32 = llvm::SignExtend32<21>(imm21);
1451 target = pc + 4 + imm32;
1452 context.arg1 = eModeThumb; // target instruction set
1453 context.arg2 = 4 + imm32; // signed offset
1454 break;
1455 }
1456 case eEncodingT4:
1457 {
1458 uint32_t S = Bits32(opcode, 26, 26);
1459 uint32_t imm10 = Bits32(opcode, 25, 16);
1460 uint32_t J1 = Bits32(opcode, 13, 13);
1461 uint32_t J2 = Bits32(opcode, 11, 11);
1462 uint32_t imm11 = Bits32(opcode, 10, 0);
1463 uint32_t I1 = !(J1 ^ S);
1464 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001465 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001466 imm32 = llvm::SignExtend32<25>(imm25);
1467 target = pc + 4 + imm32;
1468 context.arg1 = eModeThumb; // target instruction set
1469 context.arg2 = 4 + imm32; // signed offset
1470 break;
1471 }
1472 case eEncodingA1:
1473 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1474 target = pc + 8 + imm32;
1475 context.arg1 = eModeARM; // target instruction set
1476 context.arg2 = 8 + imm32; // signed offset
1477 break;
1478 default:
1479 return false;
1480 }
1481 if (!BranchWritePC(context, target))
1482 return false;
1483 }
1484 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001485}
1486
Johnny Chen53ebab72011-02-08 23:21:57 +00001487// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1488// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1489// CBNZ, CBZ
1490bool
1491EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1492{
1493#if 0
1494 // ARM pseudo code...
1495 EncodingSpecificOperations();
1496 if nonzero ^ IsZero(R[n]) then
1497 BranchWritePC(PC + imm32);
1498#endif
1499
1500 bool success = false;
1501 const uint32_t opcode = OpcodeAsUnsigned (&success);
1502 if (!success)
1503 return false;
1504
1505 // Read the register value from the operand register Rn.
1506 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1507 if (!success)
1508 return false;
1509
1510 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1511 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1512 if (!success)
1513 return false;
1514
1515 addr_t target; // target address
1516 uint32_t imm32; // PC-relative offset to branch forward
1517 bool nonzero;
1518 switch (encoding) {
1519 case eEncodingT1:
1520 imm32 = Bits32(opcode, 9, 9) << 6 | Bits32(opcode, 7, 3) << 1;
1521 nonzero = BitIsSet(opcode, 11);
1522 target = pc + 4 + imm32;
1523 context.arg1 = 4 + imm32; // signed offset
1524 context.arg2 = eModeThumb; // target instruction set
1525 break;
1526 default:
1527 return false;
1528 }
1529 if (nonzero ^ (reg_val == 0))
1530 if (!BranchWritePC(context, target))
1531 return false;
1532
1533 return true;
1534}
1535
Johnny Chen26863dc2011-02-09 23:43:29 +00001536// ADD <Rdn>, <Rm>
1537// where <Rdn> the destination register is also the first operand register
1538// and <Rm> is the second operand register.
1539bool
1540EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1541{
1542#if 0
1543 // ARM pseudo code...
1544 if ConditionPassed() then
1545 EncodingSpecificOperations();
1546 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1547 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1548 if d == 15 then
1549 ALUWritePC(result); // setflags is always FALSE here
1550 else
1551 R[d] = result;
1552 if setflags then
1553 APSR.N = result<31>;
1554 APSR.Z = IsZeroBit(result);
1555 APSR.C = carry;
1556 APSR.V = overflow;
1557#endif
1558
1559 bool success = false;
1560 const uint32_t opcode = OpcodeAsUnsigned (&success);
1561 if (!success)
1562 return false;
1563
1564 if (ConditionPassed())
1565 {
1566 uint32_t Rd, Rn, Rm;
1567 //bool setflags = false;
1568 switch (encoding)
1569 {
1570 case eEncodingT2:
1571 // setflags = FALSE
1572 Rd = Rn = Bits32(opcode, 7, 7) << 3 | Bits32(opcode, 2, 0);
1573 Rm = Bits32(opcode, 6, 3);
1574 if (Rn == 15 && Rm == 15)
1575 return false;
1576 break;
1577 default:
1578 return false;
1579 }
1580
1581 int32_t result, val1, val2;
1582 // Read the first operand.
1583 if (Rn == 15)
1584 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1585 else
1586 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1587 if (!success)
1588 return false;
1589
1590 // Read the second operand.
1591 if (Rm == 15)
1592 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1593 else
1594 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1595 if (!success)
1596 return false;
1597
1598 result = val1 + val2;
1599 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1600 result,
1601 0,
1602 0 };
1603
1604 if (Rd == 15)
1605 {
1606 if (!ALUWritePC (context, result))
1607 return false;
1608 }
1609 else
1610 {
1611 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1612 return false;
1613 }
1614 }
1615 return true;
1616}
1617
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001618// LDM loads multiple registers from consecutive memory locations, using an
1619// address from a base register. Optionally the addres just above the highest of those locations
1620// can be written back to the base register.
1621bool
1622EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1623{
1624#if 0
1625 // ARM pseudo code...
1626 if ConditionPassed()
1627 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1628 address = R[n];
1629
1630 for i = 0 to 14
1631 if registers<i> == '1' then
1632 R[i] = MemA[address, 4]; address = address + 4;
1633 if registers<15> == '1' then
1634 LoadWritePC (MemA[address, 4]);
1635
1636 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1637 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1638
1639#endif
1640
1641 bool success = false;
1642 const uint32_t opcode = OpcodeAsUnsigned (&success);
1643 if (!success)
1644 return false;
1645
1646 if (ConditionPassed())
1647 {
1648 uint32_t n;
1649 uint32_t registers = 0;
1650 bool wback;
1651 const uint32_t addr_byte_size = GetAddressByteSize();
1652 switch (encoding)
1653 {
1654 case eEncodingT1:
1655 n = Bits32 (opcode, 10, 8);
1656 registers = Bits32 (opcode, 7, 0);
1657 wback = BitIsClear (registers, n);
1658 // if BitCount(registers) < 1 then UNPREDICTABLE;
1659 if (BitCount(registers) < 1)
1660 return false;
1661 break;
1662 case eEncodingT2:
1663 n = Bits32 (opcode, 19, 16);
1664 registers = Bits32 (opcode, 15, 0);
1665 wback = BitIsSet (opcode, 21);
1666 if ((n == 15)
1667 || (BitCount (registers) < 2)
1668 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1669 return false;
1670 if (BitIsSet (registers, 15)
1671 && m_it_session.InITBlock()
1672 && !m_it_session.LastInITBlock())
1673 return false;
1674 if (wback
1675 && BitIsSet (registers, n))
1676 return false;
1677 break;
1678 case eEncodingA1:
1679 n = Bits32 (opcode, 19, 16);
1680 registers = Bits32 (opcode, 15, 0);
1681 wback = BitIsSet (opcode, 21);
1682 if ((n == 15)
1683 || (BitCount (registers) < 1))
1684 return false;
1685 break;
1686 default:
1687 return false;
1688 }
1689
1690 int32_t offset = 0;
1691 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1692 if (!success)
1693 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001694
1695 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1696 eRegisterKindDWARF,
1697 dwarf_r0 + n,
1698 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001699
1700 for (int i = 0; i < 14; ++i)
1701 {
1702 if (BitIsSet (registers, i))
1703 {
Caroline Tice85aab332011-02-08 23:56:10 +00001704 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1705 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001706 if (wback && (n == 13)) // Pop Instruction
1707 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1708
1709 // R[i] = MemA [address, 4]; address = address + 4;
1710 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1711 if (!success)
1712 return false;
1713
1714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1715 return false;
1716
1717 offset += addr_byte_size;
1718 }
1719 }
1720
1721 if (BitIsSet (registers, 15))
1722 {
1723 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001724 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1725 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001726 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1727 if (!success)
1728 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001729 // In ARMv5T and above, this is an interworking branch.
1730 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001731 return false;
1732 }
1733
1734 if (wback && BitIsClear (registers, n))
1735 {
1736 addr_t offset = addr_byte_size * BitCount (registers);
Caroline Tice85aab332011-02-08 23:56:10 +00001737 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1738 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001739
1740 // R[n] = R[n] + 4 * BitCount (registers)
1741 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1742 return false;
1743 }
1744 if (wback && BitIsSet (registers, n))
1745 // R[n] bits(32) UNKNOWN;
1746 return false; //I'm not convinced this is the right thing to do here...
1747 }
1748 return true;
1749}
1750
Caroline Tice0b29e242011-02-08 23:16:02 +00001751bool
1752EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1753{
1754#if 0
1755 // ARM pseudo code...
1756 if ConditionPassed() then
1757 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1758 address = R[n] - 4*BitCount(registers);
1759
1760 for i = 0 to 14
1761 if registers<i> == ’1’ then
1762 R[i] = MemA[address,4]; address = address + 4;
1763 if registers<15> == ’1’ then
1764 LoadWritePC(MemA[address,4]);
1765
1766 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1767 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1768#endif
1769
1770 bool success = false;
1771 const uint32_t opcode = OpcodeAsUnsigned (&success);
1772 if (!success)
1773 return false;
1774
1775 if (ConditionPassed())
1776 {
1777 uint32_t n;
1778 uint32_t registers = 0;
1779 bool wback;
1780 const uint32_t addr_byte_size = GetAddressByteSize();
1781 switch (encoding)
1782 {
1783 case eEncodingT1:
1784 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1785 n = Bits32 (opcode, 19, 16);
1786 registers = Bits32 (opcode, 15, 0);
1787 wback = BitIsSet (opcode, 21);
1788
1789 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1790 if ((n == 15)
1791 || (BitCount (registers) < 2)
1792 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1793 return false;
1794
1795 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1796 if (BitIsSet (registers, 15)
1797 && m_it_session.InITBlock()
1798 && !m_it_session.LastInITBlock())
1799 return false;
1800
1801 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1802 if (wback && BitIsSet (registers, n))
1803 return false;
1804
1805 break;
1806
1807 case eEncodingA1:
1808 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1809 n = Bits32 (opcode, 19, 16);
1810 registers = Bits32 (opcode, 15, 0);
1811 wback = BitIsSet (opcode, 21);
1812
1813 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1814 if ((n == 15) || (BitCount (registers) < 1))
1815 return false;
1816
1817 break;
1818
1819 default:
1820 return false;
1821 }
1822
1823 int32_t offset = 0;
1824 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1825 - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00001826 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1827 eRegisterKindDWARF,
1828 dwarf_r0 + n,
1829 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00001830
1831 for (int i = 0; i < 14; ++i)
1832 {
1833 if (BitIsSet (registers, i))
1834 {
1835 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00001836 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001837 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1838 if (!success)
1839 return false;
1840
1841 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1842 return false;
1843
1844 offset += addr_byte_size;
1845 }
1846 }
1847
1848 // if registers<15> == ’1’ then
1849 // LoadWritePC(MemA[address,4]);
1850 if (BitIsSet (registers, 15))
1851 {
Caroline Tice85aab332011-02-08 23:56:10 +00001852 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001853 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1854 if (!success)
1855 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001856 // In ARMv5T and above, this is an interworking branch.
1857 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00001858 return false;
1859 }
1860
1861 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1862 if (wback && BitIsClear (registers, n))
1863 {
Caroline Tice85aab332011-02-08 23:56:10 +00001864 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001865 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1866 if (!success)
1867 return false;
1868 addr = addr - (addr_byte_size * BitCount (registers));
1869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1870 return false;
1871 }
1872
1873 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1874 if (wback && BitIsSet (registers, n))
1875 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1876 }
1877 return true;
1878}
Caroline Tice85aab332011-02-08 23:56:10 +00001879
1880bool
1881EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
1882{
1883#if 0
1884 if ConditionPassed() then
1885 EncodingSpecificOperations();
1886 address = R[n] + 4;
1887
1888 for i = 0 to 14
1889 if registers<i> == ’1’ then
1890 R[i] = MemA[address,4]; address = address + 4;
1891 if registers<15> == ’1’ then
1892 LoadWritePC(MemA[address,4]);
1893
1894 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1895 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
1896#endif
1897
1898 bool success = false;
1899 const uint32_t opcode = OpcodeAsUnsigned (&success);
1900 if (!success)
1901 return false;
1902
1903 if (ConditionPassed())
1904 {
1905 uint32_t n;
1906 uint32_t registers = 0;
1907 bool wback;
1908 const uint32_t addr_byte_size = GetAddressByteSize();
1909 switch (encoding)
1910 {
1911 case eEncodingA1:
1912 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1913 n = Bits32 (opcode, 19, 16);
1914 registers = Bits32 (opcode, 15, 0);
1915 wback = BitIsSet (opcode, 21);
1916
1917 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1918 if ((n == 15) || (BitCount (registers) < 1))
1919 return false;
1920
1921 break;
1922 default:
1923 return false;
1924 }
1925 // address = R[n] + 4;
1926
1927 int32_t offset = 0;
1928 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success) + addr_byte_size;
1929
1930 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1931 eRegisterKindDWARF,
1932 dwarf_r0 + n,
1933 offset };
1934
1935 for (int i = 0; i < 14; ++i)
1936 {
1937 if (BitIsSet (registers, i))
1938 {
1939 // R[i] = MemA[address,4]; address = address + 4;
1940
1941 context.arg2 = offset;
1942 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1943 if (!success)
1944 return false;
1945
1946 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1947 return false;
1948
1949 offset += addr_byte_size;
1950 }
1951 }
1952
1953 // if registers<15> == ’1’ then
1954 // LoadWritePC(MemA[address,4]);
1955 if (BitIsSet (registers, 15))
1956 {
1957 context.arg2 = offset;
1958 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1959 if (!success)
1960 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001961 // In ARMv5T and above, this is an interworking branch.
1962 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00001963 return false;
1964 }
1965
1966 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1967 if (wback && BitIsClear (registers, n))
1968 {
1969 context.arg2 = offset;
1970 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1971 if (!success)
1972 return false;
1973 addr = addr + (addr_byte_size * BitCount (registers));
1974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1975 return false;
1976 }
1977
1978 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1979 if (wback && BitIsSet (registers, n))
1980 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1981 }
1982 return true;
1983}
Caroline Tice0b29e242011-02-08 23:16:02 +00001984
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001985EmulateInstructionARM::ARMOpcode*
1986EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001987{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001988 static ARMOpcode
1989 g_arm_opcodes[] =
1990 {
1991 //----------------------------------------------------------------------
1992 // Prologue instructions
1993 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001994
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001995 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001996 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1997 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001998
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001999 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002000 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2001 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002002 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002003 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2004 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2005 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002006
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002007 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002008 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002009
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002010 // push one register
2011 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002012 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002013
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002014 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002015 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2016 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002017
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002018 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002019 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002020 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002021
Johnny Chen9b8d7832011-02-02 01:13:56 +00002022 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2023 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2024 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2025 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002026 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2027 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002028 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002029 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2030
2031 //----------------------------------------------------------------------
2032 // Supervisor Call (previously Software Interrupt)
2033 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002034 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2035
2036 //----------------------------------------------------------------------
2037 // Branch instructions
2038 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002039 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00002040
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002041 //----------------------------------------------------------------------
2042 // Load instructions
2043 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002044 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002045 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
2046 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002047
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002048 };
2049 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2050
2051 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2052 {
2053 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2054 return &g_arm_opcodes[i];
2055 }
2056 return NULL;
2057}
Greg Clayton64c84432011-01-21 22:02:52 +00002058
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002059
2060EmulateInstructionARM::ARMOpcode*
2061EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002062{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002063
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002064 static ARMOpcode
2065 g_thumb_opcodes[] =
2066 {
2067 //----------------------------------------------------------------------
2068 // Prologue instructions
2069 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002070
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002071 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002072 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002073 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2074 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002075 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00002076 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00002077
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002078 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002079 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
2080 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002081
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002082 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002083 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002084
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002085 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002086 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2087 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002088 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2089 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002090
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002091 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002092 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2093 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002094
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002095 //----------------------------------------------------------------------
2096 // Epilogue instructions
2097 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002098
Johnny Chenc28a76d2011-02-01 18:51:48 +00002099 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002100 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
2101 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00002102 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2103 // J1 == J2 == 1
2104 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002105 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002106 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2107 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2108 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2109 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002110
2111 //----------------------------------------------------------------------
2112 // Supervisor Call (previously Software Interrupt)
2113 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002114 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2115
2116 //----------------------------------------------------------------------
2117 // If Then makes up to four following instructions conditional.
2118 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002119 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2120
2121 //----------------------------------------------------------------------
2122 // Branch instructions
2123 //----------------------------------------------------------------------
2124 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2125 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2126 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002127 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002128 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002129 // compare and branch
2130 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002131
2132 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002133 // Data-processing instructions
2134 //----------------------------------------------------------------------
2135 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2136 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
2137
2138 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002139 // Load instructions
2140 //----------------------------------------------------------------------
2141 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002142 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
2143 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002144
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002145 };
2146
2147 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2148 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2149 {
2150 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2151 return &g_thumb_opcodes[i];
2152 }
2153 return NULL;
2154}
Greg Clayton64c84432011-01-21 22:02:52 +00002155
Greg Clayton31e2a382011-01-30 20:03:56 +00002156bool
2157EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2158{
2159 m_arm_isa = 0;
2160 const char *triple_cstr = triple.GetCString();
2161 if (triple_cstr)
2162 {
2163 const char *dash = ::strchr (triple_cstr, '-');
2164 if (dash)
2165 {
2166 std::string arch (triple_cstr, dash);
2167 const char *arch_cstr = arch.c_str();
2168 if (strcasecmp(arch_cstr, "armv4t") == 0)
2169 m_arm_isa = ARMv4T;
2170 else if (strcasecmp(arch_cstr, "armv4") == 0)
2171 m_arm_isa = ARMv4;
2172 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2173 m_arm_isa = ARMv5TEJ;
2174 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2175 m_arm_isa = ARMv5TE;
2176 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2177 m_arm_isa = ARMv5T;
2178 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2179 m_arm_isa = ARMv6K;
2180 else if (strcasecmp(arch_cstr, "armv6") == 0)
2181 m_arm_isa = ARMv6;
2182 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2183 m_arm_isa = ARMv6T2;
2184 else if (strcasecmp(arch_cstr, "armv7") == 0)
2185 m_arm_isa = ARMv7;
2186 else if (strcasecmp(arch_cstr, "armv8") == 0)
2187 m_arm_isa = ARMv8;
2188 }
2189 }
2190 return m_arm_isa != 0;
2191}
2192
2193
Greg Clayton64c84432011-01-21 22:02:52 +00002194bool
2195EmulateInstructionARM::ReadInstruction ()
2196{
2197 bool success = false;
2198 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2199 if (success)
2200 {
2201 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2202 if (success)
2203 {
2204 Context read_inst_context = {eContextReadOpcode, 0, 0};
2205 if (m_inst_cpsr & MASK_CPSR_T)
2206 {
2207 m_inst_mode = eModeThumb;
2208 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2209
2210 if (success)
2211 {
2212 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2213 {
2214 m_inst.opcode_type = eOpcode16;
2215 m_inst.opcode.inst16 = thumb_opcode;
2216 }
2217 else
2218 {
2219 m_inst.opcode_type = eOpcode32;
2220 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2221 }
2222 }
2223 }
2224 else
2225 {
2226 m_inst_mode = eModeARM;
2227 m_inst.opcode_type = eOpcode32;
2228 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2229 }
2230 }
2231 }
2232 if (!success)
2233 {
2234 m_inst_mode = eModeInvalid;
2235 m_inst_pc = LLDB_INVALID_ADDRESS;
2236 }
2237 return success;
2238}
2239
Johnny Chenee9b1f72011-02-09 01:00:31 +00002240uint32_t
2241EmulateInstructionARM::ArchVersion ()
2242{
2243 return m_arm_isa;
2244}
2245
Greg Clayton64c84432011-01-21 22:02:52 +00002246bool
2247EmulateInstructionARM::ConditionPassed ()
2248{
2249 if (m_inst_cpsr == 0)
2250 return false;
2251
2252 const uint32_t cond = CurrentCond ();
2253
2254 if (cond == UINT32_MAX)
2255 return false;
2256
2257 bool result = false;
2258 switch (UnsignedBits(cond, 3, 1))
2259 {
2260 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2261 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2262 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2263 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2264 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2265 case 5:
2266 {
2267 bool n = (m_inst_cpsr & MASK_CPSR_N);
2268 bool v = (m_inst_cpsr & MASK_CPSR_V);
2269 result = n == v;
2270 }
2271 break;
2272 case 6:
2273 {
2274 bool n = (m_inst_cpsr & MASK_CPSR_N);
2275 bool v = (m_inst_cpsr & MASK_CPSR_V);
2276 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2277 }
2278 break;
2279 case 7:
2280 result = true;
2281 break;
2282 }
2283
2284 if (cond & 1)
2285 result = !result;
2286 return result;
2287}
2288
Johnny Chen9ee056b2011-02-08 00:06:35 +00002289uint32_t
2290EmulateInstructionARM::CurrentCond ()
2291{
2292 switch (m_inst_mode)
2293 {
2294 default:
2295 case eModeInvalid:
2296 break;
2297
2298 case eModeARM:
2299 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2300
2301 case eModeThumb:
2302 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2303 // 'cond' field of the encoding.
2304 if (m_inst.opcode_type == eOpcode16 &&
2305 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2306 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2307 {
2308 return Bits32(m_inst.opcode.inst16, 11, 7);
2309 }
2310 else if (m_inst.opcode_type == eOpcode32 &&
2311 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2312 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2313 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2314 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2315 {
2316 return Bits32(m_inst.opcode.inst32, 25, 22);
2317 }
2318
2319 return m_it_session.GetCond();
2320 }
2321 return UINT32_MAX; // Return invalid value
2322}
2323
Johnny Chen9ee056b2011-02-08 00:06:35 +00002324bool
2325EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2326{
2327 addr_t target;
2328
Johnny Chenee9b1f72011-02-09 01:00:31 +00002329 // Check the current instruction set.
2330 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00002331 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002332 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00002333 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002334
Johnny Chen9ee056b2011-02-08 00:06:35 +00002335 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002336 return false;
2337
2338 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002339}
2340
2341// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2342bool
2343EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2344{
2345 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00002346 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
2347 // we want to record it and issue a WriteRegister callback so the clients
2348 // can track the mode changes accordingly.
2349 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002350
2351 if (BitIsSet(addr, 0))
2352 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002353 if (CurrentInstrSet() != eModeThumb)
2354 {
2355 SelectInstrSet(eModeThumb);
2356 cpsr_changed = true;
2357 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002358 target = addr & 0xfffffffe;
2359 context.arg2 = eModeThumb;
2360 }
2361 else if (BitIsClear(addr, 1))
2362 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002363 if (CurrentInstrSet() != eModeARM)
2364 {
2365 SelectInstrSet(eModeARM);
2366 cpsr_changed = true;
2367 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002368 target = addr & 0xfffffffc;
2369 context.arg2 = eModeARM;
2370 }
2371 else
2372 return false; // address<1:0> == '10' => UNPREDICTABLE
2373
Johnny Chen0f309db2011-02-09 19:11:32 +00002374 if (cpsr_changed)
2375 {
Johnny Chen558133b2011-02-09 23:59:17 +00002376 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00002377 return false;
2378 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002379 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002380 return false;
2381
2382 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002383}
Greg Clayton64c84432011-01-21 22:02:52 +00002384
Johnny Chenee9b1f72011-02-09 01:00:31 +00002385// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
2386bool
2387EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
2388{
2389 if (ArchVersion() >= ARMv5T)
2390 return BXWritePC(context, addr);
2391 else
2392 return BranchWritePC((const Context)context, addr);
2393}
2394
Johnny Chen26863dc2011-02-09 23:43:29 +00002395// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
2396bool
2397EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
2398{
2399 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
2400 return BXWritePC(context, addr);
2401 else
2402 return BranchWritePC((const Context)context, addr);
2403}
2404
Johnny Chenee9b1f72011-02-09 01:00:31 +00002405EmulateInstructionARM::Mode
2406EmulateInstructionARM::CurrentInstrSet ()
2407{
2408 return m_inst_mode;
2409}
2410
2411// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00002412// ReadInstruction() is performed. This function has a side effect of updating
2413// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00002414bool
2415EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
2416{
Johnny Chen558133b2011-02-09 23:59:17 +00002417 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002418 switch (arm_or_thumb)
2419 {
2420 default:
2421 return false;
2422 eModeARM:
2423 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002424 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002425 break;
2426 eModeThumb:
2427 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002428 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002429 break;
2430 }
2431 return true;
2432}
2433
Greg Clayton64c84432011-01-21 22:02:52 +00002434bool
2435EmulateInstructionARM::EvaluateInstruction ()
2436{
Johnny Chenc315f862011-02-05 00:46:10 +00002437 // Advance the ITSTATE bits to their values for the next instruction.
2438 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2439 m_it_session.ITAdvance();
2440
Greg Clayton64c84432011-01-21 22:02:52 +00002441 return false;
2442}