blob: f4e8a3f649f0e9151e1d4763142afc1a110f9680 [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
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000013#include "lldb/Core/ConstString.h"
14
Greg Claytonf29a08f2011-02-09 17:41:27 +000015#include "Plugins/Process/Utility/ARMDefines.h"
16#include "Plugins/Process/Utility/ARMUtils.h"
17#include "Utility/ARM_DWARF_Registers.h"
18
Johnny Chen9b8d7832011-02-02 01:13:56 +000019#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000020 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Johnny Chend6c13f02011-02-08 20:36:34 +000025static inline uint32_t Align(uint32_t val, uint32_t alignment)
26{
27 return alignment * (val / alignment);
28}
29
Johnny Chen0e00af22011-02-10 19:40:42 +000030//----------------------------------------------------------------------
31//
32// ITSession implementation
33//
34//----------------------------------------------------------------------
35
Johnny Chen93070472011-02-04 23:02:47 +000036// A8.6.50
37// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
38static unsigned short CountITSize(unsigned ITMask) {
39 // First count the trailing zeros of the IT mask.
40 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
41 if (TZ > 3)
42 {
43 printf("Encoding error: IT Mask '0000'\n");
44 return 0;
45 }
46 return (4 - TZ);
47}
48
49// Init ITState. Note that at least one bit is always 1 in mask.
50bool ITSession::InitIT(unsigned short bits7_0)
51{
52 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
53 if (ITCounter == 0)
54 return false;
55
56 // A8.6.50 IT
57 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
58 if (FirstCond == 0xF)
59 {
60 printf("Encoding error: IT FirstCond '1111'\n");
61 return false;
62 }
63 if (FirstCond == 0xE && ITCounter != 1)
64 {
65 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
66 return false;
67 }
68
69 ITState = bits7_0;
70 return true;
71}
72
73// Update ITState if necessary.
74void ITSession::ITAdvance()
75{
76 assert(ITCounter);
77 --ITCounter;
78 if (ITCounter == 0)
79 ITState = 0;
80 else
81 {
82 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
83 SetBits32(ITState, 4, 0, NewITState4_0);
84 }
85}
86
87// Return true if we're inside an IT Block.
88bool ITSession::InITBlock()
89{
90 return ITCounter != 0;
91}
92
Johnny Chenc315f862011-02-05 00:46:10 +000093// Return true if we're the last instruction inside an IT Block.
94bool ITSession::LastInITBlock()
95{
96 return ITCounter == 1;
97}
98
Johnny Chen93070472011-02-04 23:02:47 +000099// Get condition bits for the current thumb instruction.
100uint32_t ITSession::GetCond()
101{
Johnny Chenc315f862011-02-05 00:46:10 +0000102 if (InITBlock())
103 return Bits32(ITState, 7, 4);
104 else
105 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000106}
107
Greg Clayton64c84432011-01-21 22:02:52 +0000108// ARM constants used during decoding
109#define REG_RD 0
110#define LDM_REGLIST 1
111#define PC_REG 15
112#define PC_REGLIST_BIT 0x8000
113
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMv4T (1u << 1)
116#define ARMv5T (1u << 2)
117#define ARMv5TE (1u << 3)
118#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000119#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMv6K (1u << 6)
121#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000123#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMvAll (0xffffffffu)
125
Johnny Chen9b8d7832011-02-02 01:13:56 +0000126#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
127#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000129
Johnny Chen0e00af22011-02-10 19:40:42 +0000130//----------------------------------------------------------------------
131//
132// EmulateInstructionARM implementation
133//
134//----------------------------------------------------------------------
135
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000136void
137EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
145
Caroline Ticefa172202011-02-11 22:49:54 +0000146// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
147bool
148EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
149{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000150 EmulateInstruction::Context context;
151 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
152 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000153
154 uint32_t random_data = rand ();
155 const uint32_t addr_byte_size = GetAddressByteSize();
156
157 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
158 return false;
159
160 return true;
161}
162
Caroline Tice713c2662011-02-11 17:59:55 +0000163// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
164bool
165EmulateInstructionARM::WriteBits32Unknown (int n)
166{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000167 EmulateInstruction::Context context;
168 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
169 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000170
Johnny Chen62ff6f52011-02-11 18:11:22 +0000171 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000172 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
173
174 if (!success)
175 return false;
176
177 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
178 return false;
179
180 return true;
181}
182
Johnny Chen08c25e82011-01-31 18:02:28 +0000183// Push Multiple Registers stores multiple registers to the stack, storing to
184// consecutive memory locations ending just below the address in SP, and updates
185// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000186bool
187EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000188{
189#if 0
190 // ARM pseudo code...
191 if (ConditionPassed())
192 {
193 EncodingSpecificOperations();
194 NullCheckIfThumbEE(13);
195 address = SP - 4*BitCount(registers);
196
197 for (i = 0 to 14)
198 {
199 if (registers<i> == ’1’)
200 {
201 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
202 MemA[address,4] = bits(32) UNKNOWN;
203 else
204 MemA[address,4] = R[i];
205 address = address + 4;
206 }
207 }
208
209 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
210 MemA[address,4] = PCStoreValue();
211
212 SP = SP - 4*BitCount(registers);
213 }
214#endif
215
216 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000217 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 if (!success)
219 return false;
220
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000222 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t addr_byte_size = GetAddressByteSize();
224 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000225 if (!success)
226 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000227 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000228 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000230 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000231 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000233 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000234 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 // if BitCount(registers) < 1 then UNPREDICTABLE;
236 if (BitCount(registers) < 1)
237 return false;
238 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000239 case eEncodingT2:
240 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000241 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000242 // if BitCount(registers) < 2 then UNPREDICTABLE;
243 if (BitCount(registers) < 2)
244 return false;
245 break;
246 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000249 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000253 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000254 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000255 // Instead of return false, let's handle the following case as well,
256 // which amounts to pushing one reg onto the full descending stacks.
257 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000258 break;
259 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000261 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000262 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000263 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000266 default:
267 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 }
Johnny Chence1ca772011-01-25 01:13:00 +0000269 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000270 addr_t addr = sp - sp_offset;
271 uint32_t i;
272
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000273 EmulateInstruction::Context context;
274 context.type = EmulateInstruction::eContextPushRegisterOnStack;
275 Register dwarf_reg;
276 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000277 for (i=0; i<15; ++i)
278 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000279 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000280 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000281 dwarf_reg.num = dwarf_r0 + i;
282 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
283 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000284 if (!success)
285 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000286 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000287 return false;
288 addr += addr_byte_size;
289 }
290 }
291
Johnny Chen7c1bf922011-02-08 23:49:37 +0000292 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000293 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000294 dwarf_reg.num = dwarf_pc;
295 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000296 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000297 if (!success)
298 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000299 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000300 return false;
301 }
302
303 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000304 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000305
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000306 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000307 return false;
308 }
309 return true;
310}
311
Johnny Chenef85e912011-01-31 23:07:40 +0000312// Pop Multiple Registers loads multiple registers from the stack, loading from
313// consecutive memory locations staring at the address in SP, and updates
314// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000315bool
316EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000317{
318#if 0
319 // ARM pseudo code...
320 if (ConditionPassed())
321 {
322 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
323 address = SP;
324 for i = 0 to 14
325 if registers<i> == ‘1’ then
326 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
327 if registers<15> == ‘1’ then
328 if UnalignedAllowed then
329 LoadWritePC(MemU[address,4]);
330 else
331 LoadWritePC(MemA[address,4]);
332 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
333 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
334 }
335#endif
336
337 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000338 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000339 if (!success)
340 return false;
341
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000343 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 const uint32_t addr_byte_size = GetAddressByteSize();
345 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000346 if (!success)
347 return false;
348 uint32_t registers = 0;
349 uint32_t Rt; // the destination register
350 switch (encoding) {
351 case eEncodingT1:
352 registers = Bits32(opcode, 7, 0);
353 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000354 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000355 registers |= (1u << 15);
356 // if BitCount(registers) < 1 then UNPREDICTABLE;
357 if (BitCount(registers) < 1)
358 return false;
359 break;
360 case eEncodingT2:
361 // Ignore bit 13.
362 registers = Bits32(opcode, 15, 0) & ~0x2000;
363 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000364 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000365 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000366 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
367 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
368 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000369 break;
370 case eEncodingT3:
371 Rt = Bits32(opcode, 15, 12);
372 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000373 if (Rt == 13)
374 return false;
375 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000376 return false;
377 registers = (1u << Rt);
378 break;
379 case eEncodingA1:
380 registers = Bits32(opcode, 15, 0);
381 // Instead of return false, let's handle the following case as well,
382 // which amounts to popping one reg from the full descending stacks.
383 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
384
385 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000386 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000387 return false;
388 break;
389 case eEncodingA2:
390 Rt = Bits32(opcode, 15, 12);
391 // if t == 13 then UNPREDICTABLE;
392 if (Rt == dwarf_sp)
393 return false;
394 registers = (1u << Rt);
395 break;
396 default:
397 return false;
398 }
399 addr_t sp_offset = addr_byte_size * BitCount (registers);
400 addr_t addr = sp;
401 uint32_t i, data;
402
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000403 EmulateInstruction::Context context;
404 context.type = EmulateInstruction::eContextPopRegisterOffStack;
405 Register dwarf_reg;
406 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000407 for (i=0; i<15; ++i)
408 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000409 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 dwarf_reg.num = dwarf_r0 + i;
412 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000413 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000414 if (!success)
415 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000416 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000417 return false;
418 addr += addr_byte_size;
419 }
420 }
421
Johnny Chen7c1bf922011-02-08 23:49:37 +0000422 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000423 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000424 dwarf_reg.num = dwarf_pc;
425 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000427 if (!success)
428 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000429 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000430 if (!LoadWritePC(context, data, dwarf_reg))
Johnny Chenef85e912011-01-31 23:07:40 +0000431 return false;
432 addr += addr_byte_size;
433 }
434
435 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000436 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000437
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 }
441 return true;
442}
443
Johnny Chen5b442b72011-01-27 19:34:30 +0000444// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000445// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446bool
447EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448{
449#if 0
450 // ARM pseudo code...
451 if (ConditionPassed())
452 {
453 EncodingSpecificOperations();
454 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
455 if d == 15 then
456 ALUWritePC(result); // setflags is always FALSE here
457 else
458 R[d] = result;
459 if setflags then
460 APSR.N = result<31>;
461 APSR.Z = IsZeroBit(result);
462 APSR.C = carry;
463 APSR.V = overflow;
464 }
465#endif
466
467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if (!success)
470 return false;
471
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000494 EmulateInstruction::Context context;
495 context.type = EmulateInstruction::eContextRegisterPlusOffset;
496 Register sp_reg;
497 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
498 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000499
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501 return false;
502 }
503 return true;
504}
505
Johnny Chen2ccad832011-01-28 19:57:25 +0000506// Set r7 or ip to the current stack pointer.
507// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508bool
509EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000510{
511#if 0
512 // ARM pseudo code...
513 if (ConditionPassed())
514 {
515 EncodingSpecificOperations();
516 result = R[m];
517 if d == 15 then
518 ALUWritePC(result); // setflags is always FALSE here
519 else
520 R[d] = result;
521 if setflags then
522 APSR.N = result<31>;
523 APSR.Z = IsZeroBit(result);
524 // APSR.C unchanged
525 // APSR.V unchanged
526 }
527#endif
528
529 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000531 //if (!success)
532 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000533
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000535 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000537 if (!success)
538 return false;
539 uint32_t Rd; // the destination register
540 switch (encoding) {
541 case eEncodingT1:
542 Rd = 7;
543 break;
544 case eEncodingA1:
545 Rd = 12;
546 break;
547 default:
548 return false;
549 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000550
551 EmulateInstruction::Context context;
552 context.type = EmulateInstruction::eContextRegisterPlusOffset;
553 Register sp_reg;
554 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
555 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000556
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000557 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000558 return false;
559 }
560 return true;
561}
562
Johnny Chen1c13b622011-01-29 00:11:15 +0000563// Move from high register (r8-r15) to low register (r0-r7).
564// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000565bool
566EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000567{
Johnny Chen338bf542011-02-10 19:29:03 +0000568 return EmulateMovRdRm (encoding);
569}
570
571// Move from register to register.
572// MOV (register)
573bool
574EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
575{
Johnny Chen1c13b622011-01-29 00:11:15 +0000576#if 0
577 // ARM pseudo code...
578 if (ConditionPassed())
579 {
580 EncodingSpecificOperations();
581 result = R[m];
582 if d == 15 then
583 ALUWritePC(result); // setflags is always FALSE here
584 else
585 R[d] = result;
586 if setflags then
587 APSR.N = result<31>;
588 APSR.Z = IsZeroBit(result);
589 // APSR.C unchanged
590 // APSR.V unchanged
591 }
592#endif
593
594 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000595 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 if (!success)
597 return false;
598
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 {
601 uint32_t Rm; // the source register
602 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000603 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 switch (encoding) {
605 case eEncodingT1:
606 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000607 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000608 setflags = false;
609 break;
610 case eEncodingT2:
611 Rm = Bits32(opcode, 5, 3);
612 Rd = Bits32(opcode, 2, 1);
613 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 break;
615 default:
616 return false;
617 }
Johnny Chen338bf542011-02-10 19:29:03 +0000618 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000619 if (!success)
620 return false;
621
622 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000623 EmulateInstruction::Context context;
624 context.type = EmulateInstruction::eContextRegisterPlusOffset;
625 Register dwarf_reg;
626 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
627 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000628
Johnny Chen338bf542011-02-10 19:29:03 +0000629 if (Rd == 15)
630 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000631 if (!ALUWritePC (context, reg_value, dwarf_reg))
Johnny Chen338bf542011-02-10 19:29:03 +0000632 return false;
633 }
634 else
635 {
636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
637 return false;
638 if (setflags)
639 {
640 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000641 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
642 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000643 if (m_new_inst_cpsr != m_inst_cpsr)
644 {
645 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
646 return false;
647 }
648 }
649 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
658EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
677 bool success = false;
678 const uint32_t opcode = OpcodeAsUnsigned (&success);
679 if (!success)
680 return false;
681
682 if (ConditionPassed())
683 {
684 uint32_t Rd; // the destination register
685 uint32_t imm12; // some intermediate result
686 uint32_t imm32; // the immediate value to be written to Rd
687 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
688 bool setflags;
689 switch (encoding) {
690 case eEncodingT1:
691 Rd = Bits32(opcode, 11, 8);
692 setflags = !InITBlock();
693 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
694 carry = Bit32(m_inst_cpsr, CPSR_C);
695 break;
696 case eEncodingT2:
697 Rd = Bits32(opcode, 15, 12);
698 setflags = BitIsSet(opcode, 20);
699 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
700 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
701 break;
702 default:
703 return false;
704 }
705 uint32_t result = imm32;
706
707 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000708 EmulateInstruction::Context context;
709 context.type = EmulateInstruction::eContextImmediate;
710 context.SetNoArgs ();
711
712 Register dummy_reg;
713 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
714
Johnny Chen357c30f2011-02-14 22:04:25 +0000715 if (Rd == 15)
716 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000717 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen357c30f2011-02-14 22:04:25 +0000718 return false;
719 }
720 else
721 {
722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
723 return false;
724 if (setflags)
725 {
726 m_new_inst_cpsr = m_inst_cpsr;
727 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
728 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
729 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
730 if (m_new_inst_cpsr != m_inst_cpsr)
731 {
732 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
733 return false;
734 }
735 }
736 }
737 }
738 return true;
739}
740
Johnny Chen28070c32011-02-12 01:27:26 +0000741// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
742// the destination register. It can optionally update the condition flags based
743// on the value.
744// MVN (immediate)
745bool
746EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
747{
748#if 0
749 // ARM pseudo code...
750 if (ConditionPassed())
751 {
752 EncodingSpecificOperations();
753 result = NOT(imm32);
754 if d == 15 then // Can only occur for ARM encoding
755 ALUWritePC(result); // setflags is always FALSE here
756 else
757 R[d] = result;
758 if setflags then
759 APSR.N = result<31>;
760 APSR.Z = IsZeroBit(result);
761 APSR.C = carry;
762 // APSR.V unchanged
763 }
764#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 bool success = false;
766 const uint32_t opcode = OpcodeAsUnsigned (&success);
767 if (!success)
768 return false;
769
770 if (ConditionPassed())
771 {
772 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000773 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
774 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
775 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000776 bool setflags;
777 switch (encoding) {
778 case eEncodingT1:
779 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000780 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000781 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000782 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
783 break;
784 case eEncodingA1:
785 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000786 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000787 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000788 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
789 break;
790 default:
791 return false;
792 }
793 uint32_t result = ~imm32;
794
795 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000796 EmulateInstruction::Context context;
797 context.type = EmulateInstruction::eContextImmediate;
798 context.SetNoArgs ();
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000799
800 if (Rd == 15)
801 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000802 Register dummy_reg;
803 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000804 return false;
805 }
806 else
807 {
808 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
809 return false;
810 if (setflags)
811 {
812 m_new_inst_cpsr = m_inst_cpsr;
813 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
814 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
815 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
816 if (m_new_inst_cpsr != m_inst_cpsr)
817 {
818 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
819 return false;
820 }
821 }
822 }
823 }
824 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000825}
826
Johnny Chen788e0552011-01-27 22:52:23 +0000827// PC relative immediate load into register, possibly followed by ADD (SP plus register).
828// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000829bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000830EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000831{
832#if 0
833 // ARM pseudo code...
834 if (ConditionPassed())
835 {
836 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
837 base = Align(PC,4);
838 address = if add then (base + imm32) else (base - imm32);
839 data = MemU[address,4];
840 if t == 15 then
841 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
842 elsif UnalignedSupport() || address<1:0> = ‘00’ then
843 R[t] = data;
844 else // Can only apply before ARMv7
845 if CurrentInstrSet() == InstrSet_ARM then
846 R[t] = ROR(data, 8*UInt(address<1:0>));
847 else
848 R[t] = bits(32) UNKNOWN;
849 }
850#endif
851
852 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000853 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000854 if (!success)
855 return false;
856
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000857 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000858 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000859 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000860 if (!success)
861 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000862
863 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000864 EmulateInstruction::Context context;
865 context.type = EmulateInstruction::eContextRegisterPlusOffset;
866 Register pc_reg;
867 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
868 context.SetRegisterPlusOffset (pc_reg, 0);
869
Johnny Chenc9de9102011-02-11 19:12:30 +0000870 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000871 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000872 bool add; // +imm32 or -imm32?
873 addr_t base; // the base address
874 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000875 uint32_t data; // the literal data value from the PC relative load
876 switch (encoding) {
877 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000878 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000879 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000880 add = true;
881 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000882 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000883 break;
884 case eEncodingT2:
885 Rt = Bits32(opcode, 15, 12);
886 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
887 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000888 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000889 return false;
890 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000891 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000892 break;
893 default:
894 return false;
895 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000896
897 if (add)
898 address = base + imm32;
899 else
900 address = base - imm32;
901 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000902 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000903 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000904
905 if (Rt == 15)
906 {
907 if (Bits32(address, 1, 0) == 0)
908 {
909 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000910 if (!LoadWritePC(context, data, pc_reg))
Johnny Chenc9de9102011-02-11 19:12:30 +0000911 return false;
912 }
913 else
914 return false;
915 }
916 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
917 {
918 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
919 return false;
920 }
921 else // We don't handle ARM for now.
922 return false;
923
924 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000925 return false;
926 }
927 return true;
928}
929
Johnny Chen5b442b72011-01-27 19:34:30 +0000930// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000931// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000932bool
933EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000934{
935#if 0
936 // ARM pseudo code...
937 if (ConditionPassed())
938 {
939 EncodingSpecificOperations();
940 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
941 if d == 15 then // Can only occur for ARM encoding
942 ALUWritePC(result); // setflags is always FALSE here
943 else
944 R[d] = result;
945 if setflags then
946 APSR.N = result<31>;
947 APSR.Z = IsZeroBit(result);
948 APSR.C = carry;
949 APSR.V = overflow;
950 }
951#endif
952
953 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000954 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000955 if (!success)
956 return false;
957
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000958 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000959 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000960 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000961 if (!success)
962 return false;
963 uint32_t imm32; // the immediate operand
964 switch (encoding) {
965 case eEncodingT2:
966 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
967 break;
968 default:
969 return false;
970 }
971 addr_t sp_offset = imm32;
972 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
973
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000974 EmulateInstruction::Context context;
975 context.type = EmulateInstruction::eContextAdjustStackPointer;
976 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000977
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000978 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000979 return false;
980 }
981 return true;
982}
983
984// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000985// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000986bool
987EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000988{
989#if 0
990 // ARM pseudo code...
991 if (ConditionPassed())
992 {
993 EncodingSpecificOperations();
994 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
995 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
996 if d == 15 then
997 ALUWritePC(result); // setflags is always FALSE here
998 else
999 R[d] = result;
1000 if setflags then
1001 APSR.N = result<31>;
1002 APSR.Z = IsZeroBit(result);
1003 APSR.C = carry;
1004 APSR.V = overflow;
1005 }
1006#endif
1007
1008 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001009 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001010 if (!success)
1011 return false;
1012
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001013 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001014 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001015 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001016 if (!success)
1017 return false;
1018 uint32_t Rm; // the second operand
1019 switch (encoding) {
1020 case eEncodingT2:
1021 Rm = Bits32(opcode, 6, 3);
1022 break;
1023 default:
1024 return false;
1025 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001026 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001027 if (!success)
1028 return false;
1029
1030 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1031
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001032 EmulateInstruction::Context context;
1033 context.type = EmulateInstruction::eContextAdjustStackPointer;
1034 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001037 return false;
1038 }
1039 return true;
1040}
1041
Johnny Chen9b8d7832011-02-02 01:13:56 +00001042// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1043// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1044// from Thumb to ARM.
1045// BLX (immediate)
1046bool
1047EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1048{
1049#if 0
1050 // ARM pseudo code...
1051 if (ConditionPassed())
1052 {
1053 EncodingSpecificOperations();
1054 if CurrentInstrSet() == InstrSet_ARM then
1055 LR = PC - 4;
1056 else
1057 LR = PC<31:1> : '1';
1058 if targetInstrSet == InstrSet_ARM then
1059 targetAddress = Align(PC,4) + imm32;
1060 else
1061 targetAddress = PC + imm32;
1062 SelectInstrSet(targetInstrSet);
1063 BranchWritePC(targetAddress);
1064 }
1065#endif
1066
1067 bool success = false;
1068 const uint32_t opcode = OpcodeAsUnsigned (&success);
1069 if (!success)
1070 return false;
1071
1072 if (ConditionPassed())
1073 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001074 EmulateInstruction::Context context;
1075 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001076 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001077 if (!success)
1078 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001079 addr_t lr; // next instruction address
1080 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001081 int32_t imm32; // PC-relative offset
1082 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001083 case eEncodingT1:
1084 {
1085 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001086 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001087 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001088 uint32_t J1 = Bit32(opcode, 13);
1089 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001090 uint32_t imm11 = Bits32(opcode, 10, 0);
1091 uint32_t I1 = !(J1 ^ S);
1092 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001093 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001094 imm32 = llvm::SignExtend32<25>(imm25);
1095 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001096 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001097 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001098 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001099 break;
1100 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001101 case eEncodingT2:
1102 {
1103 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001104 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001105 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001106 uint32_t J1 = Bit32(opcode, 13);
1107 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001108 uint32_t imm10L = Bits32(opcode, 10, 1);
1109 uint32_t I1 = !(J1 ^ S);
1110 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001111 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001112 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001113 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001114 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001115 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001116 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001117 break;
1118 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001119 case eEncodingA1:
1120 lr = pc + 4; // return address
1121 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001122 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001123 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001124 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001125 case eEncodingA2:
1126 lr = pc + 4; // return address
1127 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1128 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001129 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001130 break;
1131 default:
1132 return false;
1133 }
1134 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1135 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001136 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001137 return false;
1138 }
1139 return true;
1140}
1141
1142// Branch with Link and Exchange (register) calls a subroutine at an address and
1143// instruction set specified by a register.
1144// BLX (register)
1145bool
1146EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1147{
1148#if 0
1149 // ARM pseudo code...
1150 if (ConditionPassed())
1151 {
1152 EncodingSpecificOperations();
1153 target = R[m];
1154 if CurrentInstrSet() == InstrSet_ARM then
1155 next_instr_addr = PC - 4;
1156 LR = next_instr_addr;
1157 else
1158 next_instr_addr = PC - 2;
1159 LR = next_instr_addr<31:1> : ‘1’;
1160 BXWritePC(target);
1161 }
1162#endif
1163
1164 bool success = false;
1165 const uint32_t opcode = OpcodeAsUnsigned (&success);
1166 if (!success)
1167 return false;
1168
1169 if (ConditionPassed())
1170 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001171 EmulateInstruction::Context context;
1172 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001173 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1174 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001175 if (!success)
1176 return false;
1177 uint32_t Rm; // the register with the target address
1178 switch (encoding) {
1179 case eEncodingT1:
1180 lr = (pc + 2) | 1u; // return address
1181 Rm = Bits32(opcode, 6, 3);
1182 // if m == 15 then UNPREDICTABLE;
1183 if (Rm == 15)
1184 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001185 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001186 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001187 break;
1188 case eEncodingA1:
1189 lr = pc + 4; // return address
1190 Rm = Bits32(opcode, 3, 0);
1191 // if m == 15 then UNPREDICTABLE;
1192 if (Rm == 15)
1193 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001194 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001195 default:
1196 return false;
1197 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001198 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1199 if (!success)
1200 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001201 Register dwarf_reg;
1202 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1203 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001204 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1205 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001206 if (!BXWritePC(context, target, dwarf_reg))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001207 return false;
1208 }
1209 return true;
1210}
1211
Johnny Chenab3b3512011-02-12 00:10:51 +00001212// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1213// BX
1214bool
1215EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1216{
1217#if 0
1218 // ARM pseudo code...
1219 if (ConditionPassed())
1220 {
1221 EncodingSpecificOperations();
1222 BXWritePC(R[m]);
1223 }
1224#endif
1225
1226 bool success = false;
1227 const uint32_t opcode = OpcodeAsUnsigned (&success);
1228 if (!success)
1229 return false;
1230
1231 if (ConditionPassed())
1232 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001233 EmulateInstruction::Context context;
1234 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001235 uint32_t Rm; // the register with the target address
1236 switch (encoding) {
1237 case eEncodingT1:
1238 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001239 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001240 return false;
1241 break;
1242 case eEncodingA1:
1243 Rm = Bits32(opcode, 3, 0);
1244 break;
1245 default:
1246 return false;
1247 }
1248 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1249 if (!success)
1250 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001251
1252 Register dwarf_reg;
1253 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1254 if (!BXWritePC(context, target, dwarf_reg))
Johnny Chenab3b3512011-02-12 00:10:51 +00001255 return false;
1256 }
1257 return true;
1258}
1259
Johnny Chen0d0148e2011-01-28 02:26:08 +00001260// Set r7 to point to some ip offset.
1261// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001262bool
1263EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001264{
1265#if 0
1266 // ARM pseudo code...
1267 if (ConditionPassed())
1268 {
1269 EncodingSpecificOperations();
1270 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1271 if d == 15 then // Can only occur for ARM encoding
1272 ALUWritePC(result); // setflags is always FALSE here
1273 else
1274 R[d] = result;
1275 if setflags then
1276 APSR.N = result<31>;
1277 APSR.Z = IsZeroBit(result);
1278 APSR.C = carry;
1279 APSR.V = overflow;
1280 }
1281#endif
1282
1283 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001284 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001285 if (!success)
1286 return false;
1287
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001288 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001289 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001290 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001291 if (!success)
1292 return false;
1293 uint32_t imm32;
1294 switch (encoding) {
1295 case eEncodingA1:
1296 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1297 break;
1298 default:
1299 return false;
1300 }
1301 addr_t ip_offset = imm32;
1302 addr_t addr = ip - ip_offset; // the adjusted ip value
1303
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 EmulateInstruction::Context context;
1305 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1306 Register dwarf_reg;
1307 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1308 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001309
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001311 return false;
1312 }
1313 return true;
1314}
1315
1316// Set ip to point to some stack offset.
1317// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001318bool
1319EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001320{
1321#if 0
1322 // ARM pseudo code...
1323 if (ConditionPassed())
1324 {
1325 EncodingSpecificOperations();
1326 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1327 if d == 15 then // Can only occur for ARM encoding
1328 ALUWritePC(result); // setflags is always FALSE here
1329 else
1330 R[d] = result;
1331 if setflags then
1332 APSR.N = result<31>;
1333 APSR.Z = IsZeroBit(result);
1334 APSR.C = carry;
1335 APSR.V = overflow;
1336 }
1337#endif
1338
1339 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001340 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001341 if (!success)
1342 return false;
1343
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001344 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001345 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347 if (!success)
1348 return false;
1349 uint32_t imm32;
1350 switch (encoding) {
1351 case eEncodingA1:
1352 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1353 break;
1354 default:
1355 return false;
1356 }
1357 addr_t sp_offset = imm32;
1358 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1359
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001360 EmulateInstruction::Context context;
1361 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1362 Register dwarf_reg;
1363 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1364 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001365
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001367 return false;
1368 }
1369 return true;
1370}
1371
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001372// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001373bool
1374EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001375{
1376#if 0
1377 // ARM pseudo code...
1378 if (ConditionPassed())
1379 {
1380 EncodingSpecificOperations();
1381 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1382 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001383 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001384 else
1385 R[d] = result;
1386 if setflags then
1387 APSR.N = result<31>;
1388 APSR.Z = IsZeroBit(result);
1389 APSR.C = carry;
1390 APSR.V = overflow;
1391 }
1392#endif
1393
1394 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001395 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001396 if (!success)
1397 return false;
1398
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001399 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001400 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001401 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001402 if (!success)
1403 return false;
1404 uint32_t imm32;
1405 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001406 case eEncodingT1:
1407 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001408 case eEncodingT2:
1409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1410 break;
1411 case eEncodingT3:
1412 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1413 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001414 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001415 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416 break;
1417 default:
1418 return false;
1419 }
1420 addr_t sp_offset = imm32;
1421 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1422
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001423 EmulateInstruction::Context context;
1424 context.type = EmulateInstruction::eContextAdjustStackPointer;
1425 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001426
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001427 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001428 return false;
1429 }
1430 return true;
1431}
1432
Johnny Chen08c25e82011-01-31 18:02:28 +00001433// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001434bool
1435EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001436{
1437#if 0
1438 // ARM pseudo code...
1439 if (ConditionPassed())
1440 {
1441 EncodingSpecificOperations();
1442 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1443 address = if index then offset_addr else R[n];
1444 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1445 if wback then R[n] = offset_addr;
1446 }
1447#endif
1448
1449 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001450 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001451 if (!success)
1452 return false;
1453
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001454 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001455 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001456 const uint32_t addr_byte_size = GetAddressByteSize();
1457 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001458 if (!success)
1459 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001460 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001461 uint32_t imm12;
1462 switch (encoding) {
1463 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001464 Rt = Bits32(opcode, 15, 12);
1465 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001466 break;
1467 default:
1468 return false;
1469 }
1470 addr_t sp_offset = imm12;
1471 addr_t addr = sp - sp_offset;
1472
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001473 EmulateInstruction::Context context;
1474 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1475 Register dwarf_reg;
1476 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001477 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001478 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001479 dwarf_reg.num = dwarf_r0 + Rt;
1480 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1481 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001482 if (!success)
1483 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001484 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001485 return false;
1486 }
1487 else
1488 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001489 dwarf_reg.num = dwarf_pc;
1490 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001491 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001492 if (!success)
1493 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001494 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001495 return false;
1496 }
1497
1498 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001499 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001500
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001501 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001502 return false;
1503 }
1504 return true;
1505}
1506
Johnny Chen08c25e82011-01-31 18:02:28 +00001507// Vector Push stores multiple extension registers to the stack.
1508// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001509bool
1510EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001511{
1512#if 0
1513 // ARM pseudo code...
1514 if (ConditionPassed())
1515 {
1516 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1517 address = SP - imm32;
1518 SP = SP - imm32;
1519 if single_regs then
1520 for r = 0 to regs-1
1521 MemA[address,4] = S[d+r]; address = address+4;
1522 else
1523 for r = 0 to regs-1
1524 // Store as two word-aligned words in the correct order for current endianness.
1525 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1526 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1527 address = address+8;
1528 }
1529#endif
1530
1531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001533 if (!success)
1534 return false;
1535
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001536 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001537 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001538 const uint32_t addr_byte_size = GetAddressByteSize();
1539 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001540 if (!success)
1541 return false;
1542 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001543 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001544 uint32_t imm32; // stack offset
1545 uint32_t regs; // number of registers
1546 switch (encoding) {
1547 case eEncodingT1:
1548 case eEncodingA1:
1549 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001550 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001551 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1552 // If UInt(imm8) is odd, see "FSTMX".
1553 regs = Bits32(opcode, 7, 0) / 2;
1554 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1555 if (regs == 0 || regs > 16 || (d + regs) > 32)
1556 return false;
1557 break;
1558 case eEncodingT2:
1559 case eEncodingA2:
1560 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001561 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001562 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1563 regs = Bits32(opcode, 7, 0);
1564 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1565 if (regs == 0 || regs > 16 || (d + regs) > 32)
1566 return false;
1567 break;
1568 default:
1569 return false;
1570 }
1571 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1572 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1573 addr_t sp_offset = imm32;
1574 addr_t addr = sp - sp_offset;
1575 uint32_t i;
1576
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001577 EmulateInstruction::Context context;
1578 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1579 Register dwarf_reg;
1580 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001581 for (i=d; i<regs; ++i)
1582 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001583 dwarf_reg.num = start_reg + i;
1584 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001585 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001586 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001587 if (!success)
1588 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001589 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001590 return false;
1591 addr += reg_byte_size;
1592 }
1593
1594 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001595 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001596
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001597 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001598 return false;
1599 }
1600 return true;
1601}
1602
Johnny Chen587a0a42011-02-01 18:35:28 +00001603// Vector Pop loads multiple extension registers from the stack.
1604// It also updates SP to point just above the loaded data.
1605bool
1606EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1607{
1608#if 0
1609 // ARM pseudo code...
1610 if (ConditionPassed())
1611 {
1612 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1613 address = SP;
1614 SP = SP + imm32;
1615 if single_regs then
1616 for r = 0 to regs-1
1617 S[d+r] = MemA[address,4]; address = address+4;
1618 else
1619 for r = 0 to regs-1
1620 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1621 // Combine the word-aligned words in the correct order for current endianness.
1622 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1623 }
1624#endif
1625
1626 bool success = false;
1627 const uint32_t opcode = OpcodeAsUnsigned (&success);
1628 if (!success)
1629 return false;
1630
1631 if (ConditionPassed())
1632 {
1633 const uint32_t addr_byte_size = GetAddressByteSize();
1634 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1635 if (!success)
1636 return false;
1637 bool single_regs;
1638 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1639 uint32_t imm32; // stack offset
1640 uint32_t regs; // number of registers
1641 switch (encoding) {
1642 case eEncodingT1:
1643 case eEncodingA1:
1644 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001645 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001646 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1647 // If UInt(imm8) is odd, see "FLDMX".
1648 regs = Bits32(opcode, 7, 0) / 2;
1649 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1650 if (regs == 0 || regs > 16 || (d + regs) > 32)
1651 return false;
1652 break;
1653 case eEncodingT2:
1654 case eEncodingA2:
1655 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001656 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001657 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1658 regs = Bits32(opcode, 7, 0);
1659 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1660 if (regs == 0 || regs > 16 || (d + regs) > 32)
1661 return false;
1662 break;
1663 default:
1664 return false;
1665 }
1666 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1667 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1668 addr_t sp_offset = imm32;
1669 addr_t addr = sp;
1670 uint32_t i;
1671 uint64_t data; // uint64_t to accomodate 64-bit registers.
1672
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001673 EmulateInstruction::Context context;
1674 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1675 Register dwarf_reg;
1676 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001677 for (i=d; i<regs; ++i)
1678 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679 dwarf_reg.num = start_reg + i;
1680 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chen587a0a42011-02-01 18:35:28 +00001681 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1682 if (!success)
1683 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001684 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001685 return false;
1686 addr += reg_byte_size;
1687 }
1688
1689 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001690 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001691
1692 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1693 return false;
1694 }
1695 return true;
1696}
1697
Johnny Chenb77be412011-02-04 00:40:18 +00001698// SVC (previously SWI)
1699bool
1700EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1701{
1702#if 0
1703 // ARM pseudo code...
1704 if (ConditionPassed())
1705 {
1706 EncodingSpecificOperations();
1707 CallSupervisor();
1708 }
1709#endif
1710
1711 bool success = false;
1712 const uint32_t opcode = OpcodeAsUnsigned (&success);
1713 if (!success)
1714 return false;
1715
1716 if (ConditionPassed())
1717 {
1718 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1719 addr_t lr; // next instruction address
1720 if (!success)
1721 return false;
1722 uint32_t imm32; // the immediate constant
1723 uint32_t mode; // ARM or Thumb mode
1724 switch (encoding) {
1725 case eEncodingT1:
1726 lr = (pc + 2) | 1u; // return address
1727 imm32 = Bits32(opcode, 7, 0);
1728 mode = eModeThumb;
1729 break;
1730 case eEncodingA1:
1731 lr = pc + 4; // return address
1732 imm32 = Bits32(opcode, 23, 0);
1733 mode = eModeARM;
1734 break;
1735 default:
1736 return false;
1737 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001738
1739 EmulateInstruction::Context context;
1740 context.type = EmulateInstruction::eContextSupervisorCall;
1741 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001742 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1743 return false;
1744 }
1745 return true;
1746}
1747
Johnny Chenc315f862011-02-05 00:46:10 +00001748// If Then makes up to four following instructions (the IT block) conditional.
1749bool
1750EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1751{
1752#if 0
1753 // ARM pseudo code...
1754 EncodingSpecificOperations();
1755 ITSTATE.IT<7:0> = firstcond:mask;
1756#endif
1757
1758 bool success = false;
1759 const uint32_t opcode = OpcodeAsUnsigned (&success);
1760 if (!success)
1761 return false;
1762
1763 m_it_session.InitIT(Bits32(opcode, 7, 0));
1764 return true;
1765}
1766
Johnny Chen3b620b32011-02-07 20:11:47 +00001767// Branch causes a branch to a target address.
1768bool
1769EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1770{
1771#if 0
1772 // ARM pseudo code...
1773 if (ConditionPassed())
1774 {
1775 EncodingSpecificOperations();
1776 BranchWritePC(PC + imm32);
1777 }
1778#endif
1779
1780 bool success = false;
1781 const uint32_t opcode = OpcodeAsUnsigned (&success);
1782 if (!success)
1783 return false;
1784
Johnny Chen9ee056b2011-02-08 00:06:35 +00001785 if (ConditionPassed())
1786 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001787 EmulateInstruction::Context context;
1788 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001789 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001790 if (!success)
1791 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001792 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001793 int32_t imm32; // PC-relative offset
1794 switch (encoding) {
1795 case eEncodingT1:
1796 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1797 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1798 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001799 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001800 break;
1801 case eEncodingT2:
1802 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1803 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001804 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001805 break;
1806 case eEncodingT3:
1807 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1808 {
Johnny Chenbd599902011-02-10 21:39:01 +00001809 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001810 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001811 uint32_t J1 = Bit32(opcode, 13);
1812 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001813 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001814 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001815 imm32 = llvm::SignExtend32<21>(imm21);
1816 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001817 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001818 break;
1819 }
1820 case eEncodingT4:
1821 {
Johnny Chenbd599902011-02-10 21:39:01 +00001822 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001823 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001824 uint32_t J1 = Bit32(opcode, 13);
1825 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001826 uint32_t imm11 = Bits32(opcode, 10, 0);
1827 uint32_t I1 = !(J1 ^ S);
1828 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001829 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001830 imm32 = llvm::SignExtend32<25>(imm25);
1831 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001832 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001833 break;
1834 }
1835 case eEncodingA1:
1836 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1837 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001838 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001839 break;
1840 default:
1841 return false;
1842 }
1843 if (!BranchWritePC(context, target))
1844 return false;
1845 }
1846 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001847}
1848
Johnny Chen53ebab72011-02-08 23:21:57 +00001849// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1850// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1851// CBNZ, CBZ
1852bool
1853EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1854{
1855#if 0
1856 // ARM pseudo code...
1857 EncodingSpecificOperations();
1858 if nonzero ^ IsZero(R[n]) then
1859 BranchWritePC(PC + imm32);
1860#endif
1861
1862 bool success = false;
1863 const uint32_t opcode = OpcodeAsUnsigned (&success);
1864 if (!success)
1865 return false;
1866
1867 // Read the register value from the operand register Rn.
1868 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1869 if (!success)
1870 return false;
1871
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001872 EmulateInstruction::Context context;
1873 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001874 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1875 if (!success)
1876 return false;
1877
1878 addr_t target; // target address
1879 uint32_t imm32; // PC-relative offset to branch forward
1880 bool nonzero;
1881 switch (encoding) {
1882 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001883 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001884 nonzero = BitIsSet(opcode, 11);
1885 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001886 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001887 break;
1888 default:
1889 return false;
1890 }
1891 if (nonzero ^ (reg_val == 0))
1892 if (!BranchWritePC(context, target))
1893 return false;
1894
1895 return true;
1896}
1897
Johnny Chen26863dc2011-02-09 23:43:29 +00001898// ADD <Rdn>, <Rm>
1899// where <Rdn> the destination register is also the first operand register
1900// and <Rm> is the second operand register.
1901bool
1902EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1903{
1904#if 0
1905 // ARM pseudo code...
1906 if ConditionPassed() then
1907 EncodingSpecificOperations();
1908 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1909 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1910 if d == 15 then
1911 ALUWritePC(result); // setflags is always FALSE here
1912 else
1913 R[d] = result;
1914 if setflags then
1915 APSR.N = result<31>;
1916 APSR.Z = IsZeroBit(result);
1917 APSR.C = carry;
1918 APSR.V = overflow;
1919#endif
1920
1921 bool success = false;
1922 const uint32_t opcode = OpcodeAsUnsigned (&success);
1923 if (!success)
1924 return false;
1925
1926 if (ConditionPassed())
1927 {
1928 uint32_t Rd, Rn, Rm;
1929 //bool setflags = false;
1930 switch (encoding)
1931 {
1932 case eEncodingT2:
1933 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001934 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001935 Rm = Bits32(opcode, 6, 3);
1936 if (Rn == 15 && Rm == 15)
1937 return false;
1938 break;
1939 default:
1940 return false;
1941 }
1942
1943 int32_t result, val1, val2;
1944 // Read the first operand.
1945 if (Rn == 15)
1946 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1947 else
1948 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1949 if (!success)
1950 return false;
1951
1952 // Read the second operand.
1953 if (Rm == 15)
1954 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1955 else
1956 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1957 if (!success)
1958 return false;
1959
1960 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001961
1962 EmulateInstruction::Context context;
1963 context.type = EmulateInstruction::eContextImmediate;
1964 context.SetNoArgs ();
1965 Register dummy_reg;
1966 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001967
1968 if (Rd == 15)
1969 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001970 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen26863dc2011-02-09 23:43:29 +00001971 return false;
1972 }
1973 else
1974 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001975 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001976 return false;
1977 }
1978 }
1979 return true;
1980}
1981
Johnny Chene4a4d302011-02-11 21:53:58 +00001982// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001983bool
1984EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1985{
1986#if 0
1987 // ARM pseudo code...
1988 if ConditionPassed() then
1989 EncodingSpecificOperations();
1990 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1991 APSR.N = result<31>;
1992 APSR.Z = IsZeroBit(result);
1993 APSR.C = carry;
1994 APSR.V = overflow;
1995#endif
1996
1997 bool success = false;
1998 const uint32_t opcode = OpcodeAsUnsigned (&success);
1999 if (!success)
2000 return false;
2001
2002 uint32_t Rn; // the first operand
2003 uint32_t imm32; // the immediate value to be compared with
2004 switch (encoding) {
2005 case eEncodingT1:
2006 Rn = Bits32(opcode, 10, 8);
2007 imm32 = Bits32(opcode, 7, 0);
2008 break;
2009 default:
2010 return false;
2011 }
2012 // Read the register value from the operand register Rn.
2013 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2014 if (!success)
2015 return false;
2016
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002017 EmulateInstruction::Context context;
2018 context.type = EmulateInstruction::eContextImmediate;
2019 context.SetNoArgs ();
2020
Johnny Chend4dc4442011-02-11 02:02:56 +00002021 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2022 m_new_inst_cpsr = m_inst_cpsr;
2023 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2024 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2025 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2026 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2027 if (m_new_inst_cpsr != m_inst_cpsr)
2028 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002029 EmulateInstruction::Context context;
2030 context.type = EmulateInstruction::eContextImmediate;
2031 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002032 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2033 return false;
2034 }
2035 return true;
2036}
2037
Johnny Chene4a4d302011-02-11 21:53:58 +00002038// CMP (register)
2039bool
2040EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2041{
2042#if 0
2043 // ARM pseudo code...
2044 if ConditionPassed() then
2045 EncodingSpecificOperations();
2046 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2047 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2048 APSR.N = result<31>;
2049 APSR.Z = IsZeroBit(result);
2050 APSR.C = carry;
2051 APSR.V = overflow;
2052#endif
2053
2054 bool success = false;
2055 const uint32_t opcode = OpcodeAsUnsigned (&success);
2056 if (!success)
2057 return false;
2058
2059 uint32_t Rn; // the first operand
2060 uint32_t Rm; // the second operand
2061 switch (encoding) {
2062 case eEncodingT1:
2063 Rn = Bits32(opcode, 2, 0);
2064 Rm = Bits32(opcode, 5, 3);
2065 break;
2066 case eEncodingT2:
2067 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2068 Rm = Bits32(opcode, 6, 3);
2069 if (Rn < 8 && Rm < 8)
2070 return false;
2071 if (Rn == 15 || Rm == 15)
2072 return false;
2073 break;
2074 default:
2075 return false;
2076 }
2077 // Read the register value from register Rn.
2078 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2079 if (!success)
2080 return false;
2081 // Read the register value from register Rm.
2082 // The register value is not being shifted since we don't handle ARM for now.
2083 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2084 if (!success)
2085 return false;
2086
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002087 EmulateInstruction::Context context;
2088 context.type = EmulateInstruction::eContextImmediate;
2089 context.SetNoArgs();
2090
Johnny Chene4a4d302011-02-11 21:53:58 +00002091 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2092 m_new_inst_cpsr = m_inst_cpsr;
2093 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2094 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2095 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2096 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2097 if (m_new_inst_cpsr != m_inst_cpsr)
2098 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002099 EmulateInstruction::Context context;
2100 context.type = EmulateInstruction::eContextImmediate;
2101 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002102 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2103 return false;
2104 }
2105 return true;
2106}
2107
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002108// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002109// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002110// can be written back to the base register.
2111bool
2112EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2113{
2114#if 0
2115 // ARM pseudo code...
2116 if ConditionPassed()
2117 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2118 address = R[n];
2119
2120 for i = 0 to 14
2121 if registers<i> == '1' then
2122 R[i] = MemA[address, 4]; address = address + 4;
2123 if registers<15> == '1' then
2124 LoadWritePC (MemA[address, 4]);
2125
2126 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2127 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2128
2129#endif
2130
2131 bool success = false;
2132 const uint32_t opcode = OpcodeAsUnsigned (&success);
2133 if (!success)
2134 return false;
2135
2136 if (ConditionPassed())
2137 {
2138 uint32_t n;
2139 uint32_t registers = 0;
2140 bool wback;
2141 const uint32_t addr_byte_size = GetAddressByteSize();
2142 switch (encoding)
2143 {
2144 case eEncodingT1:
2145 n = Bits32 (opcode, 10, 8);
2146 registers = Bits32 (opcode, 7, 0);
2147 wback = BitIsClear (registers, n);
2148 // if BitCount(registers) < 1 then UNPREDICTABLE;
2149 if (BitCount(registers) < 1)
2150 return false;
2151 break;
2152 case eEncodingT2:
2153 n = Bits32 (opcode, 19, 16);
2154 registers = Bits32 (opcode, 15, 0);
2155 wback = BitIsSet (opcode, 21);
2156 if ((n == 15)
2157 || (BitCount (registers) < 2)
2158 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2159 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002160 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002161 return false;
2162 if (wback
2163 && BitIsSet (registers, n))
2164 return false;
2165 break;
2166 case eEncodingA1:
2167 n = Bits32 (opcode, 19, 16);
2168 registers = Bits32 (opcode, 15, 0);
2169 wback = BitIsSet (opcode, 21);
2170 if ((n == 15)
2171 || (BitCount (registers) < 1))
2172 return false;
2173 break;
2174 default:
2175 return false;
2176 }
2177
2178 int32_t offset = 0;
2179 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2180 if (!success)
2181 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002182
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002183 EmulateInstruction::Context context;
2184 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2185 Register dwarf_reg;
2186 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2187 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002188
2189 for (int i = 0; i < 14; ++i)
2190 {
2191 if (BitIsSet (registers, i))
2192 {
Caroline Tice85aab332011-02-08 23:56:10 +00002193 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002194 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002195 if (wback && (n == 13)) // Pop Instruction
2196 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2197
2198 // R[i] = MemA [address, 4]; address = address + 4;
2199 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2200 if (!success)
2201 return false;
2202
2203 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2204 return false;
2205
2206 offset += addr_byte_size;
2207 }
2208 }
2209
2210 if (BitIsSet (registers, 15))
2211 {
2212 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002213 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002214 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002215 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2216 if (!success)
2217 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002218 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002219 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002220 return false;
2221 }
2222
2223 if (wback && BitIsClear (registers, n))
2224 {
Caroline Ticefa172202011-02-11 22:49:54 +00002225 // R[n] = R[n] + 4 * BitCount (registers)
2226 int32_t offset = addr_byte_size * BitCount (registers);
2227 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002228 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002229
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002230 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2231 return false;
2232 }
2233 if (wback && BitIsSet (registers, n))
2234 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002235 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002236 }
2237 return true;
2238}
Caroline Tice713c2662011-02-11 17:59:55 +00002239
2240// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2241// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2242// can optionally be written back tot he base registers.
2243bool
2244EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2245{
2246#if 0
2247 // ARM pseudo code...
2248 if ConditionPassed() then
2249 EncodingSpecificOperations();
2250 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002251
Caroline Tice713c2662011-02-11 17:59:55 +00002252 for i = 0 to 14
2253 if registers<i> == ’1’ then
2254 R[i] = MemA[address,4]; address = address + 4;
2255
2256 if registers<15> == ’1’ then
2257 LoadWritePC(MemA[address,4]);
2258
2259 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2260 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2261#endif
2262
2263 bool success = false;
2264 const uint32_t opcode = OpcodeAsUnsigned (&success);
2265 if (!success)
2266 return false;
2267
2268 if (ConditionPassed())
2269 {
2270 uint32_t n;
2271 uint32_t registers = 0;
2272 bool wback;
2273 const uint32_t addr_byte_size = GetAddressByteSize();
2274
2275 // EncodingSpecificOperations();
2276 switch (encoding)
2277 {
2278 case eEncodingA1:
2279 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2280 n = Bits32 (opcode, 19, 16);
2281 registers = Bits32 (opcode, 15, 0);
2282 wback = BitIsSet (opcode, 21);
2283
2284 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2285 if ((n == 15) || (BitCount (registers) < 1))
2286 return false;
2287
2288 break;
2289
2290 default:
2291 return false;
2292 }
2293 // address = R[n] - 4*BitCount(registers) + 4;
2294
2295 int32_t offset = 0;
2296 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2297
2298 if (!success)
2299 return false;
2300
2301 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2302
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002303 EmulateInstruction::Context context;
2304 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2305 Register dwarf_reg;
2306 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2307 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002308
2309 // for i = 0 to 14
2310 for (int i = 0; i < 14; ++i)
2311 {
2312 // if registers<i> == ’1’ then
2313 if (BitIsSet (registers, i))
2314 {
2315 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002316 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002317 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2318 if (!success)
2319 return false;
2320 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2321 return false;
2322 offset += addr_byte_size;
2323 }
2324 }
2325
2326 // if registers<15> == ’1’ then
2327 // LoadWritePC(MemA[address,4]);
2328 if (BitIsSet (registers, 15))
2329 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002330 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002331 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2332 if (!success)
2333 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002334 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002335 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice713c2662011-02-11 17:59:55 +00002336 return false;
2337 }
2338
2339 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2340 if (wback && BitIsClear (registers, n))
2341 {
Caroline Tice713c2662011-02-11 17:59:55 +00002342 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2343 if (!success)
2344 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002345
2346 offset = (addr_byte_size * BitCount (registers)) * -1;
2347 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002348 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002349 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002350 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2351 return false;
2352 }
2353
2354 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2355 if (wback && BitIsSet (registers, n))
2356 return WriteBits32Unknown (n);
2357 }
2358 return true;
2359}
2360
2361// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2362// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2363// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002364bool
2365EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2366{
2367#if 0
2368 // ARM pseudo code...
2369 if ConditionPassed() then
2370 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2371 address = R[n] - 4*BitCount(registers);
2372
2373 for i = 0 to 14
2374 if registers<i> == ’1’ then
2375 R[i] = MemA[address,4]; address = address + 4;
2376 if registers<15> == ’1’ then
2377 LoadWritePC(MemA[address,4]);
2378
2379 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2380 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2381#endif
2382
2383 bool success = false;
2384 const uint32_t opcode = OpcodeAsUnsigned (&success);
2385 if (!success)
2386 return false;
2387
2388 if (ConditionPassed())
2389 {
2390 uint32_t n;
2391 uint32_t registers = 0;
2392 bool wback;
2393 const uint32_t addr_byte_size = GetAddressByteSize();
2394 switch (encoding)
2395 {
2396 case eEncodingT1:
2397 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2398 n = Bits32 (opcode, 19, 16);
2399 registers = Bits32 (opcode, 15, 0);
2400 wback = BitIsSet (opcode, 21);
2401
2402 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2403 if ((n == 15)
2404 || (BitCount (registers) < 2)
2405 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2406 return false;
2407
2408 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002409 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002410 return false;
2411
2412 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2413 if (wback && BitIsSet (registers, n))
2414 return false;
2415
2416 break;
2417
2418 case eEncodingA1:
2419 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2420 n = Bits32 (opcode, 19, 16);
2421 registers = Bits32 (opcode, 15, 0);
2422 wback = BitIsSet (opcode, 21);
2423
2424 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2425 if ((n == 15) || (BitCount (registers) < 1))
2426 return false;
2427
2428 break;
2429
2430 default:
2431 return false;
2432 }
2433
Caroline Tice713c2662011-02-11 17:59:55 +00002434 // address = R[n] - 4*BitCount(registers);
2435
Caroline Tice0b29e242011-02-08 23:16:02 +00002436 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002437 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2438
2439 if (!success)
2440 return false;
2441
2442 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002443 EmulateInstruction::Context context;
2444 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2445 Register dwarf_reg;
2446 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2447 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002448
2449 for (int i = 0; i < 14; ++i)
2450 {
2451 if (BitIsSet (registers, i))
2452 {
2453 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002454 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002455 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2456 if (!success)
2457 return false;
2458
2459 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2460 return false;
2461
2462 offset += addr_byte_size;
2463 }
2464 }
2465
2466 // if registers<15> == ’1’ then
2467 // LoadWritePC(MemA[address,4]);
2468 if (BitIsSet (registers, 15))
2469 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002470 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002471 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2472 if (!success)
2473 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002474 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002475 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice0b29e242011-02-08 23:16:02 +00002476 return false;
2477 }
2478
2479 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2480 if (wback && BitIsClear (registers, n))
2481 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002482 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2483 if (!success)
2484 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002485
2486 offset = (addr_byte_size * BitCount (registers)) * -1;
2487 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002488 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002489 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002490 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2491 return false;
2492 }
2493
2494 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2495 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002496 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002497 }
2498 return true;
2499}
Caroline Tice85aab332011-02-08 23:56:10 +00002500
Caroline Tice713c2662011-02-11 17:59:55 +00002501// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2502// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2503// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002504bool
2505EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2506{
2507#if 0
2508 if ConditionPassed() then
2509 EncodingSpecificOperations();
2510 address = R[n] + 4;
2511
2512 for i = 0 to 14
2513 if registers<i> == ’1’ then
2514 R[i] = MemA[address,4]; address = address + 4;
2515 if registers<15> == ’1’ then
2516 LoadWritePC(MemA[address,4]);
2517
2518 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2519 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2520#endif
2521
2522 bool success = false;
2523 const uint32_t opcode = OpcodeAsUnsigned (&success);
2524 if (!success)
2525 return false;
2526
2527 if (ConditionPassed())
2528 {
2529 uint32_t n;
2530 uint32_t registers = 0;
2531 bool wback;
2532 const uint32_t addr_byte_size = GetAddressByteSize();
2533 switch (encoding)
2534 {
2535 case eEncodingA1:
2536 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2537 n = Bits32 (opcode, 19, 16);
2538 registers = Bits32 (opcode, 15, 0);
2539 wback = BitIsSet (opcode, 21);
2540
2541 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2542 if ((n == 15) || (BitCount (registers) < 1))
2543 return false;
2544
2545 break;
2546 default:
2547 return false;
2548 }
2549 // address = R[n] + 4;
2550
2551 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002552 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2553
2554 if (!success)
2555 return false;
2556
2557 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002558
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002559 EmulateInstruction::Context context;
2560 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2561 Register dwarf_reg;
2562 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2563 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002564
2565 for (int i = 0; i < 14; ++i)
2566 {
2567 if (BitIsSet (registers, i))
2568 {
2569 // R[i] = MemA[address,4]; address = address + 4;
2570
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002571 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002572 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2573 if (!success)
2574 return false;
2575
2576 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2577 return false;
2578
2579 offset += addr_byte_size;
2580 }
2581 }
2582
2583 // if registers<15> == ’1’ then
2584 // LoadWritePC(MemA[address,4]);
2585 if (BitIsSet (registers, 15))
2586 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002587 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002588 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2589 if (!success)
2590 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002591 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002592 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice85aab332011-02-08 23:56:10 +00002593 return false;
2594 }
2595
2596 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2597 if (wback && BitIsClear (registers, n))
2598 {
Caroline Tice85aab332011-02-08 23:56:10 +00002599 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2600 if (!success)
2601 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002602
2603 offset = addr_byte_size * BitCount (registers);
2604 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002605 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002606 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2608 return false;
2609 }
2610
2611 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2612 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002613 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002614 }
2615 return true;
2616}
Caroline Tice0b29e242011-02-08 23:16:02 +00002617
Johnny Chenef21b592011-02-10 01:52:38 +00002618// Load Register (immediate) calculates an address from a base register value and
2619// an immediate offset, loads a word from memory, and writes to a register.
2620// LDR (immediate, Thumb)
2621bool
2622EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2623{
2624#if 0
2625 // ARM pseudo code...
2626 if (ConditionPassed())
2627 {
2628 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2629 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2630 address = if index then offset_addr else R[n];
2631 data = MemU[address,4];
2632 if wback then R[n] = offset_addr;
2633 if t == 15 then
2634 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2635 elsif UnalignedSupport() || address<1:0> = '00' then
2636 R[t] = data;
2637 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2638 }
2639#endif
2640
2641 bool success = false;
2642 const uint32_t opcode = OpcodeAsUnsigned (&success);
2643 if (!success)
2644 return false;
2645
2646 if (ConditionPassed())
2647 {
2648 uint32_t Rt; // the destination register
2649 uint32_t Rn; // the base register
2650 uint32_t imm32; // the immediate offset used to form the address
2651 addr_t offset_addr; // the offset address
2652 addr_t address; // the calculated address
2653 uint32_t data; // the literal data value from memory load
2654 bool add, index, wback;
2655 switch (encoding) {
2656 case eEncodingT1:
2657 Rt = Bits32(opcode, 5, 3);
2658 Rn = Bits32(opcode, 2, 0);
2659 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2660 // index = TRUE; add = TRUE; wback = FALSE
2661 add = true;
2662 index = true;
2663 wback = false;
2664 break;
2665 default:
2666 return false;
2667 }
2668 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2669 if (!success)
2670 return false;
2671 if (add)
2672 offset_addr = base + imm32;
2673 else
2674 offset_addr = base - imm32;
2675
2676 address = (index ? offset_addr : base);
2677
2678 if (wback)
2679 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002680 EmulateInstruction::Context ctx;
2681 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
2682 Register dwarf_reg;
2683 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2684 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
2685
Johnny Chenef21b592011-02-10 01:52:38 +00002686 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2687 return false;
2688 }
2689
2690 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002691 EmulateInstruction::Context context;
2692 context.type = EmulateInstruction::eContextImmediate;
2693 context.SetNoArgs ();
2694 Register dummy_reg;
2695 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
Johnny Chenef21b592011-02-10 01:52:38 +00002696
2697 // Read memory from the address.
2698 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2699 if (!success)
2700 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00002701
2702 if (Rt == 15)
2703 {
2704 if (Bits32(address, 1, 0) == 0)
2705 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002706 if (!LoadWritePC(context, data, dummy_reg))
Johnny Chenef21b592011-02-10 01:52:38 +00002707 return false;
2708 }
2709 else
2710 return false;
2711 }
2712 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2713 {
2714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2715 return false;
2716 }
2717 else
2718 return false;
2719 }
2720 return true;
2721}
2722
Caroline Ticefa172202011-02-11 22:49:54 +00002723// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2724// consecutive memory locations start at this address, and teh address just above the last of those locations can
2725// optionally be written back to the base register.
2726bool
2727EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2728{
2729#if 0
2730 if ConditionPassed() then
2731 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2732 address = R[n];
2733
2734 for i = 0 to 14
2735 if registers<i> == ’1’ then
2736 if i == n && wback && i != LowestSetBit(registers) then
2737 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2738 else
2739 MemA[address,4] = R[i];
2740 address = address + 4;
2741
2742 if registers<15> == ’1’ then // Only possible for encoding A1
2743 MemA[address,4] = PCStoreValue();
2744 if wback then R[n] = R[n] + 4*BitCount(registers);
2745#endif
2746
2747 bool success = false;
2748 const uint32_t opcode = OpcodeAsUnsigned (&success);
2749 if (!success)
2750 return false;
2751
2752 if (ConditionPassed ())
2753 {
2754 uint32_t n;
2755 uint32_t registers = 0;
2756 bool wback;
2757 const uint32_t addr_byte_size = GetAddressByteSize();
2758
2759 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2760 switch (encoding)
2761 {
2762 case eEncodingT1:
2763 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2764 n = Bits32 (opcode, 10, 8);
2765 registers = Bits32 (opcode, 7, 0);
2766 wback = true;
2767
2768 // if BitCount(registers) < 1 then UNPREDICTABLE;
2769 if (BitCount (registers) < 1)
2770 return false;
2771
2772 break;
2773
2774 case eEncodingT2:
2775 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2776 n = Bits32 (opcode, 19, 16);
2777 registers = Bits32 (opcode, 15, 0);
2778 wback = BitIsSet (opcode, 21);
2779
2780 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2781 if ((n == 15) || (BitCount (registers) < 2))
2782 return false;
2783
2784 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2785 if (wback && BitIsSet (registers, n))
2786 return false;
2787
2788 break;
2789
2790 case eEncodingA1:
2791 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2792 n = Bits32 (opcode, 19, 16);
2793 registers = Bits32 (opcode, 15, 0);
2794 wback = BitIsSet (opcode, 21);
2795
2796 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2797 if ((n == 15) || (BitCount (registers) < 1))
2798 return false;
2799
2800 break;
2801
2802 default:
2803 return false;
2804 }
2805
2806 // address = R[n];
2807 int32_t offset = 0;
2808 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2809 if (!success)
2810 return false;
2811
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002812 EmulateInstruction::Context context;
2813 context.type = EmulateInstruction::eContextRegisterStore;
2814 Register base_reg;
2815 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00002816
2817 // for i = 0 to 14
2818 for (int i = 0; i < 14; ++i)
2819 {
2820 int lowest_set_bit = 14;
2821 // if registers<i> == ’1’ then
2822 if (BitIsSet (registers, i))
2823 {
2824 if (i < lowest_set_bit)
2825 lowest_set_bit = i;
2826 // if i == n && wback && i != LowestSetBit(registers) then
2827 if ((i == n) && wback && (i != lowest_set_bit))
2828 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2829 WriteBits32UnknownToMemory (address + offset);
2830 else
2831 {
2832 // MemA[address,4] = R[i];
2833 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2834 if (!success)
2835 return false;
2836
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002837 Register data_reg;
2838 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
2839 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002840 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2841 return false;
2842 }
2843
2844 // address = address + 4;
2845 offset += addr_byte_size;
2846 }
2847 }
2848
2849 // if registers<15> == ’1’ then // Only possible for encoding A1
2850 // MemA[address,4] = PCStoreValue();
2851 if (BitIsSet (registers, 15))
2852 {
2853 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2854 if (!success)
2855 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002856
2857 Register pc_reg;
2858 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
2859 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00002860 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2861 if (!success)
2862 return false;
2863
2864 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2865 return false;
2866 }
2867
2868 // if wback then R[n] = R[n] + 4*BitCount(registers);
2869 if (wback)
2870 {
2871 offset = addr_byte_size * BitCount (registers);
2872 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002873 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002874 addr_t data = address + offset;
2875 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2876 return false;
2877 }
2878 }
2879 return true;
2880}
2881
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002882EmulateInstructionARM::ARMOpcode*
2883EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002884{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002885 static ARMOpcode
2886 g_arm_opcodes[] =
2887 {
2888 //----------------------------------------------------------------------
2889 // Prologue instructions
2890 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002891
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002892 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002893 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2894 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002895
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002896 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002897 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2898 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002899 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002900 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2901 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2902 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002903
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002904 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002905 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002906
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002907 // push one register
2908 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002909 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002910
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002911 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002912 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2913 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002914
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002915 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002916 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002917 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002918
Johnny Chenc28a76d2011-02-01 18:51:48 +00002919 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2920 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002921 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002922 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2923
2924 //----------------------------------------------------------------------
2925 // Supervisor Call (previously Software Interrupt)
2926 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002927 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2928
2929 //----------------------------------------------------------------------
2930 // Branch instructions
2931 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002932 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002933 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2934 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2935 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2936 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002937 // for example, "bx lr"
2938 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002939
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002940 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00002941 // Data-processing instructions
2942 //----------------------------------------------------------------------
2943 // move bitwise not
2944 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
2945
2946 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002947 // Load instructions
2948 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002949 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002950 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002951 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002952 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2953
2954 //----------------------------------------------------------------------
2955 // Store instructions
2956 //----------------------------------------------------------------------
2957 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002958
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002959 };
2960 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2961
2962 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2963 {
2964 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2965 return &g_arm_opcodes[i];
2966 }
2967 return NULL;
2968}
Greg Clayton64c84432011-01-21 22:02:52 +00002969
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002970
2971EmulateInstructionARM::ARMOpcode*
2972EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002973{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002974
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002975 static ARMOpcode
2976 g_thumb_opcodes[] =
2977 {
2978 //----------------------------------------------------------------------
2979 // Prologue instructions
2980 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002981
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002982 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002983 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002984 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2985 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002986
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002987 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002988 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002989 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002990 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002991 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2992 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002993
Johnny Chenc9de9102011-02-11 19:12:30 +00002994 // PC-relative load into register (see also EmulateAddSPRm)
2995 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002996
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002997 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002998 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2999 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003000 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
3001 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003002
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003003 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00003004 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3005 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003006
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003007 //----------------------------------------------------------------------
3008 // Epilogue instructions
3009 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00003010
Johnny Chenc28a76d2011-02-01 18:51:48 +00003011 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
3012 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003013 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
3014 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
3015 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
3016 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003017
3018 //----------------------------------------------------------------------
3019 // Supervisor Call (previously Software Interrupt)
3020 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00003021 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
3022
3023 //----------------------------------------------------------------------
3024 // If Then makes up to four following instructions conditional.
3025 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00003026 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
3027
3028 //----------------------------------------------------------------------
3029 // Branch instructions
3030 //----------------------------------------------------------------------
3031 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
3032 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
3033 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00003034 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003035 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00003036 // J1 == J2 == 1
3037 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3038 // J1 == J2 == 1
3039 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3040 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003041 // for example, "bx lr"
3042 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00003043 // compare and branch
3044 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003045
3046 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00003047 // Data-processing instructions
3048 //----------------------------------------------------------------------
3049 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
3050 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00003051 // move from high register to high register
3052 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
3053 // move from low register to low register
3054 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00003055 // move immediate
3056 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
3057 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00003058 // move bitwise not
3059 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00003060 // compare a register with immediate
3061 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00003062 // compare Rn with Rm (Rn and Rm both from r0-r7)
3063 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
3064 // compare Rn with Rm (Rn and Rm not both from r0-r7)
3065 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00003066
3067 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003068 // Load instructions
3069 //----------------------------------------------------------------------
3070 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00003071 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00003072 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00003073 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
3074 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00003075 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
3076
3077 //----------------------------------------------------------------------
3078 // Store instructions
3079 //----------------------------------------------------------------------
3080 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
3081 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003082
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003083 };
3084
3085 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
3086 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
3087 {
3088 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
3089 return &g_thumb_opcodes[i];
3090 }
3091 return NULL;
3092}
Greg Clayton64c84432011-01-21 22:02:52 +00003093
Greg Clayton31e2a382011-01-30 20:03:56 +00003094bool
3095EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
3096{
3097 m_arm_isa = 0;
3098 const char *triple_cstr = triple.GetCString();
3099 if (triple_cstr)
3100 {
3101 const char *dash = ::strchr (triple_cstr, '-');
3102 if (dash)
3103 {
3104 std::string arch (triple_cstr, dash);
3105 const char *arch_cstr = arch.c_str();
3106 if (strcasecmp(arch_cstr, "armv4t") == 0)
3107 m_arm_isa = ARMv4T;
3108 else if (strcasecmp(arch_cstr, "armv4") == 0)
3109 m_arm_isa = ARMv4;
3110 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
3111 m_arm_isa = ARMv5TEJ;
3112 else if (strcasecmp(arch_cstr, "armv5te") == 0)
3113 m_arm_isa = ARMv5TE;
3114 else if (strcasecmp(arch_cstr, "armv5t") == 0)
3115 m_arm_isa = ARMv5T;
3116 else if (strcasecmp(arch_cstr, "armv6k") == 0)
3117 m_arm_isa = ARMv6K;
3118 else if (strcasecmp(arch_cstr, "armv6") == 0)
3119 m_arm_isa = ARMv6;
3120 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
3121 m_arm_isa = ARMv6T2;
3122 else if (strcasecmp(arch_cstr, "armv7") == 0)
3123 m_arm_isa = ARMv7;
3124 else if (strcasecmp(arch_cstr, "armv8") == 0)
3125 m_arm_isa = ARMv8;
3126 }
3127 }
3128 return m_arm_isa != 0;
3129}
3130
3131
Greg Clayton64c84432011-01-21 22:02:52 +00003132bool
3133EmulateInstructionARM::ReadInstruction ()
3134{
3135 bool success = false;
3136 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
3137 if (success)
3138 {
3139 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
3140 if (success)
3141 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003142 Context read_inst_context;
3143 read_inst_context.type = eContextReadOpcode;
3144 read_inst_context.SetNoArgs ();
3145
Greg Clayton64c84432011-01-21 22:02:52 +00003146 if (m_inst_cpsr & MASK_CPSR_T)
3147 {
3148 m_inst_mode = eModeThumb;
3149 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
3150
3151 if (success)
3152 {
3153 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
3154 {
3155 m_inst.opcode_type = eOpcode16;
3156 m_inst.opcode.inst16 = thumb_opcode;
3157 }
3158 else
3159 {
3160 m_inst.opcode_type = eOpcode32;
3161 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
3162 }
3163 }
3164 }
3165 else
3166 {
3167 m_inst_mode = eModeARM;
3168 m_inst.opcode_type = eOpcode32;
3169 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
3170 }
3171 }
3172 }
3173 if (!success)
3174 {
3175 m_inst_mode = eModeInvalid;
3176 m_inst_pc = LLDB_INVALID_ADDRESS;
3177 }
3178 return success;
3179}
3180
Johnny Chenee9b1f72011-02-09 01:00:31 +00003181uint32_t
3182EmulateInstructionARM::ArchVersion ()
3183{
3184 return m_arm_isa;
3185}
3186
Greg Clayton64c84432011-01-21 22:02:52 +00003187bool
3188EmulateInstructionARM::ConditionPassed ()
3189{
3190 if (m_inst_cpsr == 0)
3191 return false;
3192
3193 const uint32_t cond = CurrentCond ();
3194
3195 if (cond == UINT32_MAX)
3196 return false;
3197
3198 bool result = false;
3199 switch (UnsignedBits(cond, 3, 1))
3200 {
3201 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
3202 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
3203 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
3204 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
3205 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
3206 case 5:
3207 {
3208 bool n = (m_inst_cpsr & MASK_CPSR_N);
3209 bool v = (m_inst_cpsr & MASK_CPSR_V);
3210 result = n == v;
3211 }
3212 break;
3213 case 6:
3214 {
3215 bool n = (m_inst_cpsr & MASK_CPSR_N);
3216 bool v = (m_inst_cpsr & MASK_CPSR_V);
3217 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3218 }
3219 break;
3220 case 7:
3221 result = true;
3222 break;
3223 }
3224
3225 if (cond & 1)
3226 result = !result;
3227 return result;
3228}
3229
Johnny Chen9ee056b2011-02-08 00:06:35 +00003230uint32_t
3231EmulateInstructionARM::CurrentCond ()
3232{
3233 switch (m_inst_mode)
3234 {
3235 default:
3236 case eModeInvalid:
3237 break;
3238
3239 case eModeARM:
3240 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3241
3242 case eModeThumb:
3243 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3244 // 'cond' field of the encoding.
3245 if (m_inst.opcode_type == eOpcode16 &&
3246 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3247 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3248 {
3249 return Bits32(m_inst.opcode.inst16, 11, 7);
3250 }
3251 else if (m_inst.opcode_type == eOpcode32 &&
3252 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3253 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3254 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3255 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3256 {
3257 return Bits32(m_inst.opcode.inst32, 25, 22);
3258 }
3259
3260 return m_it_session.GetCond();
3261 }
3262 return UINT32_MAX; // Return invalid value
3263}
3264
Johnny Chen9ee056b2011-02-08 00:06:35 +00003265bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003266EmulateInstructionARM::InITBlock()
3267{
3268 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3269}
3270
3271bool
3272EmulateInstructionARM::LastInITBlock()
3273{
3274 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3275}
3276
3277bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003278EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3279{
3280 addr_t target;
3281
Johnny Chenee9b1f72011-02-09 01:00:31 +00003282 // Check the current instruction set.
3283 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003284 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003285 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003286 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003287
Johnny Chen9ee056b2011-02-08 00:06:35 +00003288 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003289 return false;
3290
3291 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003292}
3293
3294// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3295bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003296EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003297{
3298 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003299 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3300 // we want to record it and issue a WriteRegister callback so the clients
3301 // can track the mode changes accordingly.
3302 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003303
3304 if (BitIsSet(addr, 0))
3305 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003306 if (CurrentInstrSet() != eModeThumb)
3307 {
3308 SelectInstrSet(eModeThumb);
3309 cpsr_changed = true;
3310 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003311 target = addr & 0xfffffffe;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003312 context.SetModeAndRegister (eModeThumb, reg);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003313 }
3314 else if (BitIsClear(addr, 1))
3315 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003316 if (CurrentInstrSet() != eModeARM)
3317 {
3318 SelectInstrSet(eModeARM);
3319 cpsr_changed = true;
3320 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003321 target = addr & 0xfffffffc;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003322 context.SetModeAndRegister (eModeARM, reg);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003323 }
3324 else
3325 return false; // address<1:0> == '10' => UNPREDICTABLE
3326
Johnny Chen0f309db2011-02-09 19:11:32 +00003327 if (cpsr_changed)
3328 {
Johnny Chen558133b2011-02-09 23:59:17 +00003329 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003330 return false;
3331 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003332 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003333 return false;
3334
3335 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003336}
Greg Clayton64c84432011-01-21 22:02:52 +00003337
Johnny Chenee9b1f72011-02-09 01:00:31 +00003338// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3339bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003340EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chenee9b1f72011-02-09 01:00:31 +00003341{
3342 if (ArchVersion() >= ARMv5T)
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003343 return BXWritePC(context, addr, reg);
Johnny Chenee9b1f72011-02-09 01:00:31 +00003344 else
3345 return BranchWritePC((const Context)context, addr);
3346}
3347
Johnny Chen26863dc2011-02-09 23:43:29 +00003348// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3349bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003350EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chen26863dc2011-02-09 23:43:29 +00003351{
3352 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003353 return BXWritePC(context, addr, reg);
Johnny Chen26863dc2011-02-09 23:43:29 +00003354 else
3355 return BranchWritePC((const Context)context, addr);
3356}
3357
Johnny Chenee9b1f72011-02-09 01:00:31 +00003358EmulateInstructionARM::Mode
3359EmulateInstructionARM::CurrentInstrSet ()
3360{
3361 return m_inst_mode;
3362}
3363
3364// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003365// ReadInstruction() is performed. This function has a side effect of updating
3366// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003367bool
3368EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3369{
Johnny Chen558133b2011-02-09 23:59:17 +00003370 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003371 switch (arm_or_thumb)
3372 {
3373 default:
3374 return false;
3375 eModeARM:
3376 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003377 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003378 break;
3379 eModeThumb:
3380 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003381 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003382 break;
3383 }
3384 return true;
3385}
3386
Johnny Chenef21b592011-02-10 01:52:38 +00003387// This function returns TRUE if the processor currently provides support for
3388// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3389// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3390bool
3391EmulateInstructionARM::UnalignedSupport()
3392{
3393 return (ArchVersion() >= ARMv7);
3394}
3395
Johnny Chenbf6ad172011-02-11 01:29:53 +00003396// The main addition and subtraction instructions can produce status information
3397// about both unsigned carry and signed overflow conditions. This status
3398// information can be used to synthesize multi-word additions and subtractions.
3399EmulateInstructionARM::AddWithCarryResult
3400EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3401{
3402 uint32_t result;
3403 uint8_t carry_out;
3404 uint8_t overflow;
3405
3406 uint64_t unsigned_sum = x + y + carry_in;
3407 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3408
3409 result = UnsignedBits(unsigned_sum, 31, 0);
3410 carry_out = (result == unsigned_sum ? 0 : 1);
3411 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3412
3413 AddWithCarryResult res = { result, carry_out, overflow };
3414 return res;
3415}
3416
Greg Clayton64c84432011-01-21 22:02:52 +00003417bool
3418EmulateInstructionARM::EvaluateInstruction ()
3419{
Johnny Chenc315f862011-02-05 00:46:10 +00003420 // Advance the ITSTATE bits to their values for the next instruction.
3421 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3422 m_it_session.ITAdvance();
3423
Johnny Chen357c30f2011-02-14 22:04:25 +00003424 // If the flags have changed, flush it out.
3425 if (m_new_inst_cpsr != m_inst_cpsr)
3426 m_inst_cpsr = m_new_inst_cpsr;
3427
Greg Clayton64c84432011-01-21 22:02:52 +00003428 return false;
3429}