blob: a310a0ef57de8cd5447c440007106bbce2f8ea90 [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 Chen0e00af22011-02-10 19:40:42 +000028//----------------------------------------------------------------------
29//
30// ITSession implementation
31//
32//----------------------------------------------------------------------
33
Johnny Chen93070472011-02-04 23:02:47 +000034// A8.6.50
35// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
36static unsigned short CountITSize(unsigned ITMask) {
37 // First count the trailing zeros of the IT mask.
38 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
39 if (TZ > 3)
40 {
41 printf("Encoding error: IT Mask '0000'\n");
42 return 0;
43 }
44 return (4 - TZ);
45}
46
47// Init ITState. Note that at least one bit is always 1 in mask.
48bool ITSession::InitIT(unsigned short bits7_0)
49{
50 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
51 if (ITCounter == 0)
52 return false;
53
54 // A8.6.50 IT
55 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
56 if (FirstCond == 0xF)
57 {
58 printf("Encoding error: IT FirstCond '1111'\n");
59 return false;
60 }
61 if (FirstCond == 0xE && ITCounter != 1)
62 {
63 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
64 return false;
65 }
66
67 ITState = bits7_0;
68 return true;
69}
70
71// Update ITState if necessary.
72void ITSession::ITAdvance()
73{
74 assert(ITCounter);
75 --ITCounter;
76 if (ITCounter == 0)
77 ITState = 0;
78 else
79 {
80 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
81 SetBits32(ITState, 4, 0, NewITState4_0);
82 }
83}
84
85// Return true if we're inside an IT Block.
86bool ITSession::InITBlock()
87{
88 return ITCounter != 0;
89}
90
Johnny Chenc315f862011-02-05 00:46:10 +000091// Return true if we're the last instruction inside an IT Block.
92bool ITSession::LastInITBlock()
93{
94 return ITCounter == 1;
95}
96
Johnny Chen93070472011-02-04 23:02:47 +000097// Get condition bits for the current thumb instruction.
98uint32_t ITSession::GetCond()
99{
Johnny Chenc315f862011-02-05 00:46:10 +0000100 if (InITBlock())
101 return Bits32(ITState, 7, 4);
102 else
103 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000104}
105
Greg Clayton64c84432011-01-21 22:02:52 +0000106// ARM constants used during decoding
107#define REG_RD 0
108#define LDM_REGLIST 1
109#define PC_REG 15
110#define PC_REGLIST_BIT 0x8000
111
Johnny Chen251af6a2011-01-21 22:47:25 +0000112#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000113#define ARMv4T (1u << 1)
114#define ARMv5T (1u << 2)
115#define ARMv5TE (1u << 3)
116#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000117#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000118#define ARMv6K (1u << 6)
119#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000120#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000121#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000122#define ARMvAll (0xffffffffu)
123
Johnny Chen9b8d7832011-02-02 01:13:56 +0000124#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
125#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
126#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000127
Johnny Chen0e00af22011-02-10 19:40:42 +0000128//----------------------------------------------------------------------
129//
130// EmulateInstructionARM implementation
131//
132//----------------------------------------------------------------------
133
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000134void
135EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000136{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000137}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139void
140EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000141{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142}
143
Caroline Tice713c2662011-02-11 17:59:55 +0000144// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
145bool
146EmulateInstructionARM::WriteBits32Unknown (int n)
147{
148 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteRegisterRandomBits,
149 eRegisterKindDWARF,
150 dwarf_r0 + n,
151 0 };
152
Johnny Chen62ff6f52011-02-11 18:11:22 +0000153 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000154 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
155
156 if (!success)
157 return false;
158
159 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
160 return false;
161
162 return true;
163}
164
Johnny Chen08c25e82011-01-31 18:02:28 +0000165// Push Multiple Registers stores multiple registers to the stack, storing to
166// consecutive memory locations ending just below the address in SP, and updates
167// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000168bool
169EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000170{
171#if 0
172 // ARM pseudo code...
173 if (ConditionPassed())
174 {
175 EncodingSpecificOperations();
176 NullCheckIfThumbEE(13);
177 address = SP - 4*BitCount(registers);
178
179 for (i = 0 to 14)
180 {
181 if (registers<i> == ’1’)
182 {
183 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
184 MemA[address,4] = bits(32) UNKNOWN;
185 else
186 MemA[address,4] = R[i];
187 address = address + 4;
188 }
189 }
190
191 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
192 MemA[address,4] = PCStoreValue();
193
194 SP = SP - 4*BitCount(registers);
195 }
196#endif
197
198 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000199 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000200 if (!success)
201 return false;
202
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000203 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000204 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000205 const uint32_t addr_byte_size = GetAddressByteSize();
206 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000207 if (!success)
208 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000209 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000210 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000211 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000212 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000213 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000214 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000215 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000216 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000217 // if BitCount(registers) < 1 then UNPREDICTABLE;
218 if (BitCount(registers) < 1)
219 return false;
220 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000221 case eEncodingT2:
222 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000223 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000224 // if BitCount(registers) < 2 then UNPREDICTABLE;
225 if (BitCount(registers) < 2)
226 return false;
227 break;
228 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000229 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000230 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000231 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000232 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000233 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000234 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000235 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000236 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000237 // Instead of return false, let's handle the following case as well,
238 // which amounts to pushing one reg onto the full descending stacks.
239 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000240 break;
241 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000242 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000244 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000245 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000246 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000247 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000248 default:
249 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000250 }
Johnny Chence1ca772011-01-25 01:13:00 +0000251 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000252 addr_t addr = sp - sp_offset;
253 uint32_t i;
254
255 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
256 for (i=0; i<15; ++i)
257 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000258 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000259 {
260 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
261 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000262 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000263 if (!success)
264 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000265 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000266 return false;
267 addr += addr_byte_size;
268 }
269 }
270
Johnny Chen7c1bf922011-02-08 23:49:37 +0000271 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000272 {
273 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000274 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000275 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000276 if (!success)
277 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000278 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000279 return false;
280 }
281
282 context.type = EmulateInstruction::eContextAdjustStackPointer;
283 context.arg0 = eRegisterKindGeneric;
284 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000285 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000286
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000287 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000288 return false;
289 }
290 return true;
291}
292
Johnny Chenef85e912011-01-31 23:07:40 +0000293// Pop Multiple Registers loads multiple registers from the stack, loading from
294// consecutive memory locations staring at the address in SP, and updates
295// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000296bool
297EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000298{
299#if 0
300 // ARM pseudo code...
301 if (ConditionPassed())
302 {
303 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
304 address = SP;
305 for i = 0 to 14
306 if registers<i> == ‘1’ then
307 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
308 if registers<15> == ‘1’ then
309 if UnalignedAllowed then
310 LoadWritePC(MemU[address,4]);
311 else
312 LoadWritePC(MemA[address,4]);
313 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
314 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
315 }
316#endif
317
318 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000320 if (!success)
321 return false;
322
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000323 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000324 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000325 const uint32_t addr_byte_size = GetAddressByteSize();
326 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000327 if (!success)
328 return false;
329 uint32_t registers = 0;
330 uint32_t Rt; // the destination register
331 switch (encoding) {
332 case eEncodingT1:
333 registers = Bits32(opcode, 7, 0);
334 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000335 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000336 registers |= (1u << 15);
337 // if BitCount(registers) < 1 then UNPREDICTABLE;
338 if (BitCount(registers) < 1)
339 return false;
340 break;
341 case eEncodingT2:
342 // Ignore bit 13.
343 registers = Bits32(opcode, 15, 0) & ~0x2000;
344 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000345 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000346 return false;
347 break;
348 case eEncodingT3:
349 Rt = Bits32(opcode, 15, 12);
350 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
351 if (Rt == dwarf_sp)
352 return false;
353 registers = (1u << Rt);
354 break;
355 case eEncodingA1:
356 registers = Bits32(opcode, 15, 0);
357 // Instead of return false, let's handle the following case as well,
358 // which amounts to popping one reg from the full descending stacks.
359 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
360
361 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000362 if (Bit32(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000363 return false;
364 break;
365 case eEncodingA2:
366 Rt = Bits32(opcode, 15, 12);
367 // if t == 13 then UNPREDICTABLE;
368 if (Rt == dwarf_sp)
369 return false;
370 registers = (1u << Rt);
371 break;
372 default:
373 return false;
374 }
375 addr_t sp_offset = addr_byte_size * BitCount (registers);
376 addr_t addr = sp;
377 uint32_t i, data;
378
379 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
380 for (i=0; i<15; ++i)
381 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000382 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000383 {
384 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
385 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000386 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000387 if (!success)
388 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000389 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000390 return false;
391 addr += addr_byte_size;
392 }
393 }
394
Johnny Chen7c1bf922011-02-08 23:49:37 +0000395 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000396 {
397 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
398 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000399 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000400 if (!success)
401 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000402 // In ARMv5T and above, this is an interworking branch.
403 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000404 return false;
405 addr += addr_byte_size;
406 }
407
408 context.type = EmulateInstruction::eContextAdjustStackPointer;
409 context.arg0 = eRegisterKindGeneric;
410 context.arg1 = LLDB_REGNUM_GENERIC_SP;
411 context.arg2 = sp_offset;
412
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 return false;
415 }
416 return true;
417}
418
Johnny Chen5b442b72011-01-27 19:34:30 +0000419// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000420// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000421bool
422EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000423{
424#if 0
425 // ARM pseudo code...
426 if (ConditionPassed())
427 {
428 EncodingSpecificOperations();
429 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
430 if d == 15 then
431 ALUWritePC(result); // setflags is always FALSE here
432 else
433 R[d] = result;
434 if setflags then
435 APSR.N = result<31>;
436 APSR.Z = IsZeroBit(result);
437 APSR.C = carry;
438 APSR.V = overflow;
439 }
440#endif
441
442 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000443 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000444 if (!success)
445 return false;
446
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000447 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000449 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000450 if (!success)
451 return false;
452 uint32_t Rd; // the destination register
453 uint32_t imm32;
454 switch (encoding) {
455 case eEncodingT1:
456 Rd = 7;
457 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
458 break;
459 case eEncodingA1:
460 Rd = Bits32(opcode, 15, 12);
461 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
462 break;
463 default:
464 return false;
465 }
466 addr_t sp_offset = imm32;
467 addr_t addr = sp + sp_offset; // a pointer to the stack area
468
469 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
470 eRegisterKindGeneric,
471 LLDB_REGNUM_GENERIC_SP,
472 sp_offset };
473
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 return false;
476 }
477 return true;
478}
479
Johnny Chen2ccad832011-01-28 19:57:25 +0000480// Set r7 or ip to the current stack pointer.
481// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000482bool
483EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000484{
485#if 0
486 // ARM pseudo code...
487 if (ConditionPassed())
488 {
489 EncodingSpecificOperations();
490 result = R[m];
491 if d == 15 then
492 ALUWritePC(result); // setflags is always FALSE here
493 else
494 R[d] = result;
495 if setflags then
496 APSR.N = result<31>;
497 APSR.Z = IsZeroBit(result);
498 // APSR.C unchanged
499 // APSR.V unchanged
500 }
501#endif
502
503 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000505 //if (!success)
506 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000507
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000509 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000511 if (!success)
512 return false;
513 uint32_t Rd; // the destination register
514 switch (encoding) {
515 case eEncodingT1:
516 Rd = 7;
517 break;
518 case eEncodingA1:
519 Rd = 12;
520 break;
521 default:
522 return false;
523 }
524 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
525 eRegisterKindGeneric,
526 LLDB_REGNUM_GENERIC_SP,
527 0 };
528
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000529 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000530 return false;
531 }
532 return true;
533}
534
Johnny Chen1c13b622011-01-29 00:11:15 +0000535// Move from high register (r8-r15) to low register (r0-r7).
536// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000537bool
538EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000539{
Johnny Chen338bf542011-02-10 19:29:03 +0000540 return EmulateMovRdRm (encoding);
541}
542
543// Move from register to register.
544// MOV (register)
545bool
546EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
547{
Johnny Chen1c13b622011-01-29 00:11:15 +0000548#if 0
549 // ARM pseudo code...
550 if (ConditionPassed())
551 {
552 EncodingSpecificOperations();
553 result = R[m];
554 if d == 15 then
555 ALUWritePC(result); // setflags is always FALSE here
556 else
557 R[d] = result;
558 if setflags then
559 APSR.N = result<31>;
560 APSR.Z = IsZeroBit(result);
561 // APSR.C unchanged
562 // APSR.V unchanged
563 }
564#endif
565
566 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000568 if (!success)
569 return false;
570
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000571 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000572 {
573 uint32_t Rm; // the source register
574 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000575 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000576 switch (encoding) {
577 case eEncodingT1:
578 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000579 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000580 setflags = false;
581 break;
582 case eEncodingT2:
583 Rm = Bits32(opcode, 5, 3);
584 Rd = Bits32(opcode, 2, 1);
585 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000586 break;
587 default:
588 return false;
589 }
Johnny Chen338bf542011-02-10 19:29:03 +0000590 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000591 if (!success)
592 return false;
593
594 // The context specifies that Rm is to be moved into Rd.
595 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
596 eRegisterKindDWARF,
597 dwarf_r0 + Rm,
598 0 };
599
Johnny Chen338bf542011-02-10 19:29:03 +0000600 if (Rd == 15)
601 {
602 if (!ALUWritePC (context, reg_value))
603 return false;
604 }
605 else
606 {
607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
608 return false;
609 if (setflags)
610 {
611 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000612 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
613 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000614 if (m_new_inst_cpsr != m_inst_cpsr)
615 {
616 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
617 return false;
618 }
619 }
620 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000621 }
622 return true;
623}
624
Johnny Chen788e0552011-01-27 22:52:23 +0000625// PC relative immediate load into register, possibly followed by ADD (SP plus register).
626// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000627bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000628EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000629{
630#if 0
631 // ARM pseudo code...
632 if (ConditionPassed())
633 {
634 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
635 base = Align(PC,4);
636 address = if add then (base + imm32) else (base - imm32);
637 data = MemU[address,4];
638 if t == 15 then
639 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
640 elsif UnalignedSupport() || address<1:0> = ‘00’ then
641 R[t] = data;
642 else // Can only apply before ARMv7
643 if CurrentInstrSet() == InstrSet_ARM then
644 R[t] = ROR(data, 8*UInt(address<1:0>));
645 else
646 R[t] = bits(32) UNKNOWN;
647 }
648#endif
649
650 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000651 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000652 if (!success)
653 return false;
654
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000655 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000656 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000657 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000658 if (!success)
659 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000660
661 // PC relative immediate load context
662 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
663 eRegisterKindGeneric,
664 LLDB_REGNUM_GENERIC_PC,
665 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000666 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000667 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000668 bool add; // +imm32 or -imm32?
669 addr_t base; // the base address
670 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000671 uint32_t data; // the literal data value from the PC relative load
672 switch (encoding) {
673 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000674 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000675 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000676 add = true;
677 base = Align(pc + 4, 4);
678 context.arg2 = 4 + imm32;
679 break;
680 case eEncodingT2:
681 Rt = Bits32(opcode, 15, 12);
682 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
683 add = BitIsSet(opcode, 23);
684 if (Rt == 15
685 && m_it_session.InITBlock()
686 && !m_it_session.LastInITBlock())
687 return false;
688 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000689 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000690 break;
691 default:
692 return false;
693 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000694
695 if (add)
696 address = base + imm32;
697 else
698 address = base - imm32;
699 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000700 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000701 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000702
703 if (Rt == 15)
704 {
705 if (Bits32(address, 1, 0) == 0)
706 {
707 // In ARMv5T and above, this is an interworking branch.
708 if (!LoadWritePC(context, data))
709 return false;
710 }
711 else
712 return false;
713 }
714 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
715 {
716 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
717 return false;
718 }
719 else // We don't handle ARM for now.
720 return false;
721
722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000723 return false;
724 }
725 return true;
726}
727
Johnny Chen5b442b72011-01-27 19:34:30 +0000728// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000729// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000730bool
731EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000732{
733#if 0
734 // ARM pseudo code...
735 if (ConditionPassed())
736 {
737 EncodingSpecificOperations();
738 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
739 if d == 15 then // Can only occur for ARM encoding
740 ALUWritePC(result); // setflags is always FALSE here
741 else
742 R[d] = result;
743 if setflags then
744 APSR.N = result<31>;
745 APSR.Z = IsZeroBit(result);
746 APSR.C = carry;
747 APSR.V = overflow;
748 }
749#endif
750
751 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000752 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000753 if (!success)
754 return false;
755
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000756 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000757 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000758 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000759 if (!success)
760 return false;
761 uint32_t imm32; // the immediate operand
762 switch (encoding) {
763 case eEncodingT2:
764 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
765 break;
766 default:
767 return false;
768 }
769 addr_t sp_offset = imm32;
770 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
771
772 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
773 eRegisterKindGeneric,
774 LLDB_REGNUM_GENERIC_SP,
775 sp_offset };
776
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000777 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000778 return false;
779 }
780 return true;
781}
782
783// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000784// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000785bool
786EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000787{
788#if 0
789 // ARM pseudo code...
790 if (ConditionPassed())
791 {
792 EncodingSpecificOperations();
793 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
794 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
795 if d == 15 then
796 ALUWritePC(result); // setflags is always FALSE here
797 else
798 R[d] = result;
799 if setflags then
800 APSR.N = result<31>;
801 APSR.Z = IsZeroBit(result);
802 APSR.C = carry;
803 APSR.V = overflow;
804 }
805#endif
806
807 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000808 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000809 if (!success)
810 return false;
811
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000812 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000813 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000814 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000815 if (!success)
816 return false;
817 uint32_t Rm; // the second operand
818 switch (encoding) {
819 case eEncodingT2:
820 Rm = Bits32(opcode, 6, 3);
821 break;
822 default:
823 return false;
824 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000825 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000826 if (!success)
827 return false;
828
829 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
830
831 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
832 eRegisterKindGeneric,
833 LLDB_REGNUM_GENERIC_SP,
834 reg_value };
835
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000836 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000837 return false;
838 }
839 return true;
840}
841
Johnny Chen9b8d7832011-02-02 01:13:56 +0000842// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
843// at a PC-relative address, and changes instruction set from ARM to Thumb, or
844// from Thumb to ARM.
845// BLX (immediate)
846bool
847EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
848{
849#if 0
850 // ARM pseudo code...
851 if (ConditionPassed())
852 {
853 EncodingSpecificOperations();
854 if CurrentInstrSet() == InstrSet_ARM then
855 LR = PC - 4;
856 else
857 LR = PC<31:1> : '1';
858 if targetInstrSet == InstrSet_ARM then
859 targetAddress = Align(PC,4) + imm32;
860 else
861 targetAddress = PC + imm32;
862 SelectInstrSet(targetInstrSet);
863 BranchWritePC(targetAddress);
864 }
865#endif
866
867 bool success = false;
868 const uint32_t opcode = OpcodeAsUnsigned (&success);
869 if (!success)
870 return false;
871
872 if (ConditionPassed())
873 {
874 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
875 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000876 if (!success)
877 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000878 addr_t lr; // next instruction address
879 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000880 int32_t imm32; // PC-relative offset
881 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000882 case eEncodingT1:
883 {
884 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000885 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +0000886 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000887 uint32_t J1 = Bit32(opcode, 13);
888 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +0000889 uint32_t imm11 = Bits32(opcode, 10, 0);
890 uint32_t I1 = !(J1 ^ S);
891 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000892 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000893 imm32 = llvm::SignExtend32<25>(imm25);
894 target = pc + 4 + imm32;
895 context.arg1 = 4 + imm32; // signed offset
896 context.arg2 = eModeThumb; // target instruction set
897 break;
898 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000899 case eEncodingT2:
900 {
901 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000902 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000903 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000904 uint32_t J1 = Bit32(opcode, 13);
905 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000906 uint32_t imm10L = Bits32(opcode, 10, 1);
907 uint32_t I1 = !(J1 ^ S);
908 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000909 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000910 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000911 target = Align(pc + 4, 4) + imm32;
912 context.arg1 = 4 + imm32; // signed offset
913 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000914 break;
915 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000916 case eEncodingA1:
917 lr = pc + 4; // return address
918 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000919 target = Align(pc + 8, 4) + imm32;
920 context.arg1 = 8 + imm32; // signed offset
921 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000922 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000923 case eEncodingA2:
924 lr = pc + 4; // return address
925 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
926 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000927 context.arg1 = 8 + imm32; // signed offset
928 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000929 break;
930 default:
931 return false;
932 }
933 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
934 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000935 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000936 return false;
937 }
938 return true;
939}
940
941// Branch with Link and Exchange (register) calls a subroutine at an address and
942// instruction set specified by a register.
943// BLX (register)
944bool
945EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
946{
947#if 0
948 // ARM pseudo code...
949 if (ConditionPassed())
950 {
951 EncodingSpecificOperations();
952 target = R[m];
953 if CurrentInstrSet() == InstrSet_ARM then
954 next_instr_addr = PC - 4;
955 LR = next_instr_addr;
956 else
957 next_instr_addr = PC - 2;
958 LR = next_instr_addr<31:1> : ‘1’;
959 BXWritePC(target);
960 }
961#endif
962
963 bool success = false;
964 const uint32_t opcode = OpcodeAsUnsigned (&success);
965 if (!success)
966 return false;
967
968 if (ConditionPassed())
969 {
970 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
971 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
972 addr_t lr; // next instruction address
973 addr_t target; // target address
974 if (!success)
975 return false;
976 uint32_t Rm; // the register with the target address
977 switch (encoding) {
978 case eEncodingT1:
979 lr = (pc + 2) | 1u; // return address
980 Rm = Bits32(opcode, 6, 3);
981 // if m == 15 then UNPREDICTABLE;
982 if (Rm == 15)
983 return false;
984 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
985 break;
986 case eEncodingA1:
987 lr = pc + 4; // return address
988 Rm = Bits32(opcode, 3, 0);
989 // if m == 15 then UNPREDICTABLE;
990 if (Rm == 15)
991 return false;
992 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000993 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000994 default:
995 return false;
996 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000997 context.arg0 = eRegisterKindDWARF;
998 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000999 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1000 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001001 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001002 return false;
1003 }
1004 return true;
1005}
1006
Johnny Chen0d0148e2011-01-28 02:26:08 +00001007// Set r7 to point to some ip offset.
1008// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001009bool
1010EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001011{
1012#if 0
1013 // ARM pseudo code...
1014 if (ConditionPassed())
1015 {
1016 EncodingSpecificOperations();
1017 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1018 if d == 15 then // Can only occur for ARM encoding
1019 ALUWritePC(result); // setflags is always FALSE here
1020 else
1021 R[d] = result;
1022 if setflags then
1023 APSR.N = result<31>;
1024 APSR.Z = IsZeroBit(result);
1025 APSR.C = carry;
1026 APSR.V = overflow;
1027 }
1028#endif
1029
1030 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001031 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001032 if (!success)
1033 return false;
1034
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001035 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001036 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001037 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001038 if (!success)
1039 return false;
1040 uint32_t imm32;
1041 switch (encoding) {
1042 case eEncodingA1:
1043 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1044 break;
1045 default:
1046 return false;
1047 }
1048 addr_t ip_offset = imm32;
1049 addr_t addr = ip - ip_offset; // the adjusted ip value
1050
1051 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1052 eRegisterKindDWARF,
1053 dwarf_r12,
1054 -ip_offset };
1055
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001056 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001057 return false;
1058 }
1059 return true;
1060}
1061
1062// Set ip to point to some stack offset.
1063// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001064bool
1065EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001066{
1067#if 0
1068 // ARM pseudo code...
1069 if (ConditionPassed())
1070 {
1071 EncodingSpecificOperations();
1072 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1073 if d == 15 then // Can only occur for ARM encoding
1074 ALUWritePC(result); // setflags is always FALSE here
1075 else
1076 R[d] = result;
1077 if setflags then
1078 APSR.N = result<31>;
1079 APSR.Z = IsZeroBit(result);
1080 APSR.C = carry;
1081 APSR.V = overflow;
1082 }
1083#endif
1084
1085 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001086 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001087 if (!success)
1088 return false;
1089
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001090 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001091 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001092 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001093 if (!success)
1094 return false;
1095 uint32_t imm32;
1096 switch (encoding) {
1097 case eEncodingA1:
1098 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1099 break;
1100 default:
1101 return false;
1102 }
1103 addr_t sp_offset = imm32;
1104 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1105
1106 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1107 eRegisterKindGeneric,
1108 LLDB_REGNUM_GENERIC_SP,
1109 -sp_offset };
1110
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001111 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001112 return false;
1113 }
1114 return true;
1115}
1116
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001117// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001118bool
1119EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001120{
1121#if 0
1122 // ARM pseudo code...
1123 if (ConditionPassed())
1124 {
1125 EncodingSpecificOperations();
1126 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1127 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001128 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001129 else
1130 R[d] = result;
1131 if setflags then
1132 APSR.N = result<31>;
1133 APSR.Z = IsZeroBit(result);
1134 APSR.C = carry;
1135 APSR.V = overflow;
1136 }
1137#endif
1138
1139 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001141 if (!success)
1142 return false;
1143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001144 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001145 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001146 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001147 if (!success)
1148 return false;
1149 uint32_t imm32;
1150 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001151 case eEncodingT1:
1152 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001153 case eEncodingT2:
1154 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1155 break;
1156 case eEncodingT3:
1157 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1158 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001159 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001160 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001161 break;
1162 default:
1163 return false;
1164 }
1165 addr_t sp_offset = imm32;
1166 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1167
1168 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1169 eRegisterKindGeneric,
1170 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001171 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001172
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001173 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001174 return false;
1175 }
1176 return true;
1177}
1178
Johnny Chen08c25e82011-01-31 18:02:28 +00001179// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001180bool
1181EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001182{
1183#if 0
1184 // ARM pseudo code...
1185 if (ConditionPassed())
1186 {
1187 EncodingSpecificOperations();
1188 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1189 address = if index then offset_addr else R[n];
1190 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1191 if wback then R[n] = offset_addr;
1192 }
1193#endif
1194
1195 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001196 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001197 if (!success)
1198 return false;
1199
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001200 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001201 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001202 const uint32_t addr_byte_size = GetAddressByteSize();
1203 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001204 if (!success)
1205 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001206 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001207 uint32_t imm12;
1208 switch (encoding) {
1209 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001210 Rt = Bits32(opcode, 15, 12);
1211 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001212 break;
1213 default:
1214 return false;
1215 }
1216 addr_t sp_offset = imm12;
1217 addr_t addr = sp - sp_offset;
1218
1219 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001220 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001221 {
Johnny Chen91d99862011-01-25 19:07:04 +00001222 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1223 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001224 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001225 if (!success)
1226 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001227 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001228 return false;
1229 }
1230 else
1231 {
1232 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1233 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001234 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001235 if (!success)
1236 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001237 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001238 return false;
1239 }
1240
1241 context.type = EmulateInstruction::eContextAdjustStackPointer;
1242 context.arg0 = eRegisterKindGeneric;
1243 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001244 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001245
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001246 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001247 return false;
1248 }
1249 return true;
1250}
1251
Johnny Chen08c25e82011-01-31 18:02:28 +00001252// Vector Push stores multiple extension registers to the stack.
1253// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001254bool
1255EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001256{
1257#if 0
1258 // ARM pseudo code...
1259 if (ConditionPassed())
1260 {
1261 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1262 address = SP - imm32;
1263 SP = SP - imm32;
1264 if single_regs then
1265 for r = 0 to regs-1
1266 MemA[address,4] = S[d+r]; address = address+4;
1267 else
1268 for r = 0 to regs-1
1269 // Store as two word-aligned words in the correct order for current endianness.
1270 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1271 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1272 address = address+8;
1273 }
1274#endif
1275
1276 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001277 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001278 if (!success)
1279 return false;
1280
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001281 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001282 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001283 const uint32_t addr_byte_size = GetAddressByteSize();
1284 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001285 if (!success)
1286 return false;
1287 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001288 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001289 uint32_t imm32; // stack offset
1290 uint32_t regs; // number of registers
1291 switch (encoding) {
1292 case eEncodingT1:
1293 case eEncodingA1:
1294 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001295 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001296 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1297 // If UInt(imm8) is odd, see "FSTMX".
1298 regs = Bits32(opcode, 7, 0) / 2;
1299 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1300 if (regs == 0 || regs > 16 || (d + regs) > 32)
1301 return false;
1302 break;
1303 case eEncodingT2:
1304 case eEncodingA2:
1305 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001306 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001307 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1308 regs = Bits32(opcode, 7, 0);
1309 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1310 if (regs == 0 || regs > 16 || (d + regs) > 32)
1311 return false;
1312 break;
1313 default:
1314 return false;
1315 }
1316 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1317 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1318 addr_t sp_offset = imm32;
1319 addr_t addr = sp - sp_offset;
1320 uint32_t i;
1321
1322 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1323 for (i=d; i<regs; ++i)
1324 {
1325 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1326 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1327 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001328 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001329 if (!success)
1330 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001331 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001332 return false;
1333 addr += reg_byte_size;
1334 }
1335
1336 context.type = EmulateInstruction::eContextAdjustStackPointer;
1337 context.arg0 = eRegisterKindGeneric;
1338 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001339 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001340
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001341 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001342 return false;
1343 }
1344 return true;
1345}
1346
Johnny Chen587a0a42011-02-01 18:35:28 +00001347// Vector Pop loads multiple extension registers from the stack.
1348// It also updates SP to point just above the loaded data.
1349bool
1350EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1351{
1352#if 0
1353 // ARM pseudo code...
1354 if (ConditionPassed())
1355 {
1356 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1357 address = SP;
1358 SP = SP + imm32;
1359 if single_regs then
1360 for r = 0 to regs-1
1361 S[d+r] = MemA[address,4]; address = address+4;
1362 else
1363 for r = 0 to regs-1
1364 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1365 // Combine the word-aligned words in the correct order for current endianness.
1366 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1367 }
1368#endif
1369
1370 bool success = false;
1371 const uint32_t opcode = OpcodeAsUnsigned (&success);
1372 if (!success)
1373 return false;
1374
1375 if (ConditionPassed())
1376 {
1377 const uint32_t addr_byte_size = GetAddressByteSize();
1378 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1379 if (!success)
1380 return false;
1381 bool single_regs;
1382 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1383 uint32_t imm32; // stack offset
1384 uint32_t regs; // number of registers
1385 switch (encoding) {
1386 case eEncodingT1:
1387 case eEncodingA1:
1388 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001389 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001390 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1391 // If UInt(imm8) is odd, see "FLDMX".
1392 regs = Bits32(opcode, 7, 0) / 2;
1393 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1394 if (regs == 0 || regs > 16 || (d + regs) > 32)
1395 return false;
1396 break;
1397 case eEncodingT2:
1398 case eEncodingA2:
1399 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001400 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001401 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1402 regs = Bits32(opcode, 7, 0);
1403 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1404 if (regs == 0 || regs > 16 || (d + regs) > 32)
1405 return false;
1406 break;
1407 default:
1408 return false;
1409 }
1410 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1411 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1412 addr_t sp_offset = imm32;
1413 addr_t addr = sp;
1414 uint32_t i;
1415 uint64_t data; // uint64_t to accomodate 64-bit registers.
1416
1417 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1418 for (i=d; i<regs; ++i)
1419 {
1420 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1421 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1422 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1423 if (!success)
1424 return false;
1425 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1426 return false;
1427 addr += reg_byte_size;
1428 }
1429
1430 context.type = EmulateInstruction::eContextAdjustStackPointer;
1431 context.arg0 = eRegisterKindGeneric;
1432 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1433 context.arg2 = sp_offset;
1434
1435 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1436 return false;
1437 }
1438 return true;
1439}
1440
Johnny Chenb77be412011-02-04 00:40:18 +00001441// SVC (previously SWI)
1442bool
1443EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1444{
1445#if 0
1446 // ARM pseudo code...
1447 if (ConditionPassed())
1448 {
1449 EncodingSpecificOperations();
1450 CallSupervisor();
1451 }
1452#endif
1453
1454 bool success = false;
1455 const uint32_t opcode = OpcodeAsUnsigned (&success);
1456 if (!success)
1457 return false;
1458
1459 if (ConditionPassed())
1460 {
1461 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1462 addr_t lr; // next instruction address
1463 if (!success)
1464 return false;
1465 uint32_t imm32; // the immediate constant
1466 uint32_t mode; // ARM or Thumb mode
1467 switch (encoding) {
1468 case eEncodingT1:
1469 lr = (pc + 2) | 1u; // return address
1470 imm32 = Bits32(opcode, 7, 0);
1471 mode = eModeThumb;
1472 break;
1473 case eEncodingA1:
1474 lr = pc + 4; // return address
1475 imm32 = Bits32(opcode, 23, 0);
1476 mode = eModeARM;
1477 break;
1478 default:
1479 return false;
1480 }
1481 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1482 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1483 return false;
1484 }
1485 return true;
1486}
1487
Johnny Chenc315f862011-02-05 00:46:10 +00001488// If Then makes up to four following instructions (the IT block) conditional.
1489bool
1490EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1491{
1492#if 0
1493 // ARM pseudo code...
1494 EncodingSpecificOperations();
1495 ITSTATE.IT<7:0> = firstcond:mask;
1496#endif
1497
1498 bool success = false;
1499 const uint32_t opcode = OpcodeAsUnsigned (&success);
1500 if (!success)
1501 return false;
1502
1503 m_it_session.InitIT(Bits32(opcode, 7, 0));
1504 return true;
1505}
1506
Johnny Chen3b620b32011-02-07 20:11:47 +00001507// Branch causes a branch to a target address.
1508bool
1509EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1510{
1511#if 0
1512 // ARM pseudo code...
1513 if (ConditionPassed())
1514 {
1515 EncodingSpecificOperations();
1516 BranchWritePC(PC + imm32);
1517 }
1518#endif
1519
1520 bool success = false;
1521 const uint32_t opcode = OpcodeAsUnsigned (&success);
1522 if (!success)
1523 return false;
1524
Johnny Chen9ee056b2011-02-08 00:06:35 +00001525 if (ConditionPassed())
1526 {
1527 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1528 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001529 if (!success)
1530 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001531 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001532 int32_t imm32; // PC-relative offset
1533 switch (encoding) {
1534 case eEncodingT1:
1535 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1536 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1537 target = pc + 4 + imm32;
1538 context.arg1 = 4 + imm32; // signed offset
1539 context.arg2 = eModeThumb; // target instruction set
1540 break;
1541 case eEncodingT2:
1542 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1543 target = pc + 4 + imm32;
1544 context.arg1 = 4 + imm32; // signed offset
1545 context.arg2 = eModeThumb; // target instruction set
1546 break;
1547 case eEncodingT3:
1548 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1549 {
Johnny Chenbd599902011-02-10 21:39:01 +00001550 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001551 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001552 uint32_t J1 = Bit32(opcode, 13);
1553 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001554 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001555 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001556 imm32 = llvm::SignExtend32<21>(imm21);
1557 target = pc + 4 + imm32;
1558 context.arg1 = eModeThumb; // target instruction set
1559 context.arg2 = 4 + imm32; // signed offset
1560 break;
1561 }
1562 case eEncodingT4:
1563 {
Johnny Chenbd599902011-02-10 21:39:01 +00001564 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001565 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001566 uint32_t J1 = Bit32(opcode, 13);
1567 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001568 uint32_t imm11 = Bits32(opcode, 10, 0);
1569 uint32_t I1 = !(J1 ^ S);
1570 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001571 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001572 imm32 = llvm::SignExtend32<25>(imm25);
1573 target = pc + 4 + imm32;
1574 context.arg1 = eModeThumb; // target instruction set
1575 context.arg2 = 4 + imm32; // signed offset
1576 break;
1577 }
1578 case eEncodingA1:
1579 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1580 target = pc + 8 + imm32;
1581 context.arg1 = eModeARM; // target instruction set
1582 context.arg2 = 8 + imm32; // signed offset
1583 break;
1584 default:
1585 return false;
1586 }
1587 if (!BranchWritePC(context, target))
1588 return false;
1589 }
1590 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001591}
1592
Johnny Chen53ebab72011-02-08 23:21:57 +00001593// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1594// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1595// CBNZ, CBZ
1596bool
1597EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1598{
1599#if 0
1600 // ARM pseudo code...
1601 EncodingSpecificOperations();
1602 if nonzero ^ IsZero(R[n]) then
1603 BranchWritePC(PC + imm32);
1604#endif
1605
1606 bool success = false;
1607 const uint32_t opcode = OpcodeAsUnsigned (&success);
1608 if (!success)
1609 return false;
1610
1611 // Read the register value from the operand register Rn.
1612 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1613 if (!success)
1614 return false;
1615
1616 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1617 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1618 if (!success)
1619 return false;
1620
1621 addr_t target; // target address
1622 uint32_t imm32; // PC-relative offset to branch forward
1623 bool nonzero;
1624 switch (encoding) {
1625 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001626 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001627 nonzero = BitIsSet(opcode, 11);
1628 target = pc + 4 + imm32;
1629 context.arg1 = 4 + imm32; // signed offset
1630 context.arg2 = eModeThumb; // target instruction set
1631 break;
1632 default:
1633 return false;
1634 }
1635 if (nonzero ^ (reg_val == 0))
1636 if (!BranchWritePC(context, target))
1637 return false;
1638
1639 return true;
1640}
1641
Johnny Chen26863dc2011-02-09 23:43:29 +00001642// ADD <Rdn>, <Rm>
1643// where <Rdn> the destination register is also the first operand register
1644// and <Rm> is the second operand register.
1645bool
1646EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1647{
1648#if 0
1649 // ARM pseudo code...
1650 if ConditionPassed() then
1651 EncodingSpecificOperations();
1652 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1653 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1654 if d == 15 then
1655 ALUWritePC(result); // setflags is always FALSE here
1656 else
1657 R[d] = result;
1658 if setflags then
1659 APSR.N = result<31>;
1660 APSR.Z = IsZeroBit(result);
1661 APSR.C = carry;
1662 APSR.V = overflow;
1663#endif
1664
1665 bool success = false;
1666 const uint32_t opcode = OpcodeAsUnsigned (&success);
1667 if (!success)
1668 return false;
1669
1670 if (ConditionPassed())
1671 {
1672 uint32_t Rd, Rn, Rm;
1673 //bool setflags = false;
1674 switch (encoding)
1675 {
1676 case eEncodingT2:
1677 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001678 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001679 Rm = Bits32(opcode, 6, 3);
1680 if (Rn == 15 && Rm == 15)
1681 return false;
1682 break;
1683 default:
1684 return false;
1685 }
1686
1687 int32_t result, val1, val2;
1688 // Read the first operand.
1689 if (Rn == 15)
1690 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1691 else
1692 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1693 if (!success)
1694 return false;
1695
1696 // Read the second operand.
1697 if (Rm == 15)
1698 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1699 else
1700 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1701 if (!success)
1702 return false;
1703
1704 result = val1 + val2;
1705 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1706 result,
1707 0,
1708 0 };
1709
1710 if (Rd == 15)
1711 {
1712 if (!ALUWritePC (context, result))
1713 return false;
1714 }
1715 else
1716 {
1717 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1718 return false;
1719 }
1720 }
1721 return true;
1722}
1723
Johnny Chend4dc4442011-02-11 02:02:56 +00001724bool
1725EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1726{
1727#if 0
1728 // ARM pseudo code...
1729 if ConditionPassed() then
1730 EncodingSpecificOperations();
1731 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1732 APSR.N = result<31>;
1733 APSR.Z = IsZeroBit(result);
1734 APSR.C = carry;
1735 APSR.V = overflow;
1736#endif
1737
1738 bool success = false;
1739 const uint32_t opcode = OpcodeAsUnsigned (&success);
1740 if (!success)
1741 return false;
1742
1743 uint32_t Rn; // the first operand
1744 uint32_t imm32; // the immediate value to be compared with
1745 switch (encoding) {
1746 case eEncodingT1:
1747 Rn = Bits32(opcode, 10, 8);
1748 imm32 = Bits32(opcode, 7, 0);
1749 break;
1750 default:
1751 return false;
1752 }
1753 // Read the register value from the operand register Rn.
1754 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1755 if (!success)
1756 return false;
1757
1758 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1759 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1760 m_new_inst_cpsr = m_inst_cpsr;
1761 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1762 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1763 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1764 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1765 if (m_new_inst_cpsr != m_inst_cpsr)
1766 {
1767 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1768 return false;
1769 }
1770 return true;
1771}
1772
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001773// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00001774// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001775// can be written back to the base register.
1776bool
1777EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1778{
1779#if 0
1780 // ARM pseudo code...
1781 if ConditionPassed()
1782 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1783 address = R[n];
1784
1785 for i = 0 to 14
1786 if registers<i> == '1' then
1787 R[i] = MemA[address, 4]; address = address + 4;
1788 if registers<15> == '1' then
1789 LoadWritePC (MemA[address, 4]);
1790
1791 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1792 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1793
1794#endif
1795
1796 bool success = false;
1797 const uint32_t opcode = OpcodeAsUnsigned (&success);
1798 if (!success)
1799 return false;
1800
1801 if (ConditionPassed())
1802 {
1803 uint32_t n;
1804 uint32_t registers = 0;
1805 bool wback;
1806 const uint32_t addr_byte_size = GetAddressByteSize();
1807 switch (encoding)
1808 {
1809 case eEncodingT1:
1810 n = Bits32 (opcode, 10, 8);
1811 registers = Bits32 (opcode, 7, 0);
1812 wback = BitIsClear (registers, n);
1813 // if BitCount(registers) < 1 then UNPREDICTABLE;
1814 if (BitCount(registers) < 1)
1815 return false;
1816 break;
1817 case eEncodingT2:
1818 n = Bits32 (opcode, 19, 16);
1819 registers = Bits32 (opcode, 15, 0);
1820 wback = BitIsSet (opcode, 21);
1821 if ((n == 15)
1822 || (BitCount (registers) < 2)
1823 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1824 return false;
1825 if (BitIsSet (registers, 15)
1826 && m_it_session.InITBlock()
1827 && !m_it_session.LastInITBlock())
1828 return false;
1829 if (wback
1830 && BitIsSet (registers, n))
1831 return false;
1832 break;
1833 case eEncodingA1:
1834 n = Bits32 (opcode, 19, 16);
1835 registers = Bits32 (opcode, 15, 0);
1836 wback = BitIsSet (opcode, 21);
1837 if ((n == 15)
1838 || (BitCount (registers) < 1))
1839 return false;
1840 break;
1841 default:
1842 return false;
1843 }
1844
1845 int32_t offset = 0;
1846 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1847 if (!success)
1848 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001849
1850 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1851 eRegisterKindDWARF,
1852 dwarf_r0 + n,
1853 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001854
1855 for (int i = 0; i < 14; ++i)
1856 {
1857 if (BitIsSet (registers, i))
1858 {
Caroline Tice85aab332011-02-08 23:56:10 +00001859 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1860 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001861 if (wback && (n == 13)) // Pop Instruction
1862 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1863
1864 // R[i] = MemA [address, 4]; address = address + 4;
1865 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1866 if (!success)
1867 return false;
1868
1869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1870 return false;
1871
1872 offset += addr_byte_size;
1873 }
1874 }
1875
1876 if (BitIsSet (registers, 15))
1877 {
1878 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001879 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1880 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001881 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1882 if (!success)
1883 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001884 // In ARMv5T and above, this is an interworking branch.
1885 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001886 return false;
1887 }
1888
1889 if (wback && BitIsClear (registers, n))
1890 {
1891 addr_t offset = addr_byte_size * BitCount (registers);
Caroline Tice85aab332011-02-08 23:56:10 +00001892 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1893 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001894
1895 // R[n] = R[n] + 4 * BitCount (registers)
1896 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1897 return false;
1898 }
1899 if (wback && BitIsSet (registers, n))
1900 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00001901 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001902 }
1903 return true;
1904}
Caroline Tice713c2662011-02-11 17:59:55 +00001905
1906// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
1907// The consecutive memorty locations end at this address and the address just below the lowest of those locations
1908// can optionally be written back tot he base registers.
1909bool
1910EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
1911{
1912#if 0
1913 // ARM pseudo code...
1914 if ConditionPassed() then
1915 EncodingSpecificOperations();
1916 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001917
Caroline Tice713c2662011-02-11 17:59:55 +00001918 for i = 0 to 14
1919 if registers<i> == ’1’ then
1920 R[i] = MemA[address,4]; address = address + 4;
1921
1922 if registers<15> == ’1’ then
1923 LoadWritePC(MemA[address,4]);
1924
1925 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1926 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
1927#endif
1928
1929 bool success = false;
1930 const uint32_t opcode = OpcodeAsUnsigned (&success);
1931 if (!success)
1932 return false;
1933
1934 if (ConditionPassed())
1935 {
1936 uint32_t n;
1937 uint32_t registers = 0;
1938 bool wback;
1939 const uint32_t addr_byte_size = GetAddressByteSize();
1940
1941 // EncodingSpecificOperations();
1942 switch (encoding)
1943 {
1944 case eEncodingA1:
1945 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1946 n = Bits32 (opcode, 19, 16);
1947 registers = Bits32 (opcode, 15, 0);
1948 wback = BitIsSet (opcode, 21);
1949
1950 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1951 if ((n == 15) || (BitCount (registers) < 1))
1952 return false;
1953
1954 break;
1955
1956 default:
1957 return false;
1958 }
1959 // address = R[n] - 4*BitCount(registers) + 4;
1960
1961 int32_t offset = 0;
1962 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1963
1964 if (!success)
1965 return false;
1966
1967 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
1968
1969 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1970 eRegisterKindDWARF,
1971 dwarf_r0 + n,
1972 offset };
1973
1974 // for i = 0 to 14
1975 for (int i = 0; i < 14; ++i)
1976 {
1977 // if registers<i> == ’1’ then
1978 if (BitIsSet (registers, i))
1979 {
1980 // R[i] = MemA[address,4]; address = address + 4;
1981 context.arg2 = offset;
1982 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1983 if (!success)
1984 return false;
1985 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1986 return false;
1987 offset += addr_byte_size;
1988 }
1989 }
1990
1991 // if registers<15> == ’1’ then
1992 // LoadWritePC(MemA[address,4]);
1993 if (BitIsSet (registers, 15))
1994 {
1995 context.arg2 = offset;
1996 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1997 if (!success)
1998 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00001999 // In ARMv5T and above, this is an interworking branch.
2000 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002001 return false;
2002 }
2003
2004 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2005 if (wback && BitIsClear (registers, n))
2006 {
2007 context.arg2 = offset;
2008 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2009 if (!success)
2010 return false;
2011 addr = addr - (addr_byte_size * BitCount (registers));
2012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2013 return false;
2014 }
2015
2016 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2017 if (wback && BitIsSet (registers, n))
2018 return WriteBits32Unknown (n);
2019 }
2020 return true;
2021}
2022
2023// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2024// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2025// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002026bool
2027EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2028{
2029#if 0
2030 // ARM pseudo code...
2031 if ConditionPassed() then
2032 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2033 address = R[n] - 4*BitCount(registers);
2034
2035 for i = 0 to 14
2036 if registers<i> == ’1’ then
2037 R[i] = MemA[address,4]; address = address + 4;
2038 if registers<15> == ’1’ then
2039 LoadWritePC(MemA[address,4]);
2040
2041 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2042 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2043#endif
2044
2045 bool success = false;
2046 const uint32_t opcode = OpcodeAsUnsigned (&success);
2047 if (!success)
2048 return false;
2049
2050 if (ConditionPassed())
2051 {
2052 uint32_t n;
2053 uint32_t registers = 0;
2054 bool wback;
2055 const uint32_t addr_byte_size = GetAddressByteSize();
2056 switch (encoding)
2057 {
2058 case eEncodingT1:
2059 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2060 n = Bits32 (opcode, 19, 16);
2061 registers = Bits32 (opcode, 15, 0);
2062 wback = BitIsSet (opcode, 21);
2063
2064 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2065 if ((n == 15)
2066 || (BitCount (registers) < 2)
2067 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2068 return false;
2069
2070 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
2071 if (BitIsSet (registers, 15)
2072 && m_it_session.InITBlock()
2073 && !m_it_session.LastInITBlock())
2074 return false;
2075
2076 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2077 if (wback && BitIsSet (registers, n))
2078 return false;
2079
2080 break;
2081
2082 case eEncodingA1:
2083 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2084 n = Bits32 (opcode, 19, 16);
2085 registers = Bits32 (opcode, 15, 0);
2086 wback = BitIsSet (opcode, 21);
2087
2088 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2089 if ((n == 15) || (BitCount (registers) < 1))
2090 return false;
2091
2092 break;
2093
2094 default:
2095 return false;
2096 }
2097
Caroline Tice713c2662011-02-11 17:59:55 +00002098 // address = R[n] - 4*BitCount(registers);
2099
Caroline Tice0b29e242011-02-08 23:16:02 +00002100 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002101 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2102
2103 if (!success)
2104 return false;
2105
2106 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002107 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2108 eRegisterKindDWARF,
2109 dwarf_r0 + n,
2110 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002111
2112 for (int i = 0; i < 14; ++i)
2113 {
2114 if (BitIsSet (registers, i))
2115 {
2116 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002117 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002118 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2119 if (!success)
2120 return false;
2121
2122 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2123 return false;
2124
2125 offset += addr_byte_size;
2126 }
2127 }
2128
2129 // if registers<15> == ’1’ then
2130 // LoadWritePC(MemA[address,4]);
2131 if (BitIsSet (registers, 15))
2132 {
Caroline Tice85aab332011-02-08 23:56:10 +00002133 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002134 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2135 if (!success)
2136 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002137 // In ARMv5T and above, this is an interworking branch.
2138 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002139 return false;
2140 }
2141
2142 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2143 if (wback && BitIsClear (registers, n))
2144 {
Caroline Tice85aab332011-02-08 23:56:10 +00002145 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002146 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2147 if (!success)
2148 return false;
2149 addr = addr - (addr_byte_size * BitCount (registers));
2150 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2151 return false;
2152 }
2153
2154 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2155 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002156 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002157 }
2158 return true;
2159}
Caroline Tice85aab332011-02-08 23:56:10 +00002160
Caroline Tice713c2662011-02-11 17:59:55 +00002161// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2162// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2163// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002164bool
2165EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2166{
2167#if 0
2168 if ConditionPassed() then
2169 EncodingSpecificOperations();
2170 address = R[n] + 4;
2171
2172 for i = 0 to 14
2173 if registers<i> == ’1’ then
2174 R[i] = MemA[address,4]; address = address + 4;
2175 if registers<15> == ’1’ then
2176 LoadWritePC(MemA[address,4]);
2177
2178 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2179 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2180#endif
2181
2182 bool success = false;
2183 const uint32_t opcode = OpcodeAsUnsigned (&success);
2184 if (!success)
2185 return false;
2186
2187 if (ConditionPassed())
2188 {
2189 uint32_t n;
2190 uint32_t registers = 0;
2191 bool wback;
2192 const uint32_t addr_byte_size = GetAddressByteSize();
2193 switch (encoding)
2194 {
2195 case eEncodingA1:
2196 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2197 n = Bits32 (opcode, 19, 16);
2198 registers = Bits32 (opcode, 15, 0);
2199 wback = BitIsSet (opcode, 21);
2200
2201 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2202 if ((n == 15) || (BitCount (registers) < 1))
2203 return false;
2204
2205 break;
2206 default:
2207 return false;
2208 }
2209 // address = R[n] + 4;
2210
2211 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002212 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2213
2214 if (!success)
2215 return false;
2216
2217 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002218
2219 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2220 eRegisterKindDWARF,
2221 dwarf_r0 + n,
2222 offset };
2223
2224 for (int i = 0; i < 14; ++i)
2225 {
2226 if (BitIsSet (registers, i))
2227 {
2228 // R[i] = MemA[address,4]; address = address + 4;
2229
2230 context.arg2 = offset;
2231 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2232 if (!success)
2233 return false;
2234
2235 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2236 return false;
2237
2238 offset += addr_byte_size;
2239 }
2240 }
2241
2242 // if registers<15> == ’1’ then
2243 // LoadWritePC(MemA[address,4]);
2244 if (BitIsSet (registers, 15))
2245 {
2246 context.arg2 = offset;
2247 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2248 if (!success)
2249 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002250 // In ARMv5T and above, this is an interworking branch.
2251 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002252 return false;
2253 }
2254
2255 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2256 if (wback && BitIsClear (registers, n))
2257 {
2258 context.arg2 = offset;
2259 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2260 if (!success)
2261 return false;
2262 addr = addr + (addr_byte_size * BitCount (registers));
2263 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2264 return false;
2265 }
2266
2267 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2268 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002269 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002270 }
2271 return true;
2272}
Caroline Tice0b29e242011-02-08 23:16:02 +00002273
Johnny Chenef21b592011-02-10 01:52:38 +00002274// Load Register (immediate) calculates an address from a base register value and
2275// an immediate offset, loads a word from memory, and writes to a register.
2276// LDR (immediate, Thumb)
2277bool
2278EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2279{
2280#if 0
2281 // ARM pseudo code...
2282 if (ConditionPassed())
2283 {
2284 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2285 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2286 address = if index then offset_addr else R[n];
2287 data = MemU[address,4];
2288 if wback then R[n] = offset_addr;
2289 if t == 15 then
2290 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2291 elsif UnalignedSupport() || address<1:0> = '00' then
2292 R[t] = data;
2293 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2294 }
2295#endif
2296
2297 bool success = false;
2298 const uint32_t opcode = OpcodeAsUnsigned (&success);
2299 if (!success)
2300 return false;
2301
2302 if (ConditionPassed())
2303 {
2304 uint32_t Rt; // the destination register
2305 uint32_t Rn; // the base register
2306 uint32_t imm32; // the immediate offset used to form the address
2307 addr_t offset_addr; // the offset address
2308 addr_t address; // the calculated address
2309 uint32_t data; // the literal data value from memory load
2310 bool add, index, wback;
2311 switch (encoding) {
2312 case eEncodingT1:
2313 Rt = Bits32(opcode, 5, 3);
2314 Rn = Bits32(opcode, 2, 0);
2315 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2316 // index = TRUE; add = TRUE; wback = FALSE
2317 add = true;
2318 index = true;
2319 wback = false;
2320 break;
2321 default:
2322 return false;
2323 }
2324 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2325 if (!success)
2326 return false;
2327 if (add)
2328 offset_addr = base + imm32;
2329 else
2330 offset_addr = base - imm32;
2331
2332 address = (index ? offset_addr : base);
2333
2334 if (wback)
2335 {
2336 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2337 eRegisterKindDWARF,
2338 dwarf_r0 + Rn,
2339 (int32_t) (offset_addr - base)};
2340 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2341 return false;
2342 }
2343
2344 // Prepare to write to the Rt register.
2345 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2346 0,
2347 0,
2348 0};
2349
2350 // Read memory from the address.
2351 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2352 if (!success)
2353 return false;
2354 context.arg0 = data;
2355
2356 if (Rt == 15)
2357 {
2358 if (Bits32(address, 1, 0) == 0)
2359 {
2360 if (!LoadWritePC(context, data))
2361 return false;
2362 }
2363 else
2364 return false;
2365 }
2366 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2367 {
2368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2369 return false;
2370 }
2371 else
2372 return false;
2373 }
2374 return true;
2375}
2376
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002377EmulateInstructionARM::ARMOpcode*
2378EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002379{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002380 static ARMOpcode
2381 g_arm_opcodes[] =
2382 {
2383 //----------------------------------------------------------------------
2384 // Prologue instructions
2385 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002386
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002387 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002388 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2389 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002390
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002391 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002392 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2393 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002394 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002395 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2396 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2397 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002398
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002399 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002400 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002401
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002402 // push one register
2403 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002404 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002405
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002406 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002407 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2408 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002409
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002410 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002411 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002412 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002413
Johnny Chenc28a76d2011-02-01 18:51:48 +00002414 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2415 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002416 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002417 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2418
2419 //----------------------------------------------------------------------
2420 // Supervisor Call (previously Software Interrupt)
2421 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002422 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2423
2424 //----------------------------------------------------------------------
2425 // Branch instructions
2426 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002427 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002428 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2429 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2430 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2431 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002432
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002433 //----------------------------------------------------------------------
2434 // Load instructions
2435 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002436 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002437 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002438 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
2439 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002440
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002441 };
2442 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2443
2444 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2445 {
2446 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2447 return &g_arm_opcodes[i];
2448 }
2449 return NULL;
2450}
Greg Clayton64c84432011-01-21 22:02:52 +00002451
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002452
2453EmulateInstructionARM::ARMOpcode*
2454EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002455{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002456
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002457 static ARMOpcode
2458 g_thumb_opcodes[] =
2459 {
2460 //----------------------------------------------------------------------
2461 // Prologue instructions
2462 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002463
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002464 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002465 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002466 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2467 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002468
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002469 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002470 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002471 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002472 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002473 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2474 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002475
Johnny Chenc9de9102011-02-11 19:12:30 +00002476 // PC-relative load into register (see also EmulateAddSPRm)
2477 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002478
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002479 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002480 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2481 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002482 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2483 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002484
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002485 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002486 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2487 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002488
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002489 //----------------------------------------------------------------------
2490 // Epilogue instructions
2491 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002492
Johnny Chenc28a76d2011-02-01 18:51:48 +00002493 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2494 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002495 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2496 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2497 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2498 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002499
2500 //----------------------------------------------------------------------
2501 // Supervisor Call (previously Software Interrupt)
2502 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002503 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2504
2505 //----------------------------------------------------------------------
2506 // If Then makes up to four following instructions conditional.
2507 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002508 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2509
2510 //----------------------------------------------------------------------
2511 // Branch instructions
2512 //----------------------------------------------------------------------
2513 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2514 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2515 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002516 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002517 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00002518 // J1 == J2 == 1
2519 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2520 // J1 == J2 == 1
2521 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2522 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002523 // compare and branch
2524 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002525
2526 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002527 // Data-processing instructions
2528 //----------------------------------------------------------------------
2529 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2530 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002531 // move from high register to high register
2532 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2533 // move from low register to low register
2534 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00002535 // compare a register with immediate
2536 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002537
2538 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002539 // Load instructions
2540 //----------------------------------------------------------------------
2541 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002542 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002543 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00002544 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
2545 // Thumb2 PC-relative load into register
2546 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002547
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002548 };
2549
2550 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2551 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2552 {
2553 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2554 return &g_thumb_opcodes[i];
2555 }
2556 return NULL;
2557}
Greg Clayton64c84432011-01-21 22:02:52 +00002558
Greg Clayton31e2a382011-01-30 20:03:56 +00002559bool
2560EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2561{
2562 m_arm_isa = 0;
2563 const char *triple_cstr = triple.GetCString();
2564 if (triple_cstr)
2565 {
2566 const char *dash = ::strchr (triple_cstr, '-');
2567 if (dash)
2568 {
2569 std::string arch (triple_cstr, dash);
2570 const char *arch_cstr = arch.c_str();
2571 if (strcasecmp(arch_cstr, "armv4t") == 0)
2572 m_arm_isa = ARMv4T;
2573 else if (strcasecmp(arch_cstr, "armv4") == 0)
2574 m_arm_isa = ARMv4;
2575 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2576 m_arm_isa = ARMv5TEJ;
2577 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2578 m_arm_isa = ARMv5TE;
2579 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2580 m_arm_isa = ARMv5T;
2581 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2582 m_arm_isa = ARMv6K;
2583 else if (strcasecmp(arch_cstr, "armv6") == 0)
2584 m_arm_isa = ARMv6;
2585 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2586 m_arm_isa = ARMv6T2;
2587 else if (strcasecmp(arch_cstr, "armv7") == 0)
2588 m_arm_isa = ARMv7;
2589 else if (strcasecmp(arch_cstr, "armv8") == 0)
2590 m_arm_isa = ARMv8;
2591 }
2592 }
2593 return m_arm_isa != 0;
2594}
2595
2596
Greg Clayton64c84432011-01-21 22:02:52 +00002597bool
2598EmulateInstructionARM::ReadInstruction ()
2599{
2600 bool success = false;
2601 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2602 if (success)
2603 {
2604 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2605 if (success)
2606 {
2607 Context read_inst_context = {eContextReadOpcode, 0, 0};
2608 if (m_inst_cpsr & MASK_CPSR_T)
2609 {
2610 m_inst_mode = eModeThumb;
2611 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2612
2613 if (success)
2614 {
2615 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2616 {
2617 m_inst.opcode_type = eOpcode16;
2618 m_inst.opcode.inst16 = thumb_opcode;
2619 }
2620 else
2621 {
2622 m_inst.opcode_type = eOpcode32;
2623 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2624 }
2625 }
2626 }
2627 else
2628 {
2629 m_inst_mode = eModeARM;
2630 m_inst.opcode_type = eOpcode32;
2631 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2632 }
2633 }
2634 }
2635 if (!success)
2636 {
2637 m_inst_mode = eModeInvalid;
2638 m_inst_pc = LLDB_INVALID_ADDRESS;
2639 }
2640 return success;
2641}
2642
Johnny Chenee9b1f72011-02-09 01:00:31 +00002643uint32_t
2644EmulateInstructionARM::ArchVersion ()
2645{
2646 return m_arm_isa;
2647}
2648
Greg Clayton64c84432011-01-21 22:02:52 +00002649bool
2650EmulateInstructionARM::ConditionPassed ()
2651{
2652 if (m_inst_cpsr == 0)
2653 return false;
2654
2655 const uint32_t cond = CurrentCond ();
2656
2657 if (cond == UINT32_MAX)
2658 return false;
2659
2660 bool result = false;
2661 switch (UnsignedBits(cond, 3, 1))
2662 {
2663 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2664 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2665 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2666 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2667 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2668 case 5:
2669 {
2670 bool n = (m_inst_cpsr & MASK_CPSR_N);
2671 bool v = (m_inst_cpsr & MASK_CPSR_V);
2672 result = n == v;
2673 }
2674 break;
2675 case 6:
2676 {
2677 bool n = (m_inst_cpsr & MASK_CPSR_N);
2678 bool v = (m_inst_cpsr & MASK_CPSR_V);
2679 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2680 }
2681 break;
2682 case 7:
2683 result = true;
2684 break;
2685 }
2686
2687 if (cond & 1)
2688 result = !result;
2689 return result;
2690}
2691
Johnny Chen9ee056b2011-02-08 00:06:35 +00002692uint32_t
2693EmulateInstructionARM::CurrentCond ()
2694{
2695 switch (m_inst_mode)
2696 {
2697 default:
2698 case eModeInvalid:
2699 break;
2700
2701 case eModeARM:
2702 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2703
2704 case eModeThumb:
2705 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2706 // 'cond' field of the encoding.
2707 if (m_inst.opcode_type == eOpcode16 &&
2708 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2709 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2710 {
2711 return Bits32(m_inst.opcode.inst16, 11, 7);
2712 }
2713 else if (m_inst.opcode_type == eOpcode32 &&
2714 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2715 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2716 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2717 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2718 {
2719 return Bits32(m_inst.opcode.inst32, 25, 22);
2720 }
2721
2722 return m_it_session.GetCond();
2723 }
2724 return UINT32_MAX; // Return invalid value
2725}
2726
Johnny Chen9ee056b2011-02-08 00:06:35 +00002727bool
2728EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2729{
2730 addr_t target;
2731
Johnny Chenee9b1f72011-02-09 01:00:31 +00002732 // Check the current instruction set.
2733 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00002734 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002735 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00002736 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002737
Johnny Chen9ee056b2011-02-08 00:06:35 +00002738 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002739 return false;
2740
2741 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002742}
2743
2744// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2745bool
2746EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2747{
2748 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00002749 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
2750 // we want to record it and issue a WriteRegister callback so the clients
2751 // can track the mode changes accordingly.
2752 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002753
2754 if (BitIsSet(addr, 0))
2755 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002756 if (CurrentInstrSet() != eModeThumb)
2757 {
2758 SelectInstrSet(eModeThumb);
2759 cpsr_changed = true;
2760 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002761 target = addr & 0xfffffffe;
2762 context.arg2 = eModeThumb;
2763 }
2764 else if (BitIsClear(addr, 1))
2765 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002766 if (CurrentInstrSet() != eModeARM)
2767 {
2768 SelectInstrSet(eModeARM);
2769 cpsr_changed = true;
2770 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002771 target = addr & 0xfffffffc;
2772 context.arg2 = eModeARM;
2773 }
2774 else
2775 return false; // address<1:0> == '10' => UNPREDICTABLE
2776
Johnny Chen0f309db2011-02-09 19:11:32 +00002777 if (cpsr_changed)
2778 {
Johnny Chen558133b2011-02-09 23:59:17 +00002779 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00002780 return false;
2781 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002782 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002783 return false;
2784
2785 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002786}
Greg Clayton64c84432011-01-21 22:02:52 +00002787
Johnny Chenee9b1f72011-02-09 01:00:31 +00002788// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
2789bool
2790EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
2791{
2792 if (ArchVersion() >= ARMv5T)
2793 return BXWritePC(context, addr);
2794 else
2795 return BranchWritePC((const Context)context, addr);
2796}
2797
Johnny Chen26863dc2011-02-09 23:43:29 +00002798// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
2799bool
2800EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
2801{
2802 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
2803 return BXWritePC(context, addr);
2804 else
2805 return BranchWritePC((const Context)context, addr);
2806}
2807
Johnny Chenee9b1f72011-02-09 01:00:31 +00002808EmulateInstructionARM::Mode
2809EmulateInstructionARM::CurrentInstrSet ()
2810{
2811 return m_inst_mode;
2812}
2813
2814// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00002815// ReadInstruction() is performed. This function has a side effect of updating
2816// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00002817bool
2818EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
2819{
Johnny Chen558133b2011-02-09 23:59:17 +00002820 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002821 switch (arm_or_thumb)
2822 {
2823 default:
2824 return false;
2825 eModeARM:
2826 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002827 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002828 break;
2829 eModeThumb:
2830 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002831 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002832 break;
2833 }
2834 return true;
2835}
2836
Johnny Chenef21b592011-02-10 01:52:38 +00002837// This function returns TRUE if the processor currently provides support for
2838// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
2839// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
2840bool
2841EmulateInstructionARM::UnalignedSupport()
2842{
2843 return (ArchVersion() >= ARMv7);
2844}
2845
Johnny Chenbf6ad172011-02-11 01:29:53 +00002846// The main addition and subtraction instructions can produce status information
2847// about both unsigned carry and signed overflow conditions. This status
2848// information can be used to synthesize multi-word additions and subtractions.
2849EmulateInstructionARM::AddWithCarryResult
2850EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
2851{
2852 uint32_t result;
2853 uint8_t carry_out;
2854 uint8_t overflow;
2855
2856 uint64_t unsigned_sum = x + y + carry_in;
2857 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
2858
2859 result = UnsignedBits(unsigned_sum, 31, 0);
2860 carry_out = (result == unsigned_sum ? 0 : 1);
2861 overflow = ((int32_t)result == signed_sum ? 0 : 1);
2862
2863 AddWithCarryResult res = { result, carry_out, overflow };
2864 return res;
2865}
2866
Greg Clayton64c84432011-01-21 22:02:52 +00002867bool
2868EmulateInstructionARM::EvaluateInstruction ()
2869{
Johnny Chenc315f862011-02-05 00:46:10 +00002870 // Advance the ITSTATE bits to their values for the next instruction.
2871 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2872 m_it_session.ITAdvance();
2873
Greg Clayton64c84432011-01-21 22:02:52 +00002874 return false;
2875}