blob: 7b58731c8c791e1ce220e826edd297e6f693a2a5 [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.
Johnny Chen668b4512011-02-15 21:08:58 +0000430 if (!LoadWritePC(context, data))
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 {
Johnny Chen668b4512011-02-15 21:08:58 +0000631 if (!ALUWritePC (context, reg_value))
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);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000701 if (BadReg(Rd))
702 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000703 break;
704 default:
705 return false;
706 }
707 uint32_t result = imm32;
708
709 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000710 EmulateInstruction::Context context;
711 context.type = EmulateInstruction::eContextImmediate;
712 context.SetNoArgs ();
713
Johnny Chen357c30f2011-02-14 22:04:25 +0000714 if (Rd == 15)
715 {
Johnny Chen668b4512011-02-15 21:08:58 +0000716 if (!ALUWritePC (context, result))
Johnny Chen357c30f2011-02-14 22:04:25 +0000717 return false;
718 }
719 else
720 {
721 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
722 return false;
723 if (setflags)
724 {
725 m_new_inst_cpsr = m_inst_cpsr;
726 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
727 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
728 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
729 if (m_new_inst_cpsr != m_inst_cpsr)
730 {
731 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
732 return false;
733 }
734 }
735 }
736 }
737 return true;
738}
739
Johnny Chen28070c32011-02-12 01:27:26 +0000740// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
741// the destination register. It can optionally update the condition flags based
742// on the value.
743// MVN (immediate)
744bool
745EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
746{
747#if 0
748 // ARM pseudo code...
749 if (ConditionPassed())
750 {
751 EncodingSpecificOperations();
752 result = NOT(imm32);
753 if d == 15 then // Can only occur for ARM encoding
754 ALUWritePC(result); // setflags is always FALSE here
755 else
756 R[d] = result;
757 if setflags then
758 APSR.N = result<31>;
759 APSR.Z = IsZeroBit(result);
760 APSR.C = carry;
761 // APSR.V unchanged
762 }
763#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000764 bool success = false;
765 const uint32_t opcode = OpcodeAsUnsigned (&success);
766 if (!success)
767 return false;
768
769 if (ConditionPassed())
770 {
771 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000772 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
773 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
774 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000775 bool setflags;
776 switch (encoding) {
777 case eEncodingT1:
778 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000779 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000780 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000781 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
782 break;
783 case eEncodingA1:
784 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000785 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000786 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000787 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
788 break;
789 default:
790 return false;
791 }
792 uint32_t result = ~imm32;
793
794 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000795 EmulateInstruction::Context context;
796 context.type = EmulateInstruction::eContextImmediate;
797 context.SetNoArgs ();
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000798
799 if (Rd == 15)
800 {
Johnny Chen668b4512011-02-15 21:08:58 +0000801 if (!ALUWritePC (context, result))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000802 return false;
803 }
804 else
805 {
806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
807 return false;
808 if (setflags)
809 {
810 m_new_inst_cpsr = m_inst_cpsr;
811 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
812 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
813 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
814 if (m_new_inst_cpsr != m_inst_cpsr)
815 {
816 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
817 return false;
818 }
819 }
820 }
821 }
822 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000823}
824
Johnny Chen788e0552011-01-27 22:52:23 +0000825// PC relative immediate load into register, possibly followed by ADD (SP plus register).
826// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000827bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000828EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000829{
830#if 0
831 // ARM pseudo code...
832 if (ConditionPassed())
833 {
834 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
835 base = Align(PC,4);
836 address = if add then (base + imm32) else (base - imm32);
837 data = MemU[address,4];
838 if t == 15 then
839 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
840 elsif UnalignedSupport() || address<1:0> = ‘00’ then
841 R[t] = data;
842 else // Can only apply before ARMv7
843 if CurrentInstrSet() == InstrSet_ARM then
844 R[t] = ROR(data, 8*UInt(address<1:0>));
845 else
846 R[t] = bits(32) UNKNOWN;
847 }
848#endif
849
850 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000851 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000852 if (!success)
853 return false;
854
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000855 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000856 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000857 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000858 if (!success)
859 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000860
861 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000862 EmulateInstruction::Context context;
863 context.type = EmulateInstruction::eContextRegisterPlusOffset;
864 Register pc_reg;
865 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
866 context.SetRegisterPlusOffset (pc_reg, 0);
867
Johnny Chenc9de9102011-02-11 19:12:30 +0000868 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000869 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000870 bool add; // +imm32 or -imm32?
871 addr_t base; // the base address
872 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000873 uint32_t data; // the literal data value from the PC relative load
874 switch (encoding) {
875 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000876 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000877 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000878 add = true;
879 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000880 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000881 break;
882 case eEncodingT2:
883 Rt = Bits32(opcode, 15, 12);
884 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
885 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000886 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000887 return false;
888 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000889 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000890 break;
891 default:
892 return false;
893 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000894
895 if (add)
896 address = base + imm32;
897 else
898 address = base - imm32;
899 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000900 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000901 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000902
903 if (Rt == 15)
904 {
905 if (Bits32(address, 1, 0) == 0)
906 {
907 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000908 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000909 return false;
910 }
911 else
912 return false;
913 }
914 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
915 {
916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
917 return false;
918 }
919 else // We don't handle ARM for now.
920 return false;
921
922 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000923 return false;
924 }
925 return true;
926}
927
Johnny Chen5b442b72011-01-27 19:34:30 +0000928// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000929// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000930bool
931EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000932{
933#if 0
934 // ARM pseudo code...
935 if (ConditionPassed())
936 {
937 EncodingSpecificOperations();
938 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
939 if d == 15 then // Can only occur for ARM encoding
940 ALUWritePC(result); // setflags is always FALSE here
941 else
942 R[d] = result;
943 if setflags then
944 APSR.N = result<31>;
945 APSR.Z = IsZeroBit(result);
946 APSR.C = carry;
947 APSR.V = overflow;
948 }
949#endif
950
951 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000952 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000953 if (!success)
954 return false;
955
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000957 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000958 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000959 if (!success)
960 return false;
961 uint32_t imm32; // the immediate operand
962 switch (encoding) {
963 case eEncodingT2:
964 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
965 break;
966 default:
967 return false;
968 }
969 addr_t sp_offset = imm32;
970 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
971
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000972 EmulateInstruction::Context context;
973 context.type = EmulateInstruction::eContextAdjustStackPointer;
974 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000975
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000976 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000977 return false;
978 }
979 return true;
980}
981
982// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000983// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000984bool
985EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000986{
987#if 0
988 // ARM pseudo code...
989 if (ConditionPassed())
990 {
991 EncodingSpecificOperations();
992 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
993 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
994 if d == 15 then
995 ALUWritePC(result); // setflags is always FALSE here
996 else
997 R[d] = result;
998 if setflags then
999 APSR.N = result<31>;
1000 APSR.Z = IsZeroBit(result);
1001 APSR.C = carry;
1002 APSR.V = overflow;
1003 }
1004#endif
1005
1006 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001007 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001008 if (!success)
1009 return false;
1010
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001012 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001013 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001014 if (!success)
1015 return false;
1016 uint32_t Rm; // the second operand
1017 switch (encoding) {
1018 case eEncodingT2:
1019 Rm = Bits32(opcode, 6, 3);
1020 break;
1021 default:
1022 return false;
1023 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001024 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001025 if (!success)
1026 return false;
1027
1028 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1029
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001030 EmulateInstruction::Context context;
1031 context.type = EmulateInstruction::eContextAdjustStackPointer;
1032 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001033
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001034 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001035 return false;
1036 }
1037 return true;
1038}
1039
Johnny Chen9b8d7832011-02-02 01:13:56 +00001040// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1041// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1042// from Thumb to ARM.
1043// BLX (immediate)
1044bool
1045EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1046{
1047#if 0
1048 // ARM pseudo code...
1049 if (ConditionPassed())
1050 {
1051 EncodingSpecificOperations();
1052 if CurrentInstrSet() == InstrSet_ARM then
1053 LR = PC - 4;
1054 else
1055 LR = PC<31:1> : '1';
1056 if targetInstrSet == InstrSet_ARM then
1057 targetAddress = Align(PC,4) + imm32;
1058 else
1059 targetAddress = PC + imm32;
1060 SelectInstrSet(targetInstrSet);
1061 BranchWritePC(targetAddress);
1062 }
1063#endif
1064
1065 bool success = false;
1066 const uint32_t opcode = OpcodeAsUnsigned (&success);
1067 if (!success)
1068 return false;
1069
1070 if (ConditionPassed())
1071 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001072 EmulateInstruction::Context context;
1073 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001074 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001075 if (!success)
1076 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001077 addr_t lr; // next instruction address
1078 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001079 int32_t imm32; // PC-relative offset
1080 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001081 case eEncodingT1:
1082 {
1083 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001084 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001085 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001086 uint32_t J1 = Bit32(opcode, 13);
1087 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001088 uint32_t imm11 = Bits32(opcode, 10, 0);
1089 uint32_t I1 = !(J1 ^ S);
1090 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001091 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001092 imm32 = llvm::SignExtend32<25>(imm25);
1093 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001094 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001095 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001096 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001097 break;
1098 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001099 case eEncodingT2:
1100 {
1101 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001102 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001103 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001104 uint32_t J1 = Bit32(opcode, 13);
1105 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001106 uint32_t imm10L = Bits32(opcode, 10, 1);
1107 uint32_t I1 = !(J1 ^ S);
1108 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001109 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001110 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001111 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001112 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001113 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001114 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001115 break;
1116 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001117 case eEncodingA1:
1118 lr = pc + 4; // return address
1119 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001120 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001121 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001122 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001123 case eEncodingA2:
1124 lr = pc + 4; // return address
1125 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1126 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001127 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001128 break;
1129 default:
1130 return false;
1131 }
1132 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1133 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001134 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001135 return false;
1136 }
1137 return true;
1138}
1139
1140// Branch with Link and Exchange (register) calls a subroutine at an address and
1141// instruction set specified by a register.
1142// BLX (register)
1143bool
1144EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1145{
1146#if 0
1147 // ARM pseudo code...
1148 if (ConditionPassed())
1149 {
1150 EncodingSpecificOperations();
1151 target = R[m];
1152 if CurrentInstrSet() == InstrSet_ARM then
1153 next_instr_addr = PC - 4;
1154 LR = next_instr_addr;
1155 else
1156 next_instr_addr = PC - 2;
1157 LR = next_instr_addr<31:1> : ‘1’;
1158 BXWritePC(target);
1159 }
1160#endif
1161
1162 bool success = false;
1163 const uint32_t opcode = OpcodeAsUnsigned (&success);
1164 if (!success)
1165 return false;
1166
1167 if (ConditionPassed())
1168 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001169 EmulateInstruction::Context context;
1170 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001171 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1172 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001173 if (!success)
1174 return false;
1175 uint32_t Rm; // the register with the target address
1176 switch (encoding) {
1177 case eEncodingT1:
1178 lr = (pc + 2) | 1u; // return address
1179 Rm = Bits32(opcode, 6, 3);
1180 // if m == 15 then UNPREDICTABLE;
1181 if (Rm == 15)
1182 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001183 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001184 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001185 break;
1186 case eEncodingA1:
1187 lr = pc + 4; // return address
1188 Rm = Bits32(opcode, 3, 0);
1189 // if m == 15 then UNPREDICTABLE;
1190 if (Rm == 15)
1191 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001192 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001193 default:
1194 return false;
1195 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001196 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1197 if (!success)
1198 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001199 Register dwarf_reg;
1200 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1201 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001202 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1203 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001204 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001205 return false;
1206 }
1207 return true;
1208}
1209
Johnny Chenab3b3512011-02-12 00:10:51 +00001210// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1211// BX
1212bool
1213EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1214{
1215#if 0
1216 // ARM pseudo code...
1217 if (ConditionPassed())
1218 {
1219 EncodingSpecificOperations();
1220 BXWritePC(R[m]);
1221 }
1222#endif
1223
1224 bool success = false;
1225 const uint32_t opcode = OpcodeAsUnsigned (&success);
1226 if (!success)
1227 return false;
1228
1229 if (ConditionPassed())
1230 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001231 EmulateInstruction::Context context;
1232 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001233 uint32_t Rm; // the register with the target address
1234 switch (encoding) {
1235 case eEncodingT1:
1236 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001237 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001238 return false;
1239 break;
1240 case eEncodingA1:
1241 Rm = Bits32(opcode, 3, 0);
1242 break;
1243 default:
1244 return false;
1245 }
1246 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1247 if (!success)
1248 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001249
1250 Register dwarf_reg;
1251 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001252 context.SetRegister (dwarf_reg);
1253 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001254 return false;
1255 }
1256 return true;
1257}
1258
Johnny Chen0d0148e2011-01-28 02:26:08 +00001259// Set r7 to point to some ip offset.
1260// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001261bool
1262EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001263{
1264#if 0
1265 // ARM pseudo code...
1266 if (ConditionPassed())
1267 {
1268 EncodingSpecificOperations();
1269 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1270 if d == 15 then // Can only occur for ARM encoding
1271 ALUWritePC(result); // setflags is always FALSE here
1272 else
1273 R[d] = result;
1274 if setflags then
1275 APSR.N = result<31>;
1276 APSR.Z = IsZeroBit(result);
1277 APSR.C = carry;
1278 APSR.V = overflow;
1279 }
1280#endif
1281
1282 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001283 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001284 if (!success)
1285 return false;
1286
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001287 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001288 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001289 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001290 if (!success)
1291 return false;
1292 uint32_t imm32;
1293 switch (encoding) {
1294 case eEncodingA1:
1295 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1296 break;
1297 default:
1298 return false;
1299 }
1300 addr_t ip_offset = imm32;
1301 addr_t addr = ip - ip_offset; // the adjusted ip value
1302
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001303 EmulateInstruction::Context context;
1304 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1305 Register dwarf_reg;
1306 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1307 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001308
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001309 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001310 return false;
1311 }
1312 return true;
1313}
1314
1315// Set ip to point to some stack offset.
1316// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001317bool
1318EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001319{
1320#if 0
1321 // ARM pseudo code...
1322 if (ConditionPassed())
1323 {
1324 EncodingSpecificOperations();
1325 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1326 if d == 15 then // Can only occur for ARM encoding
1327 ALUWritePC(result); // setflags is always FALSE here
1328 else
1329 R[d] = result;
1330 if setflags then
1331 APSR.N = result<31>;
1332 APSR.Z = IsZeroBit(result);
1333 APSR.C = carry;
1334 APSR.V = overflow;
1335 }
1336#endif
1337
1338 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001339 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001340 if (!success)
1341 return false;
1342
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001343 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001345 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001346 if (!success)
1347 return false;
1348 uint32_t imm32;
1349 switch (encoding) {
1350 case eEncodingA1:
1351 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1352 break;
1353 default:
1354 return false;
1355 }
1356 addr_t sp_offset = imm32;
1357 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1358
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001359 EmulateInstruction::Context context;
1360 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1361 Register dwarf_reg;
1362 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1363 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001364
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001365 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001366 return false;
1367 }
1368 return true;
1369}
1370
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001371// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001372bool
1373EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001374{
1375#if 0
1376 // ARM pseudo code...
1377 if (ConditionPassed())
1378 {
1379 EncodingSpecificOperations();
1380 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1381 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001382 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001383 else
1384 R[d] = result;
1385 if setflags then
1386 APSR.N = result<31>;
1387 APSR.Z = IsZeroBit(result);
1388 APSR.C = carry;
1389 APSR.V = overflow;
1390 }
1391#endif
1392
1393 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001394 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001395 if (!success)
1396 return false;
1397
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001398 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001399 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001400 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001401 if (!success)
1402 return false;
1403 uint32_t imm32;
1404 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001405 case eEncodingT1:
1406 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001407 case eEncodingT2:
1408 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1409 break;
1410 case eEncodingT3:
1411 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1412 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001413 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001414 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001415 break;
1416 default:
1417 return false;
1418 }
1419 addr_t sp_offset = imm32;
1420 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1421
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001422 EmulateInstruction::Context context;
1423 context.type = EmulateInstruction::eContextAdjustStackPointer;
1424 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001425
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001426 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001427 return false;
1428 }
1429 return true;
1430}
1431
Johnny Chen08c25e82011-01-31 18:02:28 +00001432// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001433bool
1434EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001435{
1436#if 0
1437 // ARM pseudo code...
1438 if (ConditionPassed())
1439 {
1440 EncodingSpecificOperations();
1441 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1442 address = if index then offset_addr else R[n];
1443 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1444 if wback then R[n] = offset_addr;
1445 }
1446#endif
1447
1448 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001449 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001450 if (!success)
1451 return false;
1452
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001453 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001454 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001455 const uint32_t addr_byte_size = GetAddressByteSize();
1456 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001457 if (!success)
1458 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001459 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001460 uint32_t imm12;
1461 switch (encoding) {
1462 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001463 Rt = Bits32(opcode, 15, 12);
1464 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001465 break;
1466 default:
1467 return false;
1468 }
1469 addr_t sp_offset = imm12;
1470 addr_t addr = sp - sp_offset;
1471
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001472 EmulateInstruction::Context context;
1473 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1474 Register dwarf_reg;
1475 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001476 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001477 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001478 dwarf_reg.num = dwarf_r0 + Rt;
1479 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1480 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001481 if (!success)
1482 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001483 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001484 return false;
1485 }
1486 else
1487 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001488 dwarf_reg.num = dwarf_pc;
1489 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001490 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001491 if (!success)
1492 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001493 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001494 return false;
1495 }
1496
1497 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001498 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001499
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001500 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001501 return false;
1502 }
1503 return true;
1504}
1505
Johnny Chen08c25e82011-01-31 18:02:28 +00001506// Vector Push stores multiple extension registers to the stack.
1507// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001508bool
1509EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001510{
1511#if 0
1512 // ARM pseudo code...
1513 if (ConditionPassed())
1514 {
1515 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1516 address = SP - imm32;
1517 SP = SP - imm32;
1518 if single_regs then
1519 for r = 0 to regs-1
1520 MemA[address,4] = S[d+r]; address = address+4;
1521 else
1522 for r = 0 to regs-1
1523 // Store as two word-aligned words in the correct order for current endianness.
1524 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1525 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1526 address = address+8;
1527 }
1528#endif
1529
1530 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001531 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001532 if (!success)
1533 return false;
1534
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001535 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001536 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001537 const uint32_t addr_byte_size = GetAddressByteSize();
1538 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001539 if (!success)
1540 return false;
1541 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001542 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001543 uint32_t imm32; // stack offset
1544 uint32_t regs; // number of registers
1545 switch (encoding) {
1546 case eEncodingT1:
1547 case eEncodingA1:
1548 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001549 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001550 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1551 // If UInt(imm8) is odd, see "FSTMX".
1552 regs = Bits32(opcode, 7, 0) / 2;
1553 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1554 if (regs == 0 || regs > 16 || (d + regs) > 32)
1555 return false;
1556 break;
1557 case eEncodingT2:
1558 case eEncodingA2:
1559 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001560 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001561 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1562 regs = Bits32(opcode, 7, 0);
1563 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1564 if (regs == 0 || regs > 16 || (d + regs) > 32)
1565 return false;
1566 break;
1567 default:
1568 return false;
1569 }
1570 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1571 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1572 addr_t sp_offset = imm32;
1573 addr_t addr = sp - sp_offset;
1574 uint32_t i;
1575
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001576 EmulateInstruction::Context context;
1577 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1578 Register dwarf_reg;
1579 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001580 for (i=d; i<regs; ++i)
1581 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001582 dwarf_reg.num = start_reg + i;
1583 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001584 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001585 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001586 if (!success)
1587 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001589 return false;
1590 addr += reg_byte_size;
1591 }
1592
1593 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001594 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001595
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001596 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001597 return false;
1598 }
1599 return true;
1600}
1601
Johnny Chen587a0a42011-02-01 18:35:28 +00001602// Vector Pop loads multiple extension registers from the stack.
1603// It also updates SP to point just above the loaded data.
1604bool
1605EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1606{
1607#if 0
1608 // ARM pseudo code...
1609 if (ConditionPassed())
1610 {
1611 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1612 address = SP;
1613 SP = SP + imm32;
1614 if single_regs then
1615 for r = 0 to regs-1
1616 S[d+r] = MemA[address,4]; address = address+4;
1617 else
1618 for r = 0 to regs-1
1619 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1620 // Combine the word-aligned words in the correct order for current endianness.
1621 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1622 }
1623#endif
1624
1625 bool success = false;
1626 const uint32_t opcode = OpcodeAsUnsigned (&success);
1627 if (!success)
1628 return false;
1629
1630 if (ConditionPassed())
1631 {
1632 const uint32_t addr_byte_size = GetAddressByteSize();
1633 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1634 if (!success)
1635 return false;
1636 bool single_regs;
1637 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1638 uint32_t imm32; // stack offset
1639 uint32_t regs; // number of registers
1640 switch (encoding) {
1641 case eEncodingT1:
1642 case eEncodingA1:
1643 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001644 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001645 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1646 // If UInt(imm8) is odd, see "FLDMX".
1647 regs = Bits32(opcode, 7, 0) / 2;
1648 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1649 if (regs == 0 || regs > 16 || (d + regs) > 32)
1650 return false;
1651 break;
1652 case eEncodingT2:
1653 case eEncodingA2:
1654 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001655 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001656 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1657 regs = Bits32(opcode, 7, 0);
1658 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1659 if (regs == 0 || regs > 16 || (d + regs) > 32)
1660 return false;
1661 break;
1662 default:
1663 return false;
1664 }
1665 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1666 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1667 addr_t sp_offset = imm32;
1668 addr_t addr = sp;
1669 uint32_t i;
1670 uint64_t data; // uint64_t to accomodate 64-bit registers.
1671
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001672 EmulateInstruction::Context context;
1673 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1674 Register dwarf_reg;
1675 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001676 for (i=d; i<regs; ++i)
1677 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001678 dwarf_reg.num = start_reg + i;
1679 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chen587a0a42011-02-01 18:35:28 +00001680 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1681 if (!success)
1682 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001683 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001684 return false;
1685 addr += reg_byte_size;
1686 }
1687
1688 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001689 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001690
1691 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1692 return false;
1693 }
1694 return true;
1695}
1696
Johnny Chenb77be412011-02-04 00:40:18 +00001697// SVC (previously SWI)
1698bool
1699EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1700{
1701#if 0
1702 // ARM pseudo code...
1703 if (ConditionPassed())
1704 {
1705 EncodingSpecificOperations();
1706 CallSupervisor();
1707 }
1708#endif
1709
1710 bool success = false;
1711 const uint32_t opcode = OpcodeAsUnsigned (&success);
1712 if (!success)
1713 return false;
1714
1715 if (ConditionPassed())
1716 {
1717 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1718 addr_t lr; // next instruction address
1719 if (!success)
1720 return false;
1721 uint32_t imm32; // the immediate constant
1722 uint32_t mode; // ARM or Thumb mode
1723 switch (encoding) {
1724 case eEncodingT1:
1725 lr = (pc + 2) | 1u; // return address
1726 imm32 = Bits32(opcode, 7, 0);
1727 mode = eModeThumb;
1728 break;
1729 case eEncodingA1:
1730 lr = pc + 4; // return address
1731 imm32 = Bits32(opcode, 23, 0);
1732 mode = eModeARM;
1733 break;
1734 default:
1735 return false;
1736 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001737
1738 EmulateInstruction::Context context;
1739 context.type = EmulateInstruction::eContextSupervisorCall;
1740 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001741 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1742 return false;
1743 }
1744 return true;
1745}
1746
Johnny Chenc315f862011-02-05 00:46:10 +00001747// If Then makes up to four following instructions (the IT block) conditional.
1748bool
1749EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1750{
1751#if 0
1752 // ARM pseudo code...
1753 EncodingSpecificOperations();
1754 ITSTATE.IT<7:0> = firstcond:mask;
1755#endif
1756
1757 bool success = false;
1758 const uint32_t opcode = OpcodeAsUnsigned (&success);
1759 if (!success)
1760 return false;
1761
1762 m_it_session.InitIT(Bits32(opcode, 7, 0));
1763 return true;
1764}
1765
Johnny Chen3b620b32011-02-07 20:11:47 +00001766// Branch causes a branch to a target address.
1767bool
1768EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1769{
1770#if 0
1771 // ARM pseudo code...
1772 if (ConditionPassed())
1773 {
1774 EncodingSpecificOperations();
1775 BranchWritePC(PC + imm32);
1776 }
1777#endif
1778
1779 bool success = false;
1780 const uint32_t opcode = OpcodeAsUnsigned (&success);
1781 if (!success)
1782 return false;
1783
Johnny Chen9ee056b2011-02-08 00:06:35 +00001784 if (ConditionPassed())
1785 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001786 EmulateInstruction::Context context;
1787 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001788 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001789 if (!success)
1790 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001791 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001792 int32_t imm32; // PC-relative offset
1793 switch (encoding) {
1794 case eEncodingT1:
1795 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1796 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1797 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001798 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001799 break;
1800 case eEncodingT2:
1801 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1802 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001803 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001804 break;
1805 case eEncodingT3:
1806 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1807 {
Johnny Chenbd599902011-02-10 21:39:01 +00001808 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001809 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001810 uint32_t J1 = Bit32(opcode, 13);
1811 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001812 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001813 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001814 imm32 = llvm::SignExtend32<21>(imm21);
1815 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001816 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001817 break;
1818 }
1819 case eEncodingT4:
1820 {
Johnny Chenbd599902011-02-10 21:39:01 +00001821 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001822 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001823 uint32_t J1 = Bit32(opcode, 13);
1824 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001825 uint32_t imm11 = Bits32(opcode, 10, 0);
1826 uint32_t I1 = !(J1 ^ S);
1827 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001828 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001829 imm32 = llvm::SignExtend32<25>(imm25);
1830 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001831 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001832 break;
1833 }
1834 case eEncodingA1:
1835 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1836 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001837 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001838 break;
1839 default:
1840 return false;
1841 }
1842 if (!BranchWritePC(context, target))
1843 return false;
1844 }
1845 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001846}
1847
Johnny Chen53ebab72011-02-08 23:21:57 +00001848// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1849// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1850// CBNZ, CBZ
1851bool
1852EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1853{
1854#if 0
1855 // ARM pseudo code...
1856 EncodingSpecificOperations();
1857 if nonzero ^ IsZero(R[n]) then
1858 BranchWritePC(PC + imm32);
1859#endif
1860
1861 bool success = false;
1862 const uint32_t opcode = OpcodeAsUnsigned (&success);
1863 if (!success)
1864 return false;
1865
1866 // Read the register value from the operand register Rn.
1867 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1868 if (!success)
1869 return false;
1870
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001871 EmulateInstruction::Context context;
1872 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001873 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1874 if (!success)
1875 return false;
1876
1877 addr_t target; // target address
1878 uint32_t imm32; // PC-relative offset to branch forward
1879 bool nonzero;
1880 switch (encoding) {
1881 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001882 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001883 nonzero = BitIsSet(opcode, 11);
1884 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001885 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001886 break;
1887 default:
1888 return false;
1889 }
1890 if (nonzero ^ (reg_val == 0))
1891 if (!BranchWritePC(context, target))
1892 return false;
1893
1894 return true;
1895}
1896
Johnny Chen26863dc2011-02-09 23:43:29 +00001897// ADD <Rdn>, <Rm>
1898// where <Rdn> the destination register is also the first operand register
1899// and <Rm> is the second operand register.
1900bool
1901EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1902{
1903#if 0
1904 // ARM pseudo code...
1905 if ConditionPassed() then
1906 EncodingSpecificOperations();
1907 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1908 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1909 if d == 15 then
1910 ALUWritePC(result); // setflags is always FALSE here
1911 else
1912 R[d] = result;
1913 if setflags then
1914 APSR.N = result<31>;
1915 APSR.Z = IsZeroBit(result);
1916 APSR.C = carry;
1917 APSR.V = overflow;
1918#endif
1919
1920 bool success = false;
1921 const uint32_t opcode = OpcodeAsUnsigned (&success);
1922 if (!success)
1923 return false;
1924
1925 if (ConditionPassed())
1926 {
1927 uint32_t Rd, Rn, Rm;
1928 //bool setflags = false;
1929 switch (encoding)
1930 {
1931 case eEncodingT2:
1932 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001933 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001934 Rm = Bits32(opcode, 6, 3);
1935 if (Rn == 15 && Rm == 15)
1936 return false;
1937 break;
1938 default:
1939 return false;
1940 }
1941
1942 int32_t result, val1, val2;
1943 // Read the first operand.
1944 if (Rn == 15)
1945 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1946 else
1947 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1948 if (!success)
1949 return false;
1950
1951 // Read the second operand.
1952 if (Rm == 15)
1953 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1954 else
1955 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1956 if (!success)
1957 return false;
1958
1959 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001960
1961 EmulateInstruction::Context context;
1962 context.type = EmulateInstruction::eContextImmediate;
1963 context.SetNoArgs ();
Johnny Chen26863dc2011-02-09 23:43:29 +00001964
1965 if (Rd == 15)
1966 {
Johnny Chen668b4512011-02-15 21:08:58 +00001967 if (!ALUWritePC (context, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001968 return false;
1969 }
1970 else
1971 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001972 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001973 return false;
1974 }
1975 }
1976 return true;
1977}
1978
Johnny Chene4a4d302011-02-11 21:53:58 +00001979// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001980bool
1981EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1982{
1983#if 0
1984 // ARM pseudo code...
1985 if ConditionPassed() then
1986 EncodingSpecificOperations();
1987 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1988 APSR.N = result<31>;
1989 APSR.Z = IsZeroBit(result);
1990 APSR.C = carry;
1991 APSR.V = overflow;
1992#endif
1993
1994 bool success = false;
1995 const uint32_t opcode = OpcodeAsUnsigned (&success);
1996 if (!success)
1997 return false;
1998
1999 uint32_t Rn; // the first operand
2000 uint32_t imm32; // the immediate value to be compared with
2001 switch (encoding) {
2002 case eEncodingT1:
2003 Rn = Bits32(opcode, 10, 8);
2004 imm32 = Bits32(opcode, 7, 0);
2005 break;
2006 default:
2007 return false;
2008 }
2009 // Read the register value from the operand register Rn.
2010 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2011 if (!success)
2012 return false;
2013
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002014 EmulateInstruction::Context context;
2015 context.type = EmulateInstruction::eContextImmediate;
2016 context.SetNoArgs ();
2017
Johnny Chend4dc4442011-02-11 02:02:56 +00002018 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2019 m_new_inst_cpsr = m_inst_cpsr;
2020 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2021 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2022 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2023 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2024 if (m_new_inst_cpsr != m_inst_cpsr)
2025 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002026 EmulateInstruction::Context context;
2027 context.type = EmulateInstruction::eContextImmediate;
2028 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002029 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2030 return false;
2031 }
2032 return true;
2033}
2034
Johnny Chene4a4d302011-02-11 21:53:58 +00002035// CMP (register)
2036bool
2037EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2038{
2039#if 0
2040 // ARM pseudo code...
2041 if ConditionPassed() then
2042 EncodingSpecificOperations();
2043 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2044 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2045 APSR.N = result<31>;
2046 APSR.Z = IsZeroBit(result);
2047 APSR.C = carry;
2048 APSR.V = overflow;
2049#endif
2050
2051 bool success = false;
2052 const uint32_t opcode = OpcodeAsUnsigned (&success);
2053 if (!success)
2054 return false;
2055
2056 uint32_t Rn; // the first operand
2057 uint32_t Rm; // the second operand
2058 switch (encoding) {
2059 case eEncodingT1:
2060 Rn = Bits32(opcode, 2, 0);
2061 Rm = Bits32(opcode, 5, 3);
2062 break;
2063 case eEncodingT2:
2064 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2065 Rm = Bits32(opcode, 6, 3);
2066 if (Rn < 8 && Rm < 8)
2067 return false;
2068 if (Rn == 15 || Rm == 15)
2069 return false;
2070 break;
2071 default:
2072 return false;
2073 }
2074 // Read the register value from register Rn.
2075 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2076 if (!success)
2077 return false;
2078 // Read the register value from register Rm.
2079 // The register value is not being shifted since we don't handle ARM for now.
2080 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2081 if (!success)
2082 return false;
2083
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002084 EmulateInstruction::Context context;
2085 context.type = EmulateInstruction::eContextImmediate;
2086 context.SetNoArgs();
2087
Johnny Chene4a4d302011-02-11 21:53:58 +00002088 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2089 m_new_inst_cpsr = m_inst_cpsr;
2090 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2091 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2092 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2093 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2094 if (m_new_inst_cpsr != m_inst_cpsr)
2095 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002096 EmulateInstruction::Context context;
2097 context.type = EmulateInstruction::eContextImmediate;
2098 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002099 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2100 return false;
2101 }
2102 return true;
2103}
2104
Johnny Chen82f16aa2011-02-15 20:10:55 +00002105// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2106// shifting in copies of its sign bit, and writes the result to the destination register. It can
2107// optionally update the condition flags based on the result.
2108bool
2109EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2110{
2111#if 0
2112 // ARM pseudo code...
2113 if ConditionPassed() then
2114 EncodingSpecificOperations();
2115 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2116 if d == 15 then // Can only occur for ARM encoding
2117 ALUWritePC(result); // setflags is always FALSE here
2118 else
2119 R[d] = result;
2120 if setflags then
2121 APSR.N = result<31>;
2122 APSR.Z = IsZeroBit(result);
2123 APSR.C = carry;
2124 // APSR.V unchanged
2125#endif
2126
2127 bool success = false;
2128 const uint32_t opcode = OpcodeAsUnsigned (&success);
2129 if (!success)
2130 return false;
2131
2132 if (ConditionPassed())
2133 {
2134 uint32_t Rd; // the destination register
2135 uint32_t Rm; // the first operand register
2136 uint32_t imm5; // encoding for the shift amount
2137 uint32_t carry; // the carry bit after the shift operation
2138 bool setflags;
2139 switch (encoding) {
2140 case eEncodingT1:
2141 Rd = Bits32(opcode, 2, 0);
2142 Rm = Bits32(opcode, 5, 3);
2143 setflags = !InITBlock();
2144 imm5 = Bits32(opcode, 10, 6);
2145 break;
2146 case eEncodingT2:
2147 Rd = Bits32(opcode, 11, 8);
2148 Rm = Bits32(opcode, 3, 0);
2149 setflags = BitIsSet(opcode, 20);
2150 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2151 if (BadReg(Rd) || BadReg(Rm))
2152 return false;
2153 break;
2154 case eEncodingA1:
2155 Rd = Bits32(opcode, 15, 12);
2156 Rm = Bits32(opcode, 3, 0);
2157 setflags = BitIsSet(opcode, 20);
2158 imm5 = Bits32(opcode, 11, 7);
2159 break;
2160 default:
2161 return false;
2162 }
2163
2164 // Get the first operand.
2165 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2166 if (!success)
2167 return false;
2168
2169 // Decode the shift amount.
2170 uint32_t amt = DecodeImmShift(SRType_ASR, imm5);
2171
2172 uint32_t result = Shift_C(value, SRType_ASR, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
2173
2174 // The context specifies that an immediate is to be moved into Rd.
2175 EmulateInstruction::Context context;
2176 context.type = EmulateInstruction::eContextImmediate;
2177 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002178
2179 if (Rd == 15)
2180 {
Johnny Chen668b4512011-02-15 21:08:58 +00002181 if (!ALUWritePC (context, result))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002182 return false;
2183 }
2184 else
2185 {
2186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
2187 return false;
2188 if (setflags)
2189 {
2190 m_new_inst_cpsr = m_inst_cpsr;
2191 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
2192 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
2193 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
2194 if (m_new_inst_cpsr != m_inst_cpsr)
2195 {
2196 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2197 return false;
2198 }
2199 }
2200 }
2201 }
2202 return true;
2203}
2204
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002205// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002206// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002207// can be written back to the base register.
2208bool
2209EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2210{
2211#if 0
2212 // ARM pseudo code...
2213 if ConditionPassed()
2214 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2215 address = R[n];
2216
2217 for i = 0 to 14
2218 if registers<i> == '1' then
2219 R[i] = MemA[address, 4]; address = address + 4;
2220 if registers<15> == '1' then
2221 LoadWritePC (MemA[address, 4]);
2222
2223 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2224 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2225
2226#endif
2227
2228 bool success = false;
2229 const uint32_t opcode = OpcodeAsUnsigned (&success);
2230 if (!success)
2231 return false;
2232
2233 if (ConditionPassed())
2234 {
2235 uint32_t n;
2236 uint32_t registers = 0;
2237 bool wback;
2238 const uint32_t addr_byte_size = GetAddressByteSize();
2239 switch (encoding)
2240 {
2241 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002242 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002243 n = Bits32 (opcode, 10, 8);
2244 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002245 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002246 wback = BitIsClear (registers, n);
2247 // if BitCount(registers) < 1 then UNPREDICTABLE;
2248 if (BitCount(registers) < 1)
2249 return false;
2250 break;
2251 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002252 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2253 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002254 n = Bits32 (opcode, 19, 16);
2255 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002256 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002257 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002258
2259 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002260 if ((n == 15)
2261 || (BitCount (registers) < 2)
2262 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2263 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002264
2265 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002266 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002267 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002268
2269 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002270 if (wback
2271 && BitIsSet (registers, n))
2272 return false;
2273 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002274
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002275 case eEncodingA1:
2276 n = Bits32 (opcode, 19, 16);
2277 registers = Bits32 (opcode, 15, 0);
2278 wback = BitIsSet (opcode, 21);
2279 if ((n == 15)
2280 || (BitCount (registers) < 1))
2281 return false;
2282 break;
2283 default:
2284 return false;
2285 }
2286
2287 int32_t offset = 0;
2288 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2289 if (!success)
2290 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002291
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002292 EmulateInstruction::Context context;
2293 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2294 Register dwarf_reg;
2295 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2296 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002297
2298 for (int i = 0; i < 14; ++i)
2299 {
2300 if (BitIsSet (registers, i))
2301 {
Caroline Tice85aab332011-02-08 23:56:10 +00002302 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002303 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002304 if (wback && (n == 13)) // Pop Instruction
2305 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2306
2307 // R[i] = MemA [address, 4]; address = address + 4;
2308 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2309 if (!success)
2310 return false;
2311
2312 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2313 return false;
2314
2315 offset += addr_byte_size;
2316 }
2317 }
2318
2319 if (BitIsSet (registers, 15))
2320 {
2321 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002322 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002323 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002324 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2325 if (!success)
2326 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002327 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002328 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002329 return false;
2330 }
2331
2332 if (wback && BitIsClear (registers, n))
2333 {
Caroline Ticefa172202011-02-11 22:49:54 +00002334 // R[n] = R[n] + 4 * BitCount (registers)
2335 int32_t offset = addr_byte_size * BitCount (registers);
2336 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002337 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002338
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002339 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2340 return false;
2341 }
2342 if (wback && BitIsSet (registers, n))
2343 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002344 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002345 }
2346 return true;
2347}
Caroline Tice713c2662011-02-11 17:59:55 +00002348
2349// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2350// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2351// can optionally be written back tot he base registers.
2352bool
2353EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2354{
2355#if 0
2356 // ARM pseudo code...
2357 if ConditionPassed() then
2358 EncodingSpecificOperations();
2359 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002360
Caroline Tice713c2662011-02-11 17:59:55 +00002361 for i = 0 to 14
2362 if registers<i> == ’1’ then
2363 R[i] = MemA[address,4]; address = address + 4;
2364
2365 if registers<15> == ’1’ then
2366 LoadWritePC(MemA[address,4]);
2367
2368 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2369 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2370#endif
2371
2372 bool success = false;
2373 const uint32_t opcode = OpcodeAsUnsigned (&success);
2374 if (!success)
2375 return false;
2376
2377 if (ConditionPassed())
2378 {
2379 uint32_t n;
2380 uint32_t registers = 0;
2381 bool wback;
2382 const uint32_t addr_byte_size = GetAddressByteSize();
2383
2384 // EncodingSpecificOperations();
2385 switch (encoding)
2386 {
2387 case eEncodingA1:
2388 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2389 n = Bits32 (opcode, 19, 16);
2390 registers = Bits32 (opcode, 15, 0);
2391 wback = BitIsSet (opcode, 21);
2392
2393 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2394 if ((n == 15) || (BitCount (registers) < 1))
2395 return false;
2396
2397 break;
2398
2399 default:
2400 return false;
2401 }
2402 // address = R[n] - 4*BitCount(registers) + 4;
2403
2404 int32_t offset = 0;
2405 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2406
2407 if (!success)
2408 return false;
2409
2410 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2411
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002412 EmulateInstruction::Context context;
2413 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2414 Register dwarf_reg;
2415 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2416 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002417
2418 // for i = 0 to 14
2419 for (int i = 0; i < 14; ++i)
2420 {
2421 // if registers<i> == ’1’ then
2422 if (BitIsSet (registers, i))
2423 {
2424 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002425 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002426 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2427 if (!success)
2428 return false;
2429 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2430 return false;
2431 offset += addr_byte_size;
2432 }
2433 }
2434
2435 // if registers<15> == ’1’ then
2436 // LoadWritePC(MemA[address,4]);
2437 if (BitIsSet (registers, 15))
2438 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002439 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002440 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2441 if (!success)
2442 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002443 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002444 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002445 return false;
2446 }
2447
2448 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2449 if (wback && BitIsClear (registers, n))
2450 {
Caroline Tice713c2662011-02-11 17:59:55 +00002451 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2452 if (!success)
2453 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002454
2455 offset = (addr_byte_size * BitCount (registers)) * -1;
2456 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002457 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002458 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002459 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2460 return false;
2461 }
2462
2463 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2464 if (wback && BitIsSet (registers, n))
2465 return WriteBits32Unknown (n);
2466 }
2467 return true;
2468}
2469
2470// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2471// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2472// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002473bool
2474EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2475{
2476#if 0
2477 // ARM pseudo code...
2478 if ConditionPassed() then
2479 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2480 address = R[n] - 4*BitCount(registers);
2481
2482 for i = 0 to 14
2483 if registers<i> == ’1’ then
2484 R[i] = MemA[address,4]; address = address + 4;
2485 if registers<15> == ’1’ then
2486 LoadWritePC(MemA[address,4]);
2487
2488 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2489 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2490#endif
2491
2492 bool success = false;
2493 const uint32_t opcode = OpcodeAsUnsigned (&success);
2494 if (!success)
2495 return false;
2496
2497 if (ConditionPassed())
2498 {
2499 uint32_t n;
2500 uint32_t registers = 0;
2501 bool wback;
2502 const uint32_t addr_byte_size = GetAddressByteSize();
2503 switch (encoding)
2504 {
2505 case eEncodingT1:
2506 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2507 n = Bits32 (opcode, 19, 16);
2508 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002509 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002510 wback = BitIsSet (opcode, 21);
2511
2512 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2513 if ((n == 15)
2514 || (BitCount (registers) < 2)
2515 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2516 return false;
2517
2518 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002519 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002520 return false;
2521
2522 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2523 if (wback && BitIsSet (registers, n))
2524 return false;
2525
2526 break;
2527
2528 case eEncodingA1:
2529 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2530 n = Bits32 (opcode, 19, 16);
2531 registers = Bits32 (opcode, 15, 0);
2532 wback = BitIsSet (opcode, 21);
2533
2534 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2535 if ((n == 15) || (BitCount (registers) < 1))
2536 return false;
2537
2538 break;
2539
2540 default:
2541 return false;
2542 }
2543
Caroline Tice713c2662011-02-11 17:59:55 +00002544 // address = R[n] - 4*BitCount(registers);
2545
Caroline Tice0b29e242011-02-08 23:16:02 +00002546 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002547 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2548
2549 if (!success)
2550 return false;
2551
2552 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002553 EmulateInstruction::Context context;
2554 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2555 Register dwarf_reg;
2556 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2557 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002558
2559 for (int i = 0; i < 14; ++i)
2560 {
2561 if (BitIsSet (registers, i))
2562 {
2563 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002564 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002565 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2566 if (!success)
2567 return false;
2568
2569 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2570 return false;
2571
2572 offset += addr_byte_size;
2573 }
2574 }
2575
2576 // if registers<15> == ’1’ then
2577 // LoadWritePC(MemA[address,4]);
2578 if (BitIsSet (registers, 15))
2579 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002580 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002581 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2582 if (!success)
2583 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002584 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002585 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002586 return false;
2587 }
2588
2589 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2590 if (wback && BitIsClear (registers, n))
2591 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002592 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2593 if (!success)
2594 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002595
2596 offset = (addr_byte_size * BitCount (registers)) * -1;
2597 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002598 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002599 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002600 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2601 return false;
2602 }
2603
2604 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2605 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002606 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002607 }
2608 return true;
2609}
Caroline Tice85aab332011-02-08 23:56:10 +00002610
Caroline Tice713c2662011-02-11 17:59:55 +00002611// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2612// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2613// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002614bool
2615EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2616{
2617#if 0
2618 if ConditionPassed() then
2619 EncodingSpecificOperations();
2620 address = R[n] + 4;
2621
2622 for i = 0 to 14
2623 if registers<i> == ’1’ then
2624 R[i] = MemA[address,4]; address = address + 4;
2625 if registers<15> == ’1’ then
2626 LoadWritePC(MemA[address,4]);
2627
2628 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2629 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2630#endif
2631
2632 bool success = false;
2633 const uint32_t opcode = OpcodeAsUnsigned (&success);
2634 if (!success)
2635 return false;
2636
2637 if (ConditionPassed())
2638 {
2639 uint32_t n;
2640 uint32_t registers = 0;
2641 bool wback;
2642 const uint32_t addr_byte_size = GetAddressByteSize();
2643 switch (encoding)
2644 {
2645 case eEncodingA1:
2646 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2647 n = Bits32 (opcode, 19, 16);
2648 registers = Bits32 (opcode, 15, 0);
2649 wback = BitIsSet (opcode, 21);
2650
2651 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2652 if ((n == 15) || (BitCount (registers) < 1))
2653 return false;
2654
2655 break;
2656 default:
2657 return false;
2658 }
2659 // address = R[n] + 4;
2660
2661 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002662 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2663
2664 if (!success)
2665 return false;
2666
2667 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002668
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002669 EmulateInstruction::Context context;
2670 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2671 Register dwarf_reg;
2672 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2673 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002674
2675 for (int i = 0; i < 14; ++i)
2676 {
2677 if (BitIsSet (registers, i))
2678 {
2679 // R[i] = MemA[address,4]; address = address + 4;
2680
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002681 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002682 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2683 if (!success)
2684 return false;
2685
2686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2687 return false;
2688
2689 offset += addr_byte_size;
2690 }
2691 }
2692
2693 // if registers<15> == ’1’ then
2694 // LoadWritePC(MemA[address,4]);
2695 if (BitIsSet (registers, 15))
2696 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002697 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002698 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2699 if (!success)
2700 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002701 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002702 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002703 return false;
2704 }
2705
2706 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2707 if (wback && BitIsClear (registers, n))
2708 {
Caroline Tice85aab332011-02-08 23:56:10 +00002709 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2710 if (!success)
2711 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002712
2713 offset = addr_byte_size * BitCount (registers);
2714 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002715 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002716 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002717 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2718 return false;
2719 }
2720
2721 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2722 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002723 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002724 }
2725 return true;
2726}
Caroline Tice0b29e242011-02-08 23:16:02 +00002727
Johnny Chenef21b592011-02-10 01:52:38 +00002728// Load Register (immediate) calculates an address from a base register value and
2729// an immediate offset, loads a word from memory, and writes to a register.
2730// LDR (immediate, Thumb)
2731bool
2732EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2733{
2734#if 0
2735 // ARM pseudo code...
2736 if (ConditionPassed())
2737 {
2738 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2739 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2740 address = if index then offset_addr else R[n];
2741 data = MemU[address,4];
2742 if wback then R[n] = offset_addr;
2743 if t == 15 then
2744 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2745 elsif UnalignedSupport() || address<1:0> = '00' then
2746 R[t] = data;
2747 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2748 }
2749#endif
2750
2751 bool success = false;
2752 const uint32_t opcode = OpcodeAsUnsigned (&success);
2753 if (!success)
2754 return false;
2755
2756 if (ConditionPassed())
2757 {
2758 uint32_t Rt; // the destination register
2759 uint32_t Rn; // the base register
2760 uint32_t imm32; // the immediate offset used to form the address
2761 addr_t offset_addr; // the offset address
2762 addr_t address; // the calculated address
2763 uint32_t data; // the literal data value from memory load
2764 bool add, index, wback;
2765 switch (encoding) {
2766 case eEncodingT1:
2767 Rt = Bits32(opcode, 5, 3);
2768 Rn = Bits32(opcode, 2, 0);
2769 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2770 // index = TRUE; add = TRUE; wback = FALSE
2771 add = true;
2772 index = true;
2773 wback = false;
2774 break;
2775 default:
2776 return false;
2777 }
2778 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2779 if (!success)
2780 return false;
2781 if (add)
2782 offset_addr = base + imm32;
2783 else
2784 offset_addr = base - imm32;
2785
2786 address = (index ? offset_addr : base);
2787
2788 if (wback)
2789 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002790 EmulateInstruction::Context ctx;
2791 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
2792 Register dwarf_reg;
2793 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2794 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
2795
Johnny Chenef21b592011-02-10 01:52:38 +00002796 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2797 return false;
2798 }
2799
2800 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002801 EmulateInstruction::Context context;
2802 context.type = EmulateInstruction::eContextImmediate;
2803 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00002804
2805 // Read memory from the address.
2806 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2807 if (!success)
2808 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00002809
2810 if (Rt == 15)
2811 {
2812 if (Bits32(address, 1, 0) == 0)
2813 {
Johnny Chen668b4512011-02-15 21:08:58 +00002814 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00002815 return false;
2816 }
2817 else
2818 return false;
2819 }
2820 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2821 {
2822 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2823 return false;
2824 }
2825 else
2826 return false;
2827 }
2828 return true;
2829}
2830
Caroline Ticeaf556562011-02-15 18:42:15 +00002831// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
2832// from a base register. The consecutive memory locations start at this address, and teh address just above the last
2833// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00002834bool
2835EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2836{
2837#if 0
2838 if ConditionPassed() then
2839 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2840 address = R[n];
2841
2842 for i = 0 to 14
2843 if registers<i> == ’1’ then
2844 if i == n && wback && i != LowestSetBit(registers) then
2845 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2846 else
2847 MemA[address,4] = R[i];
2848 address = address + 4;
2849
2850 if registers<15> == ’1’ then // Only possible for encoding A1
2851 MemA[address,4] = PCStoreValue();
2852 if wback then R[n] = R[n] + 4*BitCount(registers);
2853#endif
2854
2855 bool success = false;
2856 const uint32_t opcode = OpcodeAsUnsigned (&success);
2857 if (!success)
2858 return false;
2859
2860 if (ConditionPassed ())
2861 {
2862 uint32_t n;
2863 uint32_t registers = 0;
2864 bool wback;
2865 const uint32_t addr_byte_size = GetAddressByteSize();
2866
2867 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2868 switch (encoding)
2869 {
2870 case eEncodingT1:
2871 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2872 n = Bits32 (opcode, 10, 8);
2873 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002874 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00002875 wback = true;
2876
2877 // if BitCount(registers) < 1 then UNPREDICTABLE;
2878 if (BitCount (registers) < 1)
2879 return false;
2880
2881 break;
2882
2883 case eEncodingT2:
2884 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2885 n = Bits32 (opcode, 19, 16);
2886 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002887 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00002888 wback = BitIsSet (opcode, 21);
2889
2890 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2891 if ((n == 15) || (BitCount (registers) < 2))
2892 return false;
2893
2894 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2895 if (wback && BitIsSet (registers, n))
2896 return false;
2897
2898 break;
2899
2900 case eEncodingA1:
2901 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2902 n = Bits32 (opcode, 19, 16);
2903 registers = Bits32 (opcode, 15, 0);
2904 wback = BitIsSet (opcode, 21);
2905
2906 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2907 if ((n == 15) || (BitCount (registers) < 1))
2908 return false;
2909
2910 break;
2911
2912 default:
2913 return false;
2914 }
2915
2916 // address = R[n];
2917 int32_t offset = 0;
2918 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2919 if (!success)
2920 return false;
2921
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002922 EmulateInstruction::Context context;
2923 context.type = EmulateInstruction::eContextRegisterStore;
2924 Register base_reg;
2925 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00002926
2927 // for i = 0 to 14
2928 for (int i = 0; i < 14; ++i)
2929 {
2930 int lowest_set_bit = 14;
2931 // if registers<i> == ’1’ then
2932 if (BitIsSet (registers, i))
2933 {
2934 if (i < lowest_set_bit)
2935 lowest_set_bit = i;
2936 // if i == n && wback && i != LowestSetBit(registers) then
2937 if ((i == n) && wback && (i != lowest_set_bit))
2938 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2939 WriteBits32UnknownToMemory (address + offset);
2940 else
2941 {
2942 // MemA[address,4] = R[i];
2943 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2944 if (!success)
2945 return false;
2946
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002947 Register data_reg;
2948 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
2949 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002950 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2951 return false;
2952 }
2953
2954 // address = address + 4;
2955 offset += addr_byte_size;
2956 }
2957 }
2958
2959 // if registers<15> == ’1’ then // Only possible for encoding A1
2960 // MemA[address,4] = PCStoreValue();
2961 if (BitIsSet (registers, 15))
2962 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002963 Register pc_reg;
2964 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
2965 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00002966 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2967 if (!success)
2968 return false;
2969
2970 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2971 return false;
2972 }
2973
2974 // if wback then R[n] = R[n] + 4*BitCount(registers);
2975 if (wback)
2976 {
2977 offset = addr_byte_size * BitCount (registers);
2978 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002979 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002980 addr_t data = address + offset;
2981 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2982 return false;
2983 }
2984 }
2985 return true;
2986}
2987
Caroline Ticeaf556562011-02-15 18:42:15 +00002988// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
2989// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
2990// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00002991bool
2992EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
2993{
2994#if 0
2995 if ConditionPassed() then
2996 EncodingSpecificOperations();
2997 address = R[n] - 4*BitCount(registers) + 4;
2998
2999 for i = 0 to 14
3000 if registers<i> == ’1’ then
3001 if i == n && wback && i != LowestSetBit(registers) then
3002 MemA[address,4] = bits(32) UNKNOWN;
3003 else
3004 MemA[address,4] = R[i];
3005 address = address + 4;
3006
3007 if registers<15> == ’1’ then
3008 MemA[address,4] = PCStoreValue();
3009
3010 if wback then R[n] = R[n] - 4*BitCount(registers);
3011#endif
3012
3013 bool success = false;
3014 const uint32_t opcode = OpcodeAsUnsigned (&success);
3015 if (!success)
3016 return false;
3017
3018 if (ConditionPassed ())
3019 {
3020 uint32_t n;
3021 uint32_t registers = 0;
3022 bool wback;
3023 const uint32_t addr_byte_size = GetAddressByteSize();
3024
3025 // EncodingSpecificOperations();
3026 switch (encoding)
3027 {
3028 case eEncodingA1:
3029 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3030 n = Bits32 (opcode, 19, 16);
3031 registers = Bits32 (opcode, 15, 0);
3032 wback = BitIsSet (opcode, 21);
3033
3034 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3035 if ((n == 15) || (BitCount (registers) < 1))
3036 return false;
3037 break;
3038 default:
3039 return false;
3040 }
3041
3042 // address = R[n] - 4*BitCount(registers) + 4;
3043 int32_t offset = 0;
3044 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3045 if (!success)
3046 return false;
3047
3048 address = address - (addr_byte_size * BitCount (registers)) + 4;
3049
3050 EmulateInstruction::Context context;
3051 context.type = EmulateInstruction::eContextRegisterStore;
3052 Register base_reg;
3053 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3054
3055 // for i = 0 to 14
3056 for (int i = 0; i < 14; ++i)
3057 {
3058 int lowest_bit_set = 14;
3059 // if registers<i> == ’1’ then
3060 if (BitIsSet (registers, i))
3061 {
3062 if (i < lowest_bit_set)
3063 lowest_bit_set = i;
3064 //if i == n && wback && i != LowestSetBit(registers) then
3065 if ((i == n) && wback && (i != lowest_bit_set))
3066 // MemA[address,4] = bits(32) UNKNOWN;
3067 WriteBits32UnknownToMemory (address + offset);
3068 else
3069 {
3070 // MemA[address,4] = R[i];
3071 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3072 if (!success)
3073 return false;
3074
3075 Register data_reg;
3076 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3077 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3078 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3079 return false;
3080 }
3081
3082 // address = address + 4;
3083 offset += addr_byte_size;
3084 }
3085 }
3086
3087 // if registers<15> == ’1’ then
3088 // MemA[address,4] = PCStoreValue();
3089 if (BitIsSet (registers, 15))
3090 {
3091 Register pc_reg;
3092 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3093 context.SetRegisterPlusOffset (pc_reg, 8);
3094 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3095 if (!success)
3096 return false;
3097
3098 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3099 return false;
3100 }
3101
3102 // if wback then R[n] = R[n] - 4*BitCount(registers);
3103 if (wback)
3104 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003105 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003106 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3107 context.SetImmediateSigned (offset);
3108 addr_t data = address + offset;
3109 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3110 return false;
3111 }
3112 }
3113 return true;
3114}
3115
Caroline Ticeaf556562011-02-15 18:42:15 +00003116// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3117// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3118// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003119bool
3120EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3121{
3122#if 0
3123 if ConditionPassed() then
3124 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3125 address = R[n] - 4*BitCount(registers);
3126
3127 for i = 0 to 14
3128 if registers<i> == ’1’ then
3129 if i == n && wback && i != LowestSetBit(registers) then
3130 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3131 else
3132 MemA[address,4] = R[i];
3133 address = address + 4;
3134
3135 if registers<15> == ’1’ then // Only possible for encoding A1
3136 MemA[address,4] = PCStoreValue();
3137
3138 if wback then R[n] = R[n] - 4*BitCount(registers);
3139#endif
3140
3141
3142 bool success = false;
3143 const uint32_t opcode = OpcodeAsUnsigned (&success);
3144 if (!success)
3145 return false;
3146
3147 if (ConditionPassed ())
3148 {
3149 uint32_t n;
3150 uint32_t registers = 0;
3151 bool wback;
3152 const uint32_t addr_byte_size = GetAddressByteSize();
3153
3154 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3155 switch (encoding)
3156 {
3157 case eEncodingT1:
3158 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3159 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3160 {
3161 // See PUSH
3162 }
3163 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3164 n = Bits32 (opcode, 19, 16);
3165 registers = Bits32 (opcode, 15, 0);
3166 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3167 wback = BitIsSet (opcode, 21);
3168 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3169 if ((n == 15) || BitCount (registers) < 2)
3170 return false;
3171 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3172 if (wback && BitIsSet (registers, n))
3173 return false;
3174 break;
3175
3176 case eEncodingA1:
3177 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3178 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3179 {
3180 // See Push
3181 }
3182 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3183 n = Bits32 (opcode, 19, 16);
3184 registers = Bits32 (opcode, 15, 0);
3185 wback = BitIsSet (opcode, 21);
3186 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3187 if ((n == 15) || BitCount (registers) < 1)
3188 return false;
3189 break;
3190
3191 default:
3192 return false;
3193 }
3194
3195 // address = R[n] - 4*BitCount(registers);
3196
3197 int32_t offset = 0;
3198 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3199 if (!success)
3200 return false;
3201
3202 address = address - (addr_byte_size * BitCount (registers));
3203
3204 EmulateInstruction::Context context;
3205 context.type = EmulateInstruction::eContextRegisterStore;
3206 Register base_reg;
3207 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3208
3209 // for i = 0 to 14
3210 for (int i = 0; i < 14; ++i)
3211 {
3212 uint32_t lowest_set_bit = 14;
3213 // if registers<i> == ’1’ then
3214 if (BitIsSet (registers, i))
3215 {
3216 if (i < lowest_set_bit)
3217 lowest_set_bit = i;
3218 // if i == n && wback && i != LowestSetBit(registers) then
3219 if ((i == n) && wback && (i != lowest_set_bit))
3220 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3221 WriteBits32UnknownToMemory (address + offset);
3222 else
3223 {
3224 // MemA[address,4] = R[i];
3225 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3226 if (!success)
3227 return false;
3228
3229 Register data_reg;
3230 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3231 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3232 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3233 return false;
3234 }
3235
3236 // address = address + 4;
3237 offset += addr_byte_size;
3238 }
3239 }
3240
3241 // if registers<15> == ’1’ then // Only possible for encoding A1
3242 // MemA[address,4] = PCStoreValue();
3243 if (BitIsSet (registers, 15))
3244 {
3245 Register pc_reg;
3246 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3247 context.SetRegisterPlusOffset (pc_reg, 8);
3248 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3249 if (!success)
3250 return false;
3251
3252 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3253 return false;
3254 }
3255
3256 // if wback then R[n] = R[n] - 4*BitCount(registers);
3257 if (wback)
3258 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003259 offset = (addr_byte_size * BitCount (registers)) * -1;
3260 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3261 context.SetImmediateSigned (offset);
3262 addr_t data = address + offset;
3263 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3264 return false;
3265 }
3266 }
3267 return true;
3268}
3269
3270// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3271// from a base register. The consecutive memory locations start just above this address, and the address of the last
3272// of those locations can optionally be written back to the base register.
3273bool
3274EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3275{
3276#if 0
3277 if ConditionPassed() then
3278 EncodingSpecificOperations();
3279 address = R[n] + 4;
3280
3281 for i = 0 to 14
3282 if registers<i> == ’1’ then
3283 if i == n && wback && i != LowestSetBit(registers) then
3284 MemA[address,4] = bits(32) UNKNOWN;
3285 else
3286 MemA[address,4] = R[i];
3287 address = address + 4;
3288
3289 if registers<15> == ’1’ then
3290 MemA[address,4] = PCStoreValue();
3291
3292 if wback then R[n] = R[n] + 4*BitCount(registers);
3293#endif
3294
3295 bool success = false;
3296 const uint32_t opcode = OpcodeAsUnsigned (&success);
3297 if (!success)
3298 return false;
3299
3300 if (ConditionPassed())
3301 {
3302 uint32_t n;
3303 uint32_t registers = 0;
3304 bool wback;
3305 const uint32_t addr_byte_size = GetAddressByteSize();
3306
3307 // EncodingSpecificOperations();
3308 switch (encoding)
3309 {
3310 case eEncodingA1:
3311 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3312 n = Bits32 (opcode, 19, 16);
3313 registers = Bits32 (opcode, 15, 0);
3314 wback = BitIsSet (opcode, 21);
3315
3316 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3317 if ((n == 15) && (BitCount (registers) < 1))
3318 return false;
3319 break;
3320 default:
3321 return false;
3322 }
3323 // address = R[n] + 4;
3324
3325 int32_t offset = 0;
3326 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3327 if (!success)
3328 return false;
3329
3330 address = address + addr_byte_size;
3331
3332 EmulateInstruction::Context context;
3333 context.type = EmulateInstruction::eContextRegisterStore;
3334 Register base_reg;
3335 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3336
3337 uint32_t lowest_set_bit = 14;
3338 // for i = 0 to 14
3339 for (int i = 0; i < 14; ++i)
3340 {
3341 // if registers<i> == ’1’ then
3342 if (BitIsSet (registers, i))
3343 {
3344 if (i < lowest_set_bit)
3345 lowest_set_bit = i;
3346 // if i == n && wback && i != LowestSetBit(registers) then
3347 if ((i == n) && wback && (i != lowest_set_bit))
3348 // MemA[address,4] = bits(32) UNKNOWN;
3349 WriteBits32UnknownToMemory (address + offset);
3350 // else
3351 else
3352 {
3353 // MemA[address,4] = R[i];
3354 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3355 if (!success)
3356 return false;
3357
3358 Register data_reg;
3359 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3360 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3361 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3362 return false;
3363 }
3364
3365 // address = address + 4;
3366 offset += addr_byte_size;
3367 }
3368 }
3369
3370 // if registers<15> == ’1’ then
3371 // MemA[address,4] = PCStoreValue();
3372 if (BitIsSet (registers, 15))
3373 {
3374 Register pc_reg;
3375 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3376 context.SetRegisterPlusOffset (pc_reg, 8);
3377 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3378 if (!success)
3379 return false;
3380
3381 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3382 return false;
3383 }
3384
3385 // if wback then R[n] = R[n] + 4*BitCount(registers);
3386 if (wback)
3387 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003388 offset = addr_byte_size * BitCount (registers);
3389 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3390 context.SetImmediateSigned (offset);
3391 addr_t data = address + offset;
3392 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3393 return false;
3394 }
3395 }
3396 return true;
3397}
3398
Caroline Ticeaf556562011-02-15 18:42:15 +00003399
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003400EmulateInstructionARM::ARMOpcode*
3401EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00003402{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003403 static ARMOpcode
3404 g_arm_opcodes[] =
3405 {
3406 //----------------------------------------------------------------------
3407 // Prologue instructions
3408 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00003409
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003410 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00003411 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
3412 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00003413
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003414 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00003415 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
3416 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00003417 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00003418 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
3419 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
3420 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00003421
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003422 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00003423 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00003424
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003425 // push one register
3426 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00003427 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00003428
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003429 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00003430 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3431 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00003432
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003433 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00003434 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003435 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00003436
Johnny Chenc28a76d2011-02-01 18:51:48 +00003437 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
3438 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00003439 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003440 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
3441
3442 //----------------------------------------------------------------------
3443 // Supervisor Call (previously Software Interrupt)
3444 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00003445 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
3446
3447 //----------------------------------------------------------------------
3448 // Branch instructions
3449 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003450 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00003451 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
3452 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3453 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3454 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003455 // for example, "bx lr"
3456 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003457
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003458 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00003459 // Data-processing instructions
3460 //----------------------------------------------------------------------
3461 // move bitwise not
3462 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00003463 // asr (immediate)
3464 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen28070c32011-02-12 01:27:26 +00003465
3466 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003467 // Load instructions
3468 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00003469 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00003470 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00003471 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00003472 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
3473
3474 //----------------------------------------------------------------------
3475 // Store instructions
3476 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00003477 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003478 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00003479 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
3480 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }
Caroline Tice1511f502011-02-15 00:19:42 +00003481
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003482
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003483 };
3484 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
3485
3486 for (size_t i=0; i<k_num_arm_opcodes; ++i)
3487 {
3488 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
3489 return &g_arm_opcodes[i];
3490 }
3491 return NULL;
3492}
Greg Clayton64c84432011-01-21 22:02:52 +00003493
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003494
3495EmulateInstructionARM::ARMOpcode*
3496EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00003497{
Johnny Chenfdd179e2011-01-31 20:09:28 +00003498
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003499 static ARMOpcode
3500 g_thumb_opcodes[] =
3501 {
3502 //----------------------------------------------------------------------
3503 // Prologue instructions
3504 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00003505
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003506 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00003507 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00003508 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
3509 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00003510
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003511 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00003512 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00003513 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00003514 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00003515 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
3516 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00003517
Johnny Chenc9de9102011-02-11 19:12:30 +00003518 // PC-relative load into register (see also EmulateAddSPRm)
3519 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00003520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003521 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00003522 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
3523 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003524 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
3525 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003526
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003527 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00003528 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3529 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003531 //----------------------------------------------------------------------
3532 // Epilogue instructions
3533 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00003534
Johnny Chenc28a76d2011-02-01 18:51:48 +00003535 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
3536 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003537 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
3538 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
3539 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
3540 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003541
3542 //----------------------------------------------------------------------
3543 // Supervisor Call (previously Software Interrupt)
3544 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00003545 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
3546
3547 //----------------------------------------------------------------------
3548 // If Then makes up to four following instructions conditional.
3549 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00003550 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
3551
3552 //----------------------------------------------------------------------
3553 // Branch instructions
3554 //----------------------------------------------------------------------
3555 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
3556 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
3557 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00003558 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003559 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00003560 // J1 == J2 == 1
3561 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3562 // J1 == J2 == 1
3563 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3564 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003565 // for example, "bx lr"
3566 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00003567 // compare and branch
3568 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003569
3570 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00003571 // Data-processing instructions
3572 //----------------------------------------------------------------------
3573 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
3574 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00003575 // move from high register to high register
3576 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
3577 // move from low register to low register
3578 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00003579 // move immediate
3580 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
3581 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00003582 // move bitwise not
3583 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00003584 // compare a register with immediate
3585 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00003586 // compare Rn with Rm (Rn and Rm both from r0-r7)
3587 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
3588 // compare Rn with Rm (Rn and Rm not both from r0-r7)
3589 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00003590 // asr (immediate)
3591 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00003592 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen26863dc2011-02-09 23:43:29 +00003593
3594 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003595 // Load instructions
3596 //----------------------------------------------------------------------
3597 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00003599 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00003600 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
3601 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00003602 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
3603
3604 //----------------------------------------------------------------------
3605 // Store instructions
3606 //----------------------------------------------------------------------
3607 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003608 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
3609 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003610
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003611 };
3612
3613 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
3614 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
3615 {
3616 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
3617 return &g_thumb_opcodes[i];
3618 }
3619 return NULL;
3620}
Greg Clayton64c84432011-01-21 22:02:52 +00003621
Greg Clayton31e2a382011-01-30 20:03:56 +00003622bool
3623EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
3624{
3625 m_arm_isa = 0;
3626 const char *triple_cstr = triple.GetCString();
3627 if (triple_cstr)
3628 {
3629 const char *dash = ::strchr (triple_cstr, '-');
3630 if (dash)
3631 {
3632 std::string arch (triple_cstr, dash);
3633 const char *arch_cstr = arch.c_str();
3634 if (strcasecmp(arch_cstr, "armv4t") == 0)
3635 m_arm_isa = ARMv4T;
3636 else if (strcasecmp(arch_cstr, "armv4") == 0)
3637 m_arm_isa = ARMv4;
3638 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
3639 m_arm_isa = ARMv5TEJ;
3640 else if (strcasecmp(arch_cstr, "armv5te") == 0)
3641 m_arm_isa = ARMv5TE;
3642 else if (strcasecmp(arch_cstr, "armv5t") == 0)
3643 m_arm_isa = ARMv5T;
3644 else if (strcasecmp(arch_cstr, "armv6k") == 0)
3645 m_arm_isa = ARMv6K;
3646 else if (strcasecmp(arch_cstr, "armv6") == 0)
3647 m_arm_isa = ARMv6;
3648 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
3649 m_arm_isa = ARMv6T2;
3650 else if (strcasecmp(arch_cstr, "armv7") == 0)
3651 m_arm_isa = ARMv7;
3652 else if (strcasecmp(arch_cstr, "armv8") == 0)
3653 m_arm_isa = ARMv8;
3654 }
3655 }
3656 return m_arm_isa != 0;
3657}
3658
3659
Greg Clayton64c84432011-01-21 22:02:52 +00003660bool
3661EmulateInstructionARM::ReadInstruction ()
3662{
3663 bool success = false;
3664 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
3665 if (success)
3666 {
3667 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
3668 if (success)
3669 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003670 Context read_inst_context;
3671 read_inst_context.type = eContextReadOpcode;
3672 read_inst_context.SetNoArgs ();
3673
Greg Clayton64c84432011-01-21 22:02:52 +00003674 if (m_inst_cpsr & MASK_CPSR_T)
3675 {
3676 m_inst_mode = eModeThumb;
3677 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
3678
3679 if (success)
3680 {
3681 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
3682 {
3683 m_inst.opcode_type = eOpcode16;
3684 m_inst.opcode.inst16 = thumb_opcode;
3685 }
3686 else
3687 {
3688 m_inst.opcode_type = eOpcode32;
3689 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
3690 }
3691 }
3692 }
3693 else
3694 {
3695 m_inst_mode = eModeARM;
3696 m_inst.opcode_type = eOpcode32;
3697 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
3698 }
3699 }
3700 }
3701 if (!success)
3702 {
3703 m_inst_mode = eModeInvalid;
3704 m_inst_pc = LLDB_INVALID_ADDRESS;
3705 }
3706 return success;
3707}
3708
Johnny Chenee9b1f72011-02-09 01:00:31 +00003709uint32_t
3710EmulateInstructionARM::ArchVersion ()
3711{
3712 return m_arm_isa;
3713}
3714
Greg Clayton64c84432011-01-21 22:02:52 +00003715bool
3716EmulateInstructionARM::ConditionPassed ()
3717{
3718 if (m_inst_cpsr == 0)
3719 return false;
3720
3721 const uint32_t cond = CurrentCond ();
3722
3723 if (cond == UINT32_MAX)
3724 return false;
3725
3726 bool result = false;
3727 switch (UnsignedBits(cond, 3, 1))
3728 {
3729 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
3730 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
3731 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
3732 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
3733 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
3734 case 5:
3735 {
3736 bool n = (m_inst_cpsr & MASK_CPSR_N);
3737 bool v = (m_inst_cpsr & MASK_CPSR_V);
3738 result = n == v;
3739 }
3740 break;
3741 case 6:
3742 {
3743 bool n = (m_inst_cpsr & MASK_CPSR_N);
3744 bool v = (m_inst_cpsr & MASK_CPSR_V);
3745 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3746 }
3747 break;
3748 case 7:
3749 result = true;
3750 break;
3751 }
3752
3753 if (cond & 1)
3754 result = !result;
3755 return result;
3756}
3757
Johnny Chen9ee056b2011-02-08 00:06:35 +00003758uint32_t
3759EmulateInstructionARM::CurrentCond ()
3760{
3761 switch (m_inst_mode)
3762 {
3763 default:
3764 case eModeInvalid:
3765 break;
3766
3767 case eModeARM:
3768 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3769
3770 case eModeThumb:
3771 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3772 // 'cond' field of the encoding.
3773 if (m_inst.opcode_type == eOpcode16 &&
3774 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3775 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3776 {
3777 return Bits32(m_inst.opcode.inst16, 11, 7);
3778 }
3779 else if (m_inst.opcode_type == eOpcode32 &&
3780 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3781 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3782 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3783 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3784 {
3785 return Bits32(m_inst.opcode.inst32, 25, 22);
3786 }
3787
3788 return m_it_session.GetCond();
3789 }
3790 return UINT32_MAX; // Return invalid value
3791}
3792
Johnny Chen9ee056b2011-02-08 00:06:35 +00003793bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003794EmulateInstructionARM::InITBlock()
3795{
3796 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3797}
3798
3799bool
3800EmulateInstructionARM::LastInITBlock()
3801{
3802 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3803}
3804
3805bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003806EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3807{
3808 addr_t target;
3809
Johnny Chenee9b1f72011-02-09 01:00:31 +00003810 // Check the current instruction set.
3811 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003812 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003813 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003814 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003815
Johnny Chen9ee056b2011-02-08 00:06:35 +00003816 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003817 return false;
3818
3819 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003820}
3821
3822// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3823bool
Johnny Chen668b4512011-02-15 21:08:58 +00003824EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003825{
3826 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003827 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3828 // we want to record it and issue a WriteRegister callback so the clients
3829 // can track the mode changes accordingly.
3830 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003831
3832 if (BitIsSet(addr, 0))
3833 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003834 if (CurrentInstrSet() != eModeThumb)
3835 {
3836 SelectInstrSet(eModeThumb);
3837 cpsr_changed = true;
3838 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003839 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00003840 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003841 }
3842 else if (BitIsClear(addr, 1))
3843 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003844 if (CurrentInstrSet() != eModeARM)
3845 {
3846 SelectInstrSet(eModeARM);
3847 cpsr_changed = true;
3848 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003849 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00003850 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003851 }
3852 else
3853 return false; // address<1:0> == '10' => UNPREDICTABLE
3854
Johnny Chen0f309db2011-02-09 19:11:32 +00003855 if (cpsr_changed)
3856 {
Johnny Chen558133b2011-02-09 23:59:17 +00003857 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003858 return false;
3859 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003860 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003861 return false;
3862
3863 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003864}
Greg Clayton64c84432011-01-21 22:02:52 +00003865
Johnny Chenee9b1f72011-02-09 01:00:31 +00003866// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3867bool
Johnny Chen668b4512011-02-15 21:08:58 +00003868EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00003869{
3870 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00003871 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00003872 else
3873 return BranchWritePC((const Context)context, addr);
3874}
3875
Johnny Chen26863dc2011-02-09 23:43:29 +00003876// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3877bool
Johnny Chen668b4512011-02-15 21:08:58 +00003878EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00003879{
3880 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00003881 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00003882 else
3883 return BranchWritePC((const Context)context, addr);
3884}
3885
Johnny Chenee9b1f72011-02-09 01:00:31 +00003886EmulateInstructionARM::Mode
3887EmulateInstructionARM::CurrentInstrSet ()
3888{
3889 return m_inst_mode;
3890}
3891
3892// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003893// ReadInstruction() is performed. This function has a side effect of updating
3894// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003895bool
3896EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3897{
Johnny Chen558133b2011-02-09 23:59:17 +00003898 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003899 switch (arm_or_thumb)
3900 {
3901 default:
3902 return false;
3903 eModeARM:
3904 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003905 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003906 break;
3907 eModeThumb:
3908 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003909 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003910 break;
3911 }
3912 return true;
3913}
3914
Johnny Chenef21b592011-02-10 01:52:38 +00003915// This function returns TRUE if the processor currently provides support for
3916// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3917// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3918bool
3919EmulateInstructionARM::UnalignedSupport()
3920{
3921 return (ArchVersion() >= ARMv7);
3922}
3923
Johnny Chenbf6ad172011-02-11 01:29:53 +00003924// The main addition and subtraction instructions can produce status information
3925// about both unsigned carry and signed overflow conditions. This status
3926// information can be used to synthesize multi-word additions and subtractions.
3927EmulateInstructionARM::AddWithCarryResult
3928EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3929{
3930 uint32_t result;
3931 uint8_t carry_out;
3932 uint8_t overflow;
3933
3934 uint64_t unsigned_sum = x + y + carry_in;
3935 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3936
3937 result = UnsignedBits(unsigned_sum, 31, 0);
3938 carry_out = (result == unsigned_sum ? 0 : 1);
3939 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3940
3941 AddWithCarryResult res = { result, carry_out, overflow };
3942 return res;
3943}
3944
Greg Clayton64c84432011-01-21 22:02:52 +00003945bool
3946EmulateInstructionARM::EvaluateInstruction ()
3947{
Johnny Chenc315f862011-02-05 00:46:10 +00003948 // Advance the ITSTATE bits to their values for the next instruction.
3949 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3950 m_it_session.ITAdvance();
3951
Greg Clayton64c84432011-01-21 22:02:52 +00003952 return false;
3953}