blob: 3dfaa4d349bffab6cfc93010ae02b281013af3f8 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000013#include "lldb/Core/ConstString.h"
14
Greg Claytonf29a08f2011-02-09 17:41:27 +000015#include "Plugins/Process/Utility/ARMDefines.h"
16#include "Plugins/Process/Utility/ARMUtils.h"
17#include "Utility/ARM_DWARF_Registers.h"
18
Johnny Chen9b8d7832011-02-02 01:13:56 +000019#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000020 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Johnny Chend6c13f02011-02-08 20:36:34 +000025static inline uint32_t Align(uint32_t val, uint32_t alignment)
26{
27 return alignment * (val / alignment);
28}
29
Johnny Chen0e00af22011-02-10 19:40:42 +000030//----------------------------------------------------------------------
31//
32// ITSession implementation
33//
34//----------------------------------------------------------------------
35
Johnny Chen93070472011-02-04 23:02:47 +000036// A8.6.50
37// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
38static unsigned short CountITSize(unsigned ITMask) {
39 // First count the trailing zeros of the IT mask.
40 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
41 if (TZ > 3)
42 {
43 printf("Encoding error: IT Mask '0000'\n");
44 return 0;
45 }
46 return (4 - TZ);
47}
48
49// Init ITState. Note that at least one bit is always 1 in mask.
50bool ITSession::InitIT(unsigned short bits7_0)
51{
52 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
53 if (ITCounter == 0)
54 return false;
55
56 // A8.6.50 IT
57 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
58 if (FirstCond == 0xF)
59 {
60 printf("Encoding error: IT FirstCond '1111'\n");
61 return false;
62 }
63 if (FirstCond == 0xE && ITCounter != 1)
64 {
65 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
66 return false;
67 }
68
69 ITState = bits7_0;
70 return true;
71}
72
73// Update ITState if necessary.
74void ITSession::ITAdvance()
75{
76 assert(ITCounter);
77 --ITCounter;
78 if (ITCounter == 0)
79 ITState = 0;
80 else
81 {
82 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
83 SetBits32(ITState, 4, 0, NewITState4_0);
84 }
85}
86
87// Return true if we're inside an IT Block.
88bool ITSession::InITBlock()
89{
90 return ITCounter != 0;
91}
92
Johnny Chenc315f862011-02-05 00:46:10 +000093// Return true if we're the last instruction inside an IT Block.
94bool ITSession::LastInITBlock()
95{
96 return ITCounter == 1;
97}
98
Johnny Chen93070472011-02-04 23:02:47 +000099// Get condition bits for the current thumb instruction.
100uint32_t ITSession::GetCond()
101{
Johnny Chenc315f862011-02-05 00:46:10 +0000102 if (InITBlock())
103 return Bits32(ITState, 7, 4);
104 else
105 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000106}
107
Greg Clayton64c84432011-01-21 22:02:52 +0000108// ARM constants used during decoding
109#define REG_RD 0
110#define LDM_REGLIST 1
111#define PC_REG 15
112#define PC_REGLIST_BIT 0x8000
113
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMv4T (1u << 1)
116#define ARMv5T (1u << 2)
117#define ARMv5TE (1u << 3)
118#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000119#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMv6K (1u << 6)
121#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000123#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMvAll (0xffffffffu)
125
Johnny Chen9b8d7832011-02-02 01:13:56 +0000126#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
127#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000129
Johnny Chen0e00af22011-02-10 19:40:42 +0000130//----------------------------------------------------------------------
131//
132// EmulateInstructionARM implementation
133//
134//----------------------------------------------------------------------
135
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000136void
137EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
145
Caroline Ticefa172202011-02-11 22:49:54 +0000146// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
147bool
148EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
149{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000150 EmulateInstruction::Context context;
151 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
152 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000153
154 uint32_t random_data = rand ();
155 const uint32_t addr_byte_size = GetAddressByteSize();
156
157 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
158 return false;
159
160 return true;
161}
162
Caroline Tice713c2662011-02-11 17:59:55 +0000163// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
164bool
165EmulateInstructionARM::WriteBits32Unknown (int n)
166{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000167 EmulateInstruction::Context context;
168 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
169 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000170
Johnny Chen62ff6f52011-02-11 18:11:22 +0000171 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000172 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
173
174 if (!success)
175 return false;
176
177 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
178 return false;
179
180 return true;
181}
182
Johnny Chen08c25e82011-01-31 18:02:28 +0000183// Push Multiple Registers stores multiple registers to the stack, storing to
184// consecutive memory locations ending just below the address in SP, and updates
185// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000186bool
187EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000188{
189#if 0
190 // ARM pseudo code...
191 if (ConditionPassed())
192 {
193 EncodingSpecificOperations();
194 NullCheckIfThumbEE(13);
195 address = SP - 4*BitCount(registers);
196
197 for (i = 0 to 14)
198 {
199 if (registers<i> == ’1’)
200 {
201 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
202 MemA[address,4] = bits(32) UNKNOWN;
203 else
204 MemA[address,4] = R[i];
205 address = address + 4;
206 }
207 }
208
209 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
210 MemA[address,4] = PCStoreValue();
211
212 SP = SP - 4*BitCount(registers);
213 }
214#endif
215
216 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000217 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 if (!success)
219 return false;
220
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000222 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t addr_byte_size = GetAddressByteSize();
224 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000225 if (!success)
226 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000227 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000228 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000230 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000231 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000233 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000234 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 // if BitCount(registers) < 1 then UNPREDICTABLE;
236 if (BitCount(registers) < 1)
237 return false;
238 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000239 case eEncodingT2:
240 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000241 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000242 // if BitCount(registers) < 2 then UNPREDICTABLE;
243 if (BitCount(registers) < 2)
244 return false;
245 break;
246 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000249 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000253 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000254 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000255 // Instead of return false, let's handle the following case as well,
256 // which amounts to pushing one reg onto the full descending stacks.
257 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000258 break;
259 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000261 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000262 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000263 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000266 default:
267 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 }
Johnny Chence1ca772011-01-25 01:13:00 +0000269 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000270 addr_t addr = sp - sp_offset;
271 uint32_t i;
272
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000273 EmulateInstruction::Context context;
274 context.type = EmulateInstruction::eContextPushRegisterOnStack;
275 Register dwarf_reg;
276 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000277 for (i=0; i<15; ++i)
278 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000279 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000280 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000281 dwarf_reg.num = dwarf_r0 + i;
282 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
283 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000284 if (!success)
285 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000286 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000287 return false;
288 addr += addr_byte_size;
289 }
290 }
291
Johnny Chen7c1bf922011-02-08 23:49:37 +0000292 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000293 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000294 dwarf_reg.num = dwarf_pc;
295 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000296 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000297 if (!success)
298 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000299 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000300 return false;
301 }
302
303 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000304 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000305
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000306 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000307 return false;
308 }
309 return true;
310}
311
Johnny Chenef85e912011-01-31 23:07:40 +0000312// Pop Multiple Registers loads multiple registers from the stack, loading from
313// consecutive memory locations staring at the address in SP, and updates
314// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000315bool
316EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000317{
318#if 0
319 // ARM pseudo code...
320 if (ConditionPassed())
321 {
322 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
323 address = SP;
324 for i = 0 to 14
325 if registers<i> == ‘1’ then
326 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
327 if registers<15> == ‘1’ then
328 if UnalignedAllowed then
329 LoadWritePC(MemU[address,4]);
330 else
331 LoadWritePC(MemA[address,4]);
332 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
333 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
334 }
335#endif
336
337 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000338 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000339 if (!success)
340 return false;
341
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000343 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 const uint32_t addr_byte_size = GetAddressByteSize();
345 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000346 if (!success)
347 return false;
348 uint32_t registers = 0;
349 uint32_t Rt; // the destination register
350 switch (encoding) {
351 case eEncodingT1:
352 registers = Bits32(opcode, 7, 0);
353 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000354 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000355 registers |= (1u << 15);
356 // if BitCount(registers) < 1 then UNPREDICTABLE;
357 if (BitCount(registers) < 1)
358 return false;
359 break;
360 case eEncodingT2:
361 // Ignore bit 13.
362 registers = Bits32(opcode, 15, 0) & ~0x2000;
363 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000364 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000365 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000366 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
367 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
368 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000369 break;
370 case eEncodingT3:
371 Rt = Bits32(opcode, 15, 12);
372 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000373 if (Rt == 13)
374 return false;
375 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000376 return false;
377 registers = (1u << Rt);
378 break;
379 case eEncodingA1:
380 registers = Bits32(opcode, 15, 0);
381 // Instead of return false, let's handle the following case as well,
382 // which amounts to popping one reg from the full descending stacks.
383 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
384
385 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000386 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000387 return false;
388 break;
389 case eEncodingA2:
390 Rt = Bits32(opcode, 15, 12);
391 // if t == 13 then UNPREDICTABLE;
392 if (Rt == dwarf_sp)
393 return false;
394 registers = (1u << Rt);
395 break;
396 default:
397 return false;
398 }
399 addr_t sp_offset = addr_byte_size * BitCount (registers);
400 addr_t addr = sp;
401 uint32_t i, data;
402
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000403 EmulateInstruction::Context context;
404 context.type = EmulateInstruction::eContextPopRegisterOffStack;
405 Register dwarf_reg;
406 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000407 for (i=0; i<15; ++i)
408 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000409 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 dwarf_reg.num = dwarf_r0 + i;
412 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000413 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000414 if (!success)
415 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000416 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000417 return false;
418 addr += addr_byte_size;
419 }
420 }
421
Johnny Chen7c1bf922011-02-08 23:49:37 +0000422 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000423 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000424 dwarf_reg.num = dwarf_pc;
425 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000427 if (!success)
428 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000429 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000430 if (!LoadWritePC(context, data, dwarf_reg))
Johnny Chenef85e912011-01-31 23:07:40 +0000431 return false;
432 addr += addr_byte_size;
433 }
434
435 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000436 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000437
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 }
441 return true;
442}
443
Johnny Chen5b442b72011-01-27 19:34:30 +0000444// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000445// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446bool
447EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448{
449#if 0
450 // ARM pseudo code...
451 if (ConditionPassed())
452 {
453 EncodingSpecificOperations();
454 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
455 if d == 15 then
456 ALUWritePC(result); // setflags is always FALSE here
457 else
458 R[d] = result;
459 if setflags then
460 APSR.N = result<31>;
461 APSR.Z = IsZeroBit(result);
462 APSR.C = carry;
463 APSR.V = overflow;
464 }
465#endif
466
467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if (!success)
470 return false;
471
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000494 EmulateInstruction::Context context;
495 context.type = EmulateInstruction::eContextRegisterPlusOffset;
496 Register sp_reg;
497 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
498 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000499
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501 return false;
502 }
503 return true;
504}
505
Johnny Chen2ccad832011-01-28 19:57:25 +0000506// Set r7 or ip to the current stack pointer.
507// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508bool
509EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000510{
511#if 0
512 // ARM pseudo code...
513 if (ConditionPassed())
514 {
515 EncodingSpecificOperations();
516 result = R[m];
517 if d == 15 then
518 ALUWritePC(result); // setflags is always FALSE here
519 else
520 R[d] = result;
521 if setflags then
522 APSR.N = result<31>;
523 APSR.Z = IsZeroBit(result);
524 // APSR.C unchanged
525 // APSR.V unchanged
526 }
527#endif
528
529 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000531 //if (!success)
532 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000533
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000535 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000537 if (!success)
538 return false;
539 uint32_t Rd; // the destination register
540 switch (encoding) {
541 case eEncodingT1:
542 Rd = 7;
543 break;
544 case eEncodingA1:
545 Rd = 12;
546 break;
547 default:
548 return false;
549 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000550
551 EmulateInstruction::Context context;
552 context.type = EmulateInstruction::eContextRegisterPlusOffset;
553 Register sp_reg;
554 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
555 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000556
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000557 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000558 return false;
559 }
560 return true;
561}
562
Johnny Chen1c13b622011-01-29 00:11:15 +0000563// Move from high register (r8-r15) to low register (r0-r7).
564// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000565bool
566EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000567{
Johnny Chen338bf542011-02-10 19:29:03 +0000568 return EmulateMovRdRm (encoding);
569}
570
571// Move from register to register.
572// MOV (register)
573bool
574EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
575{
Johnny Chen1c13b622011-01-29 00:11:15 +0000576#if 0
577 // ARM pseudo code...
578 if (ConditionPassed())
579 {
580 EncodingSpecificOperations();
581 result = R[m];
582 if d == 15 then
583 ALUWritePC(result); // setflags is always FALSE here
584 else
585 R[d] = result;
586 if setflags then
587 APSR.N = result<31>;
588 APSR.Z = IsZeroBit(result);
589 // APSR.C unchanged
590 // APSR.V unchanged
591 }
592#endif
593
594 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000595 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 if (!success)
597 return false;
598
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 {
601 uint32_t Rm; // the source register
602 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000603 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 switch (encoding) {
605 case eEncodingT1:
606 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000607 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000608 setflags = false;
609 break;
610 case eEncodingT2:
611 Rm = Bits32(opcode, 5, 3);
612 Rd = Bits32(opcode, 2, 1);
613 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 break;
615 default:
616 return false;
617 }
Johnny Chen338bf542011-02-10 19:29:03 +0000618 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000619 if (!success)
620 return false;
621
622 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000623 EmulateInstruction::Context context;
624 context.type = EmulateInstruction::eContextRegisterPlusOffset;
625 Register dwarf_reg;
626 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
627 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000628
Johnny Chen338bf542011-02-10 19:29:03 +0000629 if (Rd == 15)
630 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000631 if (!ALUWritePC (context, reg_value, dwarf_reg))
Johnny Chen338bf542011-02-10 19:29:03 +0000632 return false;
633 }
634 else
635 {
636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
637 return false;
638 if (setflags)
639 {
640 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000641 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
642 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000643 if (m_new_inst_cpsr != m_inst_cpsr)
644 {
645 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
646 return false;
647 }
648 }
649 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
658EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
677 bool success = false;
678 const uint32_t opcode = OpcodeAsUnsigned (&success);
679 if (!success)
680 return false;
681
682 if (ConditionPassed())
683 {
684 uint32_t Rd; // the destination register
685 uint32_t imm12; // some intermediate result
686 uint32_t imm32; // the immediate value to be written to Rd
687 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
688 bool setflags;
689 switch (encoding) {
690 case eEncodingT1:
691 Rd = Bits32(opcode, 11, 8);
692 setflags = !InITBlock();
693 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
694 carry = Bit32(m_inst_cpsr, CPSR_C);
695 break;
696 case eEncodingT2:
697 Rd = Bits32(opcode, 15, 12);
698 setflags = BitIsSet(opcode, 20);
699 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
700 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
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
714 Register dummy_reg;
715 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
716
Johnny Chen357c30f2011-02-14 22:04:25 +0000717 if (Rd == 15)
718 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000719 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen357c30f2011-02-14 22:04:25 +0000720 return false;
721 }
722 else
723 {
724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
725 return false;
726 if (setflags)
727 {
728 m_new_inst_cpsr = m_inst_cpsr;
729 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
730 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
731 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
732 if (m_new_inst_cpsr != m_inst_cpsr)
733 {
734 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
735 return false;
736 }
737 }
738 }
739 }
740 return true;
741}
742
Johnny Chen28070c32011-02-12 01:27:26 +0000743// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
744// the destination register. It can optionally update the condition flags based
745// on the value.
746// MVN (immediate)
747bool
748EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
749{
750#if 0
751 // ARM pseudo code...
752 if (ConditionPassed())
753 {
754 EncodingSpecificOperations();
755 result = NOT(imm32);
756 if d == 15 then // Can only occur for ARM encoding
757 ALUWritePC(result); // setflags is always FALSE here
758 else
759 R[d] = result;
760 if setflags then
761 APSR.N = result<31>;
762 APSR.Z = IsZeroBit(result);
763 APSR.C = carry;
764 // APSR.V unchanged
765 }
766#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000767 bool success = false;
768 const uint32_t opcode = OpcodeAsUnsigned (&success);
769 if (!success)
770 return false;
771
772 if (ConditionPassed())
773 {
774 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000775 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
776 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
777 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000778 bool setflags;
779 switch (encoding) {
780 case eEncodingT1:
781 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000782 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000783 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000784 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
785 break;
786 case eEncodingA1:
787 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000788 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000789 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000790 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
791 break;
792 default:
793 return false;
794 }
795 uint32_t result = ~imm32;
796
797 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000798 EmulateInstruction::Context context;
799 context.type = EmulateInstruction::eContextImmediate;
800 context.SetNoArgs ();
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000801
802 if (Rd == 15)
803 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000804 Register dummy_reg;
805 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000806 return false;
807 }
808 else
809 {
810 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
811 return false;
812 if (setflags)
813 {
814 m_new_inst_cpsr = m_inst_cpsr;
815 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
816 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
817 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
818 if (m_new_inst_cpsr != m_inst_cpsr)
819 {
820 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
821 return false;
822 }
823 }
824 }
825 }
826 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000827}
828
Johnny Chen788e0552011-01-27 22:52:23 +0000829// PC relative immediate load into register, possibly followed by ADD (SP plus register).
830// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000831bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000832EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000833{
834#if 0
835 // ARM pseudo code...
836 if (ConditionPassed())
837 {
838 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
839 base = Align(PC,4);
840 address = if add then (base + imm32) else (base - imm32);
841 data = MemU[address,4];
842 if t == 15 then
843 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
844 elsif UnalignedSupport() || address<1:0> = ‘00’ then
845 R[t] = data;
846 else // Can only apply before ARMv7
847 if CurrentInstrSet() == InstrSet_ARM then
848 R[t] = ROR(data, 8*UInt(address<1:0>));
849 else
850 R[t] = bits(32) UNKNOWN;
851 }
852#endif
853
854 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000855 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000856 if (!success)
857 return false;
858
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000859 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000860 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000861 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000862 if (!success)
863 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000864
865 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000866 EmulateInstruction::Context context;
867 context.type = EmulateInstruction::eContextRegisterPlusOffset;
868 Register pc_reg;
869 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
870 context.SetRegisterPlusOffset (pc_reg, 0);
871
Johnny Chenc9de9102011-02-11 19:12:30 +0000872 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000873 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000874 bool add; // +imm32 or -imm32?
875 addr_t base; // the base address
876 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000877 uint32_t data; // the literal data value from the PC relative load
878 switch (encoding) {
879 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000880 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000881 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000882 add = true;
883 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000884 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000885 break;
886 case eEncodingT2:
887 Rt = Bits32(opcode, 15, 12);
888 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
889 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000890 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000891 return false;
892 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000893 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000894 break;
895 default:
896 return false;
897 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000898
899 if (add)
900 address = base + imm32;
901 else
902 address = base - imm32;
903 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000904 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000905 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000906
907 if (Rt == 15)
908 {
909 if (Bits32(address, 1, 0) == 0)
910 {
911 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000912 if (!LoadWritePC(context, data, pc_reg))
Johnny Chenc9de9102011-02-11 19:12:30 +0000913 return false;
914 }
915 else
916 return false;
917 }
918 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
919 {
920 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
921 return false;
922 }
923 else // We don't handle ARM for now.
924 return false;
925
926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000927 return false;
928 }
929 return true;
930}
931
Johnny Chen5b442b72011-01-27 19:34:30 +0000932// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000933// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000934bool
935EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000936{
937#if 0
938 // ARM pseudo code...
939 if (ConditionPassed())
940 {
941 EncodingSpecificOperations();
942 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
943 if d == 15 then // Can only occur for ARM encoding
944 ALUWritePC(result); // setflags is always FALSE here
945 else
946 R[d] = result;
947 if setflags then
948 APSR.N = result<31>;
949 APSR.Z = IsZeroBit(result);
950 APSR.C = carry;
951 APSR.V = overflow;
952 }
953#endif
954
955 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000957 if (!success)
958 return false;
959
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000960 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000961 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000962 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000963 if (!success)
964 return false;
965 uint32_t imm32; // the immediate operand
966 switch (encoding) {
967 case eEncodingT2:
968 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
969 break;
970 default:
971 return false;
972 }
973 addr_t sp_offset = imm32;
974 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
975
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000976 EmulateInstruction::Context context;
977 context.type = EmulateInstruction::eContextAdjustStackPointer;
978 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000979
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000980 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000981 return false;
982 }
983 return true;
984}
985
986// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000987// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000988bool
989EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000990{
991#if 0
992 // ARM pseudo code...
993 if (ConditionPassed())
994 {
995 EncodingSpecificOperations();
996 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
997 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
998 if d == 15 then
999 ALUWritePC(result); // setflags is always FALSE here
1000 else
1001 R[d] = result;
1002 if setflags then
1003 APSR.N = result<31>;
1004 APSR.Z = IsZeroBit(result);
1005 APSR.C = carry;
1006 APSR.V = overflow;
1007 }
1008#endif
1009
1010 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001012 if (!success)
1013 return false;
1014
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001015 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001016 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001017 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001018 if (!success)
1019 return false;
1020 uint32_t Rm; // the second operand
1021 switch (encoding) {
1022 case eEncodingT2:
1023 Rm = Bits32(opcode, 6, 3);
1024 break;
1025 default:
1026 return false;
1027 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001028 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001029 if (!success)
1030 return false;
1031
1032 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1033
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001034 EmulateInstruction::Context context;
1035 context.type = EmulateInstruction::eContextAdjustStackPointer;
1036 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001037
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001039 return false;
1040 }
1041 return true;
1042}
1043
Johnny Chen9b8d7832011-02-02 01:13:56 +00001044// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1045// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1046// from Thumb to ARM.
1047// BLX (immediate)
1048bool
1049EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1050{
1051#if 0
1052 // ARM pseudo code...
1053 if (ConditionPassed())
1054 {
1055 EncodingSpecificOperations();
1056 if CurrentInstrSet() == InstrSet_ARM then
1057 LR = PC - 4;
1058 else
1059 LR = PC<31:1> : '1';
1060 if targetInstrSet == InstrSet_ARM then
1061 targetAddress = Align(PC,4) + imm32;
1062 else
1063 targetAddress = PC + imm32;
1064 SelectInstrSet(targetInstrSet);
1065 BranchWritePC(targetAddress);
1066 }
1067#endif
1068
1069 bool success = false;
1070 const uint32_t opcode = OpcodeAsUnsigned (&success);
1071 if (!success)
1072 return false;
1073
1074 if (ConditionPassed())
1075 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001076 EmulateInstruction::Context context;
1077 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001078 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001079 if (!success)
1080 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001081 addr_t lr; // next instruction address
1082 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001083 int32_t imm32; // PC-relative offset
1084 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001085 case eEncodingT1:
1086 {
1087 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001088 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001089 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001090 uint32_t J1 = Bit32(opcode, 13);
1091 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001092 uint32_t imm11 = Bits32(opcode, 10, 0);
1093 uint32_t I1 = !(J1 ^ S);
1094 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001095 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001096 imm32 = llvm::SignExtend32<25>(imm25);
1097 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001098 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001099 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001100 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001101 break;
1102 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001103 case eEncodingT2:
1104 {
1105 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001106 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001107 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001108 uint32_t J1 = Bit32(opcode, 13);
1109 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001110 uint32_t imm10L = Bits32(opcode, 10, 1);
1111 uint32_t I1 = !(J1 ^ S);
1112 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001113 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001115 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001116 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001117 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001118 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001119 break;
1120 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001121 case eEncodingA1:
1122 lr = pc + 4; // return address
1123 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001124 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001125 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001126 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001127 case eEncodingA2:
1128 lr = pc + 4; // return address
1129 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1130 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001131 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001132 break;
1133 default:
1134 return false;
1135 }
1136 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1137 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001138 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001139 return false;
1140 }
1141 return true;
1142}
1143
1144// Branch with Link and Exchange (register) calls a subroutine at an address and
1145// instruction set specified by a register.
1146// BLX (register)
1147bool
1148EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1149{
1150#if 0
1151 // ARM pseudo code...
1152 if (ConditionPassed())
1153 {
1154 EncodingSpecificOperations();
1155 target = R[m];
1156 if CurrentInstrSet() == InstrSet_ARM then
1157 next_instr_addr = PC - 4;
1158 LR = next_instr_addr;
1159 else
1160 next_instr_addr = PC - 2;
1161 LR = next_instr_addr<31:1> : ‘1’;
1162 BXWritePC(target);
1163 }
1164#endif
1165
1166 bool success = false;
1167 const uint32_t opcode = OpcodeAsUnsigned (&success);
1168 if (!success)
1169 return false;
1170
1171 if (ConditionPassed())
1172 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001173 EmulateInstruction::Context context;
1174 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001175 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1176 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001177 if (!success)
1178 return false;
1179 uint32_t Rm; // the register with the target address
1180 switch (encoding) {
1181 case eEncodingT1:
1182 lr = (pc + 2) | 1u; // return address
1183 Rm = Bits32(opcode, 6, 3);
1184 // if m == 15 then UNPREDICTABLE;
1185 if (Rm == 15)
1186 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001187 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001188 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001189 break;
1190 case eEncodingA1:
1191 lr = pc + 4; // return address
1192 Rm = Bits32(opcode, 3, 0);
1193 // if m == 15 then UNPREDICTABLE;
1194 if (Rm == 15)
1195 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001196 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001197 default:
1198 return false;
1199 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001200 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1201 if (!success)
1202 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001203 Register dwarf_reg;
1204 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1205 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001206 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1207 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001208 if (!BXWritePC(context, target, dwarf_reg))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001209 return false;
1210 }
1211 return true;
1212}
1213
Johnny Chenab3b3512011-02-12 00:10:51 +00001214// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1215// BX
1216bool
1217EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1218{
1219#if 0
1220 // ARM pseudo code...
1221 if (ConditionPassed())
1222 {
1223 EncodingSpecificOperations();
1224 BXWritePC(R[m]);
1225 }
1226#endif
1227
1228 bool success = false;
1229 const uint32_t opcode = OpcodeAsUnsigned (&success);
1230 if (!success)
1231 return false;
1232
1233 if (ConditionPassed())
1234 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001235 EmulateInstruction::Context context;
1236 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001237 uint32_t Rm; // the register with the target address
1238 switch (encoding) {
1239 case eEncodingT1:
1240 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001241 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001242 return false;
1243 break;
1244 case eEncodingA1:
1245 Rm = Bits32(opcode, 3, 0);
1246 break;
1247 default:
1248 return false;
1249 }
1250 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1251 if (!success)
1252 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001253
1254 Register dwarf_reg;
1255 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1256 if (!BXWritePC(context, target, dwarf_reg))
Johnny Chenab3b3512011-02-12 00:10:51 +00001257 return false;
1258 }
1259 return true;
1260}
1261
Johnny Chen0d0148e2011-01-28 02:26:08 +00001262// Set r7 to point to some ip offset.
1263// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001264bool
1265EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001266{
1267#if 0
1268 // ARM pseudo code...
1269 if (ConditionPassed())
1270 {
1271 EncodingSpecificOperations();
1272 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1273 if d == 15 then // Can only occur for ARM encoding
1274 ALUWritePC(result); // setflags is always FALSE here
1275 else
1276 R[d] = result;
1277 if setflags then
1278 APSR.N = result<31>;
1279 APSR.Z = IsZeroBit(result);
1280 APSR.C = carry;
1281 APSR.V = overflow;
1282 }
1283#endif
1284
1285 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001286 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001287 if (!success)
1288 return false;
1289
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001290 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001291 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001292 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001293 if (!success)
1294 return false;
1295 uint32_t imm32;
1296 switch (encoding) {
1297 case eEncodingA1:
1298 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1299 break;
1300 default:
1301 return false;
1302 }
1303 addr_t ip_offset = imm32;
1304 addr_t addr = ip - ip_offset; // the adjusted ip value
1305
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001306 EmulateInstruction::Context context;
1307 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1308 Register dwarf_reg;
1309 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1310 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001311
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001312 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001313 return false;
1314 }
1315 return true;
1316}
1317
1318// Set ip to point to some stack offset.
1319// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001320bool
1321EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001322{
1323#if 0
1324 // ARM pseudo code...
1325 if (ConditionPassed())
1326 {
1327 EncodingSpecificOperations();
1328 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1329 if d == 15 then // Can only occur for ARM encoding
1330 ALUWritePC(result); // setflags is always FALSE here
1331 else
1332 R[d] = result;
1333 if setflags then
1334 APSR.N = result<31>;
1335 APSR.Z = IsZeroBit(result);
1336 APSR.C = carry;
1337 APSR.V = overflow;
1338 }
1339#endif
1340
1341 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001342 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001343 if (!success)
1344 return false;
1345
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001346 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001348 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001349 if (!success)
1350 return false;
1351 uint32_t imm32;
1352 switch (encoding) {
1353 case eEncodingA1:
1354 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1355 break;
1356 default:
1357 return false;
1358 }
1359 addr_t sp_offset = imm32;
1360 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1361
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001362 EmulateInstruction::Context context;
1363 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1364 Register dwarf_reg;
1365 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1366 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001367
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001369 return false;
1370 }
1371 return true;
1372}
1373
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001374// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001375bool
1376EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001377{
1378#if 0
1379 // ARM pseudo code...
1380 if (ConditionPassed())
1381 {
1382 EncodingSpecificOperations();
1383 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1384 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001385 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001386 else
1387 R[d] = result;
1388 if setflags then
1389 APSR.N = result<31>;
1390 APSR.Z = IsZeroBit(result);
1391 APSR.C = carry;
1392 APSR.V = overflow;
1393 }
1394#endif
1395
1396 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001397 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001398 if (!success)
1399 return false;
1400
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001401 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001402 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001403 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001404 if (!success)
1405 return false;
1406 uint32_t imm32;
1407 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001408 case eEncodingT1:
1409 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001410 case eEncodingT2:
1411 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1412 break;
1413 case eEncodingT3:
1414 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1415 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001417 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001418 break;
1419 default:
1420 return false;
1421 }
1422 addr_t sp_offset = imm32;
1423 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1424
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001425 EmulateInstruction::Context context;
1426 context.type = EmulateInstruction::eContextAdjustStackPointer;
1427 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001428
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001429 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001430 return false;
1431 }
1432 return true;
1433}
1434
Johnny Chen08c25e82011-01-31 18:02:28 +00001435// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001436bool
1437EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001438{
1439#if 0
1440 // ARM pseudo code...
1441 if (ConditionPassed())
1442 {
1443 EncodingSpecificOperations();
1444 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1445 address = if index then offset_addr else R[n];
1446 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1447 if wback then R[n] = offset_addr;
1448 }
1449#endif
1450
1451 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001452 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001453 if (!success)
1454 return false;
1455
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001456 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001457 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001458 const uint32_t addr_byte_size = GetAddressByteSize();
1459 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001460 if (!success)
1461 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001462 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001463 uint32_t imm12;
1464 switch (encoding) {
1465 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001466 Rt = Bits32(opcode, 15, 12);
1467 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001468 break;
1469 default:
1470 return false;
1471 }
1472 addr_t sp_offset = imm12;
1473 addr_t addr = sp - sp_offset;
1474
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001475 EmulateInstruction::Context context;
1476 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1477 Register dwarf_reg;
1478 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001479 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001480 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001481 dwarf_reg.num = dwarf_r0 + Rt;
1482 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1483 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001484 if (!success)
1485 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001486 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001487 return false;
1488 }
1489 else
1490 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001491 dwarf_reg.num = dwarf_pc;
1492 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001493 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001494 if (!success)
1495 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001496 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001497 return false;
1498 }
1499
1500 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001501 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001502
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001503 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001504 return false;
1505 }
1506 return true;
1507}
1508
Johnny Chen08c25e82011-01-31 18:02:28 +00001509// Vector Push stores multiple extension registers to the stack.
1510// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001511bool
1512EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001513{
1514#if 0
1515 // ARM pseudo code...
1516 if (ConditionPassed())
1517 {
1518 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1519 address = SP - imm32;
1520 SP = SP - imm32;
1521 if single_regs then
1522 for r = 0 to regs-1
1523 MemA[address,4] = S[d+r]; address = address+4;
1524 else
1525 for r = 0 to regs-1
1526 // Store as two word-aligned words in the correct order for current endianness.
1527 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1528 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1529 address = address+8;
1530 }
1531#endif
1532
1533 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001534 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001535 if (!success)
1536 return false;
1537
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001538 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001539 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001540 const uint32_t addr_byte_size = GetAddressByteSize();
1541 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001542 if (!success)
1543 return false;
1544 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001545 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001546 uint32_t imm32; // stack offset
1547 uint32_t regs; // number of registers
1548 switch (encoding) {
1549 case eEncodingT1:
1550 case eEncodingA1:
1551 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001552 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001553 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1554 // If UInt(imm8) is odd, see "FSTMX".
1555 regs = Bits32(opcode, 7, 0) / 2;
1556 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1557 if (regs == 0 || regs > 16 || (d + regs) > 32)
1558 return false;
1559 break;
1560 case eEncodingT2:
1561 case eEncodingA2:
1562 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001563 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001564 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1565 regs = Bits32(opcode, 7, 0);
1566 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1567 if (regs == 0 || regs > 16 || (d + regs) > 32)
1568 return false;
1569 break;
1570 default:
1571 return false;
1572 }
1573 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1574 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1575 addr_t sp_offset = imm32;
1576 addr_t addr = sp - sp_offset;
1577 uint32_t i;
1578
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001579 EmulateInstruction::Context context;
1580 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1581 Register dwarf_reg;
1582 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001583 for (i=d; i<regs; ++i)
1584 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001585 dwarf_reg.num = start_reg + i;
1586 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001587 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001588 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001589 if (!success)
1590 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001591 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001592 return false;
1593 addr += reg_byte_size;
1594 }
1595
1596 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001597 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001598
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001599 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001600 return false;
1601 }
1602 return true;
1603}
1604
Johnny Chen587a0a42011-02-01 18:35:28 +00001605// Vector Pop loads multiple extension registers from the stack.
1606// It also updates SP to point just above the loaded data.
1607bool
1608EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1609{
1610#if 0
1611 // ARM pseudo code...
1612 if (ConditionPassed())
1613 {
1614 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1615 address = SP;
1616 SP = SP + imm32;
1617 if single_regs then
1618 for r = 0 to regs-1
1619 S[d+r] = MemA[address,4]; address = address+4;
1620 else
1621 for r = 0 to regs-1
1622 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1623 // Combine the word-aligned words in the correct order for current endianness.
1624 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1625 }
1626#endif
1627
1628 bool success = false;
1629 const uint32_t opcode = OpcodeAsUnsigned (&success);
1630 if (!success)
1631 return false;
1632
1633 if (ConditionPassed())
1634 {
1635 const uint32_t addr_byte_size = GetAddressByteSize();
1636 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1637 if (!success)
1638 return false;
1639 bool single_regs;
1640 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1641 uint32_t imm32; // stack offset
1642 uint32_t regs; // number of registers
1643 switch (encoding) {
1644 case eEncodingT1:
1645 case eEncodingA1:
1646 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001647 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001648 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1649 // If UInt(imm8) is odd, see "FLDMX".
1650 regs = Bits32(opcode, 7, 0) / 2;
1651 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1652 if (regs == 0 || regs > 16 || (d + regs) > 32)
1653 return false;
1654 break;
1655 case eEncodingT2:
1656 case eEncodingA2:
1657 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001658 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001659 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1660 regs = Bits32(opcode, 7, 0);
1661 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1662 if (regs == 0 || regs > 16 || (d + regs) > 32)
1663 return false;
1664 break;
1665 default:
1666 return false;
1667 }
1668 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1669 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1670 addr_t sp_offset = imm32;
1671 addr_t addr = sp;
1672 uint32_t i;
1673 uint64_t data; // uint64_t to accomodate 64-bit registers.
1674
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001675 EmulateInstruction::Context context;
1676 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1677 Register dwarf_reg;
1678 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001679 for (i=d; i<regs; ++i)
1680 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001681 dwarf_reg.num = start_reg + i;
1682 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chen587a0a42011-02-01 18:35:28 +00001683 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1684 if (!success)
1685 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001686 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001687 return false;
1688 addr += reg_byte_size;
1689 }
1690
1691 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001692 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001693
1694 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1695 return false;
1696 }
1697 return true;
1698}
1699
Johnny Chenb77be412011-02-04 00:40:18 +00001700// SVC (previously SWI)
1701bool
1702EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1703{
1704#if 0
1705 // ARM pseudo code...
1706 if (ConditionPassed())
1707 {
1708 EncodingSpecificOperations();
1709 CallSupervisor();
1710 }
1711#endif
1712
1713 bool success = false;
1714 const uint32_t opcode = OpcodeAsUnsigned (&success);
1715 if (!success)
1716 return false;
1717
1718 if (ConditionPassed())
1719 {
1720 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1721 addr_t lr; // next instruction address
1722 if (!success)
1723 return false;
1724 uint32_t imm32; // the immediate constant
1725 uint32_t mode; // ARM or Thumb mode
1726 switch (encoding) {
1727 case eEncodingT1:
1728 lr = (pc + 2) | 1u; // return address
1729 imm32 = Bits32(opcode, 7, 0);
1730 mode = eModeThumb;
1731 break;
1732 case eEncodingA1:
1733 lr = pc + 4; // return address
1734 imm32 = Bits32(opcode, 23, 0);
1735 mode = eModeARM;
1736 break;
1737 default:
1738 return false;
1739 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001740
1741 EmulateInstruction::Context context;
1742 context.type = EmulateInstruction::eContextSupervisorCall;
1743 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001744 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1745 return false;
1746 }
1747 return true;
1748}
1749
Johnny Chenc315f862011-02-05 00:46:10 +00001750// If Then makes up to four following instructions (the IT block) conditional.
1751bool
1752EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1753{
1754#if 0
1755 // ARM pseudo code...
1756 EncodingSpecificOperations();
1757 ITSTATE.IT<7:0> = firstcond:mask;
1758#endif
1759
1760 bool success = false;
1761 const uint32_t opcode = OpcodeAsUnsigned (&success);
1762 if (!success)
1763 return false;
1764
1765 m_it_session.InitIT(Bits32(opcode, 7, 0));
1766 return true;
1767}
1768
Johnny Chen3b620b32011-02-07 20:11:47 +00001769// Branch causes a branch to a target address.
1770bool
1771EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1772{
1773#if 0
1774 // ARM pseudo code...
1775 if (ConditionPassed())
1776 {
1777 EncodingSpecificOperations();
1778 BranchWritePC(PC + imm32);
1779 }
1780#endif
1781
1782 bool success = false;
1783 const uint32_t opcode = OpcodeAsUnsigned (&success);
1784 if (!success)
1785 return false;
1786
Johnny Chen9ee056b2011-02-08 00:06:35 +00001787 if (ConditionPassed())
1788 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001789 EmulateInstruction::Context context;
1790 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001791 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001792 if (!success)
1793 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001794 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001795 int32_t imm32; // PC-relative offset
1796 switch (encoding) {
1797 case eEncodingT1:
1798 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1799 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1800 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001801 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001802 break;
1803 case eEncodingT2:
1804 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1805 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001806 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001807 break;
1808 case eEncodingT3:
1809 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1810 {
Johnny Chenbd599902011-02-10 21:39:01 +00001811 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001812 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001813 uint32_t J1 = Bit32(opcode, 13);
1814 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001815 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001816 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001817 imm32 = llvm::SignExtend32<21>(imm21);
1818 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001819 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001820 break;
1821 }
1822 case eEncodingT4:
1823 {
Johnny Chenbd599902011-02-10 21:39:01 +00001824 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001825 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001826 uint32_t J1 = Bit32(opcode, 13);
1827 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001828 uint32_t imm11 = Bits32(opcode, 10, 0);
1829 uint32_t I1 = !(J1 ^ S);
1830 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001831 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001832 imm32 = llvm::SignExtend32<25>(imm25);
1833 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001834 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001835 break;
1836 }
1837 case eEncodingA1:
1838 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1839 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001840 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001841 break;
1842 default:
1843 return false;
1844 }
1845 if (!BranchWritePC(context, target))
1846 return false;
1847 }
1848 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001849}
1850
Johnny Chen53ebab72011-02-08 23:21:57 +00001851// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1852// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1853// CBNZ, CBZ
1854bool
1855EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1856{
1857#if 0
1858 // ARM pseudo code...
1859 EncodingSpecificOperations();
1860 if nonzero ^ IsZero(R[n]) then
1861 BranchWritePC(PC + imm32);
1862#endif
1863
1864 bool success = false;
1865 const uint32_t opcode = OpcodeAsUnsigned (&success);
1866 if (!success)
1867 return false;
1868
1869 // Read the register value from the operand register Rn.
1870 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1871 if (!success)
1872 return false;
1873
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001874 EmulateInstruction::Context context;
1875 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001876 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1877 if (!success)
1878 return false;
1879
1880 addr_t target; // target address
1881 uint32_t imm32; // PC-relative offset to branch forward
1882 bool nonzero;
1883 switch (encoding) {
1884 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001885 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001886 nonzero = BitIsSet(opcode, 11);
1887 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001888 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001889 break;
1890 default:
1891 return false;
1892 }
1893 if (nonzero ^ (reg_val == 0))
1894 if (!BranchWritePC(context, target))
1895 return false;
1896
1897 return true;
1898}
1899
Johnny Chen26863dc2011-02-09 23:43:29 +00001900// ADD <Rdn>, <Rm>
1901// where <Rdn> the destination register is also the first operand register
1902// and <Rm> is the second operand register.
1903bool
1904EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1905{
1906#if 0
1907 // ARM pseudo code...
1908 if ConditionPassed() then
1909 EncodingSpecificOperations();
1910 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1911 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1912 if d == 15 then
1913 ALUWritePC(result); // setflags is always FALSE here
1914 else
1915 R[d] = result;
1916 if setflags then
1917 APSR.N = result<31>;
1918 APSR.Z = IsZeroBit(result);
1919 APSR.C = carry;
1920 APSR.V = overflow;
1921#endif
1922
1923 bool success = false;
1924 const uint32_t opcode = OpcodeAsUnsigned (&success);
1925 if (!success)
1926 return false;
1927
1928 if (ConditionPassed())
1929 {
1930 uint32_t Rd, Rn, Rm;
1931 //bool setflags = false;
1932 switch (encoding)
1933 {
1934 case eEncodingT2:
1935 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001936 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001937 Rm = Bits32(opcode, 6, 3);
1938 if (Rn == 15 && Rm == 15)
1939 return false;
1940 break;
1941 default:
1942 return false;
1943 }
1944
1945 int32_t result, val1, val2;
1946 // Read the first operand.
1947 if (Rn == 15)
1948 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1949 else
1950 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1951 if (!success)
1952 return false;
1953
1954 // Read the second operand.
1955 if (Rm == 15)
1956 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1957 else
1958 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1959 if (!success)
1960 return false;
1961
1962 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001963
1964 EmulateInstruction::Context context;
1965 context.type = EmulateInstruction::eContextImmediate;
1966 context.SetNoArgs ();
1967 Register dummy_reg;
1968 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001969
1970 if (Rd == 15)
1971 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001972 if (!ALUWritePC (context, result, dummy_reg))
Johnny Chen26863dc2011-02-09 23:43:29 +00001973 return false;
1974 }
1975 else
1976 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001977 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001978 return false;
1979 }
1980 }
1981 return true;
1982}
1983
Johnny Chene4a4d302011-02-11 21:53:58 +00001984// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001985bool
1986EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1987{
1988#if 0
1989 // ARM pseudo code...
1990 if ConditionPassed() then
1991 EncodingSpecificOperations();
1992 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1993 APSR.N = result<31>;
1994 APSR.Z = IsZeroBit(result);
1995 APSR.C = carry;
1996 APSR.V = overflow;
1997#endif
1998
1999 bool success = false;
2000 const uint32_t opcode = OpcodeAsUnsigned (&success);
2001 if (!success)
2002 return false;
2003
2004 uint32_t Rn; // the first operand
2005 uint32_t imm32; // the immediate value to be compared with
2006 switch (encoding) {
2007 case eEncodingT1:
2008 Rn = Bits32(opcode, 10, 8);
2009 imm32 = Bits32(opcode, 7, 0);
2010 break;
2011 default:
2012 return false;
2013 }
2014 // Read the register value from the operand register Rn.
2015 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2016 if (!success)
2017 return false;
2018
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002019 EmulateInstruction::Context context;
2020 context.type = EmulateInstruction::eContextImmediate;
2021 context.SetNoArgs ();
2022
Johnny Chend4dc4442011-02-11 02:02:56 +00002023 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2024 m_new_inst_cpsr = m_inst_cpsr;
2025 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2026 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2027 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2028 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2029 if (m_new_inst_cpsr != m_inst_cpsr)
2030 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002031 EmulateInstruction::Context context;
2032 context.type = EmulateInstruction::eContextImmediate;
2033 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002034 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2035 return false;
2036 }
2037 return true;
2038}
2039
Johnny Chene4a4d302011-02-11 21:53:58 +00002040// CMP (register)
2041bool
2042EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2043{
2044#if 0
2045 // ARM pseudo code...
2046 if ConditionPassed() then
2047 EncodingSpecificOperations();
2048 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2049 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2050 APSR.N = result<31>;
2051 APSR.Z = IsZeroBit(result);
2052 APSR.C = carry;
2053 APSR.V = overflow;
2054#endif
2055
2056 bool success = false;
2057 const uint32_t opcode = OpcodeAsUnsigned (&success);
2058 if (!success)
2059 return false;
2060
2061 uint32_t Rn; // the first operand
2062 uint32_t Rm; // the second operand
2063 switch (encoding) {
2064 case eEncodingT1:
2065 Rn = Bits32(opcode, 2, 0);
2066 Rm = Bits32(opcode, 5, 3);
2067 break;
2068 case eEncodingT2:
2069 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2070 Rm = Bits32(opcode, 6, 3);
2071 if (Rn < 8 && Rm < 8)
2072 return false;
2073 if (Rn == 15 || Rm == 15)
2074 return false;
2075 break;
2076 default:
2077 return false;
2078 }
2079 // Read the register value from register Rn.
2080 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2081 if (!success)
2082 return false;
2083 // Read the register value from register Rm.
2084 // The register value is not being shifted since we don't handle ARM for now.
2085 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2086 if (!success)
2087 return false;
2088
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002089 EmulateInstruction::Context context;
2090 context.type = EmulateInstruction::eContextImmediate;
2091 context.SetNoArgs();
2092
Johnny Chene4a4d302011-02-11 21:53:58 +00002093 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2094 m_new_inst_cpsr = m_inst_cpsr;
2095 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2096 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2097 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2098 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2099 if (m_new_inst_cpsr != m_inst_cpsr)
2100 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002101 EmulateInstruction::Context context;
2102 context.type = EmulateInstruction::eContextImmediate;
2103 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002104 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2105 return false;
2106 }
2107 return true;
2108}
2109
Johnny Chen82f16aa2011-02-15 20:10:55 +00002110// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2111// shifting in copies of its sign bit, and writes the result to the destination register. It can
2112// optionally update the condition flags based on the result.
2113bool
2114EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2115{
2116#if 0
2117 // ARM pseudo code...
2118 if ConditionPassed() then
2119 EncodingSpecificOperations();
2120 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2121 if d == 15 then // Can only occur for ARM encoding
2122 ALUWritePC(result); // setflags is always FALSE here
2123 else
2124 R[d] = result;
2125 if setflags then
2126 APSR.N = result<31>;
2127 APSR.Z = IsZeroBit(result);
2128 APSR.C = carry;
2129 // APSR.V unchanged
2130#endif
2131
2132 bool success = false;
2133 const uint32_t opcode = OpcodeAsUnsigned (&success);
2134 if (!success)
2135 return false;
2136
2137 if (ConditionPassed())
2138 {
2139 uint32_t Rd; // the destination register
2140 uint32_t Rm; // the first operand register
2141 uint32_t imm5; // encoding for the shift amount
2142 uint32_t carry; // the carry bit after the shift operation
2143 bool setflags;
2144 switch (encoding) {
2145 case eEncodingT1:
2146 Rd = Bits32(opcode, 2, 0);
2147 Rm = Bits32(opcode, 5, 3);
2148 setflags = !InITBlock();
2149 imm5 = Bits32(opcode, 10, 6);
2150 break;
2151 case eEncodingT2:
2152 Rd = Bits32(opcode, 11, 8);
2153 Rm = Bits32(opcode, 3, 0);
2154 setflags = BitIsSet(opcode, 20);
2155 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2156 if (BadReg(Rd) || BadReg(Rm))
2157 return false;
2158 break;
2159 case eEncodingA1:
2160 Rd = Bits32(opcode, 15, 12);
2161 Rm = Bits32(opcode, 3, 0);
2162 setflags = BitIsSet(opcode, 20);
2163 imm5 = Bits32(opcode, 11, 7);
2164 break;
2165 default:
2166 return false;
2167 }
2168
2169 // Get the first operand.
2170 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2171 if (!success)
2172 return false;
2173
2174 // Decode the shift amount.
2175 uint32_t amt = DecodeImmShift(SRType_ASR, imm5);
2176
2177 uint32_t result = Shift_C(value, SRType_ASR, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
2178
2179 // The context specifies that an immediate is to be moved into Rd.
2180 EmulateInstruction::Context context;
2181 context.type = EmulateInstruction::eContextImmediate;
2182 context.SetNoArgs ();
2183
2184 Register dummy_reg;
2185 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
2186
2187 if (Rd == 15)
2188 {
2189 if (!ALUWritePC (context, result, dummy_reg))
2190 return false;
2191 }
2192 else
2193 {
2194 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
2195 return false;
2196 if (setflags)
2197 {
2198 m_new_inst_cpsr = m_inst_cpsr;
2199 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
2200 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
2201 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
2202 if (m_new_inst_cpsr != m_inst_cpsr)
2203 {
2204 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2205 return false;
2206 }
2207 }
2208 }
2209 }
2210 return true;
2211}
2212
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002213// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002214// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002215// can be written back to the base register.
2216bool
2217EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2218{
2219#if 0
2220 // ARM pseudo code...
2221 if ConditionPassed()
2222 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2223 address = R[n];
2224
2225 for i = 0 to 14
2226 if registers<i> == '1' then
2227 R[i] = MemA[address, 4]; address = address + 4;
2228 if registers<15> == '1' then
2229 LoadWritePC (MemA[address, 4]);
2230
2231 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2232 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2233
2234#endif
2235
2236 bool success = false;
2237 const uint32_t opcode = OpcodeAsUnsigned (&success);
2238 if (!success)
2239 return false;
2240
2241 if (ConditionPassed())
2242 {
2243 uint32_t n;
2244 uint32_t registers = 0;
2245 bool wback;
2246 const uint32_t addr_byte_size = GetAddressByteSize();
2247 switch (encoding)
2248 {
2249 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002250 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002251 n = Bits32 (opcode, 10, 8);
2252 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002253 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002254 wback = BitIsClear (registers, n);
2255 // if BitCount(registers) < 1 then UNPREDICTABLE;
2256 if (BitCount(registers) < 1)
2257 return false;
2258 break;
2259 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002260 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2261 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002262 n = Bits32 (opcode, 19, 16);
2263 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002264 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002265 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002266
2267 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002268 if ((n == 15)
2269 || (BitCount (registers) < 2)
2270 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2271 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002272
2273 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002274 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002275 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002276
2277 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002278 if (wback
2279 && BitIsSet (registers, n))
2280 return false;
2281 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002282
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002283 case eEncodingA1:
2284 n = Bits32 (opcode, 19, 16);
2285 registers = Bits32 (opcode, 15, 0);
2286 wback = BitIsSet (opcode, 21);
2287 if ((n == 15)
2288 || (BitCount (registers) < 1))
2289 return false;
2290 break;
2291 default:
2292 return false;
2293 }
2294
2295 int32_t offset = 0;
2296 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2297 if (!success)
2298 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002299
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002300 EmulateInstruction::Context context;
2301 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2302 Register dwarf_reg;
2303 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2304 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002305
2306 for (int i = 0; i < 14; ++i)
2307 {
2308 if (BitIsSet (registers, i))
2309 {
Caroline Tice85aab332011-02-08 23:56:10 +00002310 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002311 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002312 if (wback && (n == 13)) // Pop Instruction
2313 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2314
2315 // R[i] = MemA [address, 4]; address = address + 4;
2316 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2317 if (!success)
2318 return false;
2319
2320 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2321 return false;
2322
2323 offset += addr_byte_size;
2324 }
2325 }
2326
2327 if (BitIsSet (registers, 15))
2328 {
2329 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002330 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002331 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002332 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2333 if (!success)
2334 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002335 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002336 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002337 return false;
2338 }
2339
2340 if (wback && BitIsClear (registers, n))
2341 {
Caroline Ticefa172202011-02-11 22:49:54 +00002342 // R[n] = R[n] + 4 * BitCount (registers)
2343 int32_t offset = addr_byte_size * BitCount (registers);
2344 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002345 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002346
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002347 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2348 return false;
2349 }
2350 if (wback && BitIsSet (registers, n))
2351 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002352 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002353 }
2354 return true;
2355}
Caroline Tice713c2662011-02-11 17:59:55 +00002356
2357// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2358// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2359// can optionally be written back tot he base registers.
2360bool
2361EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2362{
2363#if 0
2364 // ARM pseudo code...
2365 if ConditionPassed() then
2366 EncodingSpecificOperations();
2367 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002368
Caroline Tice713c2662011-02-11 17:59:55 +00002369 for i = 0 to 14
2370 if registers<i> == ’1’ then
2371 R[i] = MemA[address,4]; address = address + 4;
2372
2373 if registers<15> == ’1’ then
2374 LoadWritePC(MemA[address,4]);
2375
2376 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2377 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2378#endif
2379
2380 bool success = false;
2381 const uint32_t opcode = OpcodeAsUnsigned (&success);
2382 if (!success)
2383 return false;
2384
2385 if (ConditionPassed())
2386 {
2387 uint32_t n;
2388 uint32_t registers = 0;
2389 bool wback;
2390 const uint32_t addr_byte_size = GetAddressByteSize();
2391
2392 // EncodingSpecificOperations();
2393 switch (encoding)
2394 {
2395 case eEncodingA1:
2396 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2397 n = Bits32 (opcode, 19, 16);
2398 registers = Bits32 (opcode, 15, 0);
2399 wback = BitIsSet (opcode, 21);
2400
2401 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2402 if ((n == 15) || (BitCount (registers) < 1))
2403 return false;
2404
2405 break;
2406
2407 default:
2408 return false;
2409 }
2410 // address = R[n] - 4*BitCount(registers) + 4;
2411
2412 int32_t offset = 0;
2413 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2414
2415 if (!success)
2416 return false;
2417
2418 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2419
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002420 EmulateInstruction::Context context;
2421 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2422 Register dwarf_reg;
2423 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2424 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002425
2426 // for i = 0 to 14
2427 for (int i = 0; i < 14; ++i)
2428 {
2429 // if registers<i> == ’1’ then
2430 if (BitIsSet (registers, i))
2431 {
2432 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002433 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002434 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2435 if (!success)
2436 return false;
2437 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2438 return false;
2439 offset += addr_byte_size;
2440 }
2441 }
2442
2443 // if registers<15> == ’1’ then
2444 // LoadWritePC(MemA[address,4]);
2445 if (BitIsSet (registers, 15))
2446 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002447 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002448 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2449 if (!success)
2450 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002451 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002452 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice713c2662011-02-11 17:59:55 +00002453 return false;
2454 }
2455
2456 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2457 if (wback && BitIsClear (registers, n))
2458 {
Caroline Tice713c2662011-02-11 17:59:55 +00002459 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2460 if (!success)
2461 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002462
2463 offset = (addr_byte_size * BitCount (registers)) * -1;
2464 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002465 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002466 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002467 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2468 return false;
2469 }
2470
2471 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2472 if (wback && BitIsSet (registers, n))
2473 return WriteBits32Unknown (n);
2474 }
2475 return true;
2476}
2477
2478// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2479// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2480// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002481bool
2482EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2483{
2484#if 0
2485 // ARM pseudo code...
2486 if ConditionPassed() then
2487 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2488 address = R[n] - 4*BitCount(registers);
2489
2490 for i = 0 to 14
2491 if registers<i> == ’1’ then
2492 R[i] = MemA[address,4]; address = address + 4;
2493 if registers<15> == ’1’ then
2494 LoadWritePC(MemA[address,4]);
2495
2496 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2497 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2498#endif
2499
2500 bool success = false;
2501 const uint32_t opcode = OpcodeAsUnsigned (&success);
2502 if (!success)
2503 return false;
2504
2505 if (ConditionPassed())
2506 {
2507 uint32_t n;
2508 uint32_t registers = 0;
2509 bool wback;
2510 const uint32_t addr_byte_size = GetAddressByteSize();
2511 switch (encoding)
2512 {
2513 case eEncodingT1:
2514 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2515 n = Bits32 (opcode, 19, 16);
2516 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002517 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002518 wback = BitIsSet (opcode, 21);
2519
2520 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2521 if ((n == 15)
2522 || (BitCount (registers) < 2)
2523 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2524 return false;
2525
2526 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002527 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002528 return false;
2529
2530 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2531 if (wback && BitIsSet (registers, n))
2532 return false;
2533
2534 break;
2535
2536 case eEncodingA1:
2537 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2538 n = Bits32 (opcode, 19, 16);
2539 registers = Bits32 (opcode, 15, 0);
2540 wback = BitIsSet (opcode, 21);
2541
2542 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2543 if ((n == 15) || (BitCount (registers) < 1))
2544 return false;
2545
2546 break;
2547
2548 default:
2549 return false;
2550 }
2551
Caroline Tice713c2662011-02-11 17:59:55 +00002552 // address = R[n] - 4*BitCount(registers);
2553
Caroline Tice0b29e242011-02-08 23:16:02 +00002554 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002555 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2556
2557 if (!success)
2558 return false;
2559
2560 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002561 EmulateInstruction::Context context;
2562 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2563 Register dwarf_reg;
2564 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2565 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002566
2567 for (int i = 0; i < 14; ++i)
2568 {
2569 if (BitIsSet (registers, i))
2570 {
2571 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002572 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002573 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2574 if (!success)
2575 return false;
2576
2577 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2578 return false;
2579
2580 offset += addr_byte_size;
2581 }
2582 }
2583
2584 // if registers<15> == ’1’ then
2585 // LoadWritePC(MemA[address,4]);
2586 if (BitIsSet (registers, 15))
2587 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002588 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002589 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2590 if (!success)
2591 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002592 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002593 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice0b29e242011-02-08 23:16:02 +00002594 return false;
2595 }
2596
2597 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2598 if (wback && BitIsClear (registers, n))
2599 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002600 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2601 if (!success)
2602 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002603
2604 offset = (addr_byte_size * BitCount (registers)) * -1;
2605 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002606 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002607 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2609 return false;
2610 }
2611
2612 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2613 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002614 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002615 }
2616 return true;
2617}
Caroline Tice85aab332011-02-08 23:56:10 +00002618
Caroline Tice713c2662011-02-11 17:59:55 +00002619// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2620// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2621// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002622bool
2623EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2624{
2625#if 0
2626 if ConditionPassed() then
2627 EncodingSpecificOperations();
2628 address = R[n] + 4;
2629
2630 for i = 0 to 14
2631 if registers<i> == ’1’ then
2632 R[i] = MemA[address,4]; address = address + 4;
2633 if registers<15> == ’1’ then
2634 LoadWritePC(MemA[address,4]);
2635
2636 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2637 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2638#endif
2639
2640 bool success = false;
2641 const uint32_t opcode = OpcodeAsUnsigned (&success);
2642 if (!success)
2643 return false;
2644
2645 if (ConditionPassed())
2646 {
2647 uint32_t n;
2648 uint32_t registers = 0;
2649 bool wback;
2650 const uint32_t addr_byte_size = GetAddressByteSize();
2651 switch (encoding)
2652 {
2653 case eEncodingA1:
2654 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2655 n = Bits32 (opcode, 19, 16);
2656 registers = Bits32 (opcode, 15, 0);
2657 wback = BitIsSet (opcode, 21);
2658
2659 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2660 if ((n == 15) || (BitCount (registers) < 1))
2661 return false;
2662
2663 break;
2664 default:
2665 return false;
2666 }
2667 // address = R[n] + 4;
2668
2669 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002670 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2671
2672 if (!success)
2673 return false;
2674
2675 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002676
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002677 EmulateInstruction::Context context;
2678 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2679 Register dwarf_reg;
2680 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2681 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002682
2683 for (int i = 0; i < 14; ++i)
2684 {
2685 if (BitIsSet (registers, i))
2686 {
2687 // R[i] = MemA[address,4]; address = address + 4;
2688
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002689 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002690 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2691 if (!success)
2692 return false;
2693
2694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2695 return false;
2696
2697 offset += addr_byte_size;
2698 }
2699 }
2700
2701 // if registers<15> == ’1’ then
2702 // LoadWritePC(MemA[address,4]);
2703 if (BitIsSet (registers, 15))
2704 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002705 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002706 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2707 if (!success)
2708 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002709 // In ARMv5T and above, this is an interworking branch.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002710 if (!LoadWritePC(context, data, dwarf_reg))
Caroline Tice85aab332011-02-08 23:56:10 +00002711 return false;
2712 }
2713
2714 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2715 if (wback && BitIsClear (registers, n))
2716 {
Caroline Tice85aab332011-02-08 23:56:10 +00002717 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2718 if (!success)
2719 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002720
2721 offset = addr_byte_size * BitCount (registers);
2722 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002723 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002724 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002725 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2726 return false;
2727 }
2728
2729 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2730 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002731 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002732 }
2733 return true;
2734}
Caroline Tice0b29e242011-02-08 23:16:02 +00002735
Johnny Chenef21b592011-02-10 01:52:38 +00002736// Load Register (immediate) calculates an address from a base register value and
2737// an immediate offset, loads a word from memory, and writes to a register.
2738// LDR (immediate, Thumb)
2739bool
2740EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2741{
2742#if 0
2743 // ARM pseudo code...
2744 if (ConditionPassed())
2745 {
2746 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2747 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2748 address = if index then offset_addr else R[n];
2749 data = MemU[address,4];
2750 if wback then R[n] = offset_addr;
2751 if t == 15 then
2752 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2753 elsif UnalignedSupport() || address<1:0> = '00' then
2754 R[t] = data;
2755 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2756 }
2757#endif
2758
2759 bool success = false;
2760 const uint32_t opcode = OpcodeAsUnsigned (&success);
2761 if (!success)
2762 return false;
2763
2764 if (ConditionPassed())
2765 {
2766 uint32_t Rt; // the destination register
2767 uint32_t Rn; // the base register
2768 uint32_t imm32; // the immediate offset used to form the address
2769 addr_t offset_addr; // the offset address
2770 addr_t address; // the calculated address
2771 uint32_t data; // the literal data value from memory load
2772 bool add, index, wback;
2773 switch (encoding) {
2774 case eEncodingT1:
2775 Rt = Bits32(opcode, 5, 3);
2776 Rn = Bits32(opcode, 2, 0);
2777 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2778 // index = TRUE; add = TRUE; wback = FALSE
2779 add = true;
2780 index = true;
2781 wback = false;
2782 break;
2783 default:
2784 return false;
2785 }
2786 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2787 if (!success)
2788 return false;
2789 if (add)
2790 offset_addr = base + imm32;
2791 else
2792 offset_addr = base - imm32;
2793
2794 address = (index ? offset_addr : base);
2795
2796 if (wback)
2797 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002798 EmulateInstruction::Context ctx;
2799 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
2800 Register dwarf_reg;
2801 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2802 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
2803
Johnny Chenef21b592011-02-10 01:52:38 +00002804 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2805 return false;
2806 }
2807
2808 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002809 EmulateInstruction::Context context;
2810 context.type = EmulateInstruction::eContextImmediate;
2811 context.SetNoArgs ();
2812 Register dummy_reg;
2813 dummy_reg.SetRegister (eRegisterKindDWARF, dwarf_r0);
Johnny Chenef21b592011-02-10 01:52:38 +00002814
2815 // Read memory from the address.
2816 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2817 if (!success)
2818 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00002819
2820 if (Rt == 15)
2821 {
2822 if (Bits32(address, 1, 0) == 0)
2823 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002824 if (!LoadWritePC(context, data, dummy_reg))
Johnny Chenef21b592011-02-10 01:52:38 +00002825 return false;
2826 }
2827 else
2828 return false;
2829 }
2830 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2831 {
2832 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2833 return false;
2834 }
2835 else
2836 return false;
2837 }
2838 return true;
2839}
2840
Caroline Ticeaf556562011-02-15 18:42:15 +00002841// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
2842// from a base register. The consecutive memory locations start at this address, and teh address just above the last
2843// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00002844bool
2845EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2846{
2847#if 0
2848 if ConditionPassed() then
2849 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2850 address = R[n];
2851
2852 for i = 0 to 14
2853 if registers<i> == ’1’ then
2854 if i == n && wback && i != LowestSetBit(registers) then
2855 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2856 else
2857 MemA[address,4] = R[i];
2858 address = address + 4;
2859
2860 if registers<15> == ’1’ then // Only possible for encoding A1
2861 MemA[address,4] = PCStoreValue();
2862 if wback then R[n] = R[n] + 4*BitCount(registers);
2863#endif
2864
2865 bool success = false;
2866 const uint32_t opcode = OpcodeAsUnsigned (&success);
2867 if (!success)
2868 return false;
2869
2870 if (ConditionPassed ())
2871 {
2872 uint32_t n;
2873 uint32_t registers = 0;
2874 bool wback;
2875 const uint32_t addr_byte_size = GetAddressByteSize();
2876
2877 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2878 switch (encoding)
2879 {
2880 case eEncodingT1:
2881 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2882 n = Bits32 (opcode, 10, 8);
2883 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002884 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00002885 wback = true;
2886
2887 // if BitCount(registers) < 1 then UNPREDICTABLE;
2888 if (BitCount (registers) < 1)
2889 return false;
2890
2891 break;
2892
2893 case eEncodingT2:
2894 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2895 n = Bits32 (opcode, 19, 16);
2896 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002897 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00002898 wback = BitIsSet (opcode, 21);
2899
2900 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2901 if ((n == 15) || (BitCount (registers) < 2))
2902 return false;
2903
2904 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2905 if (wback && BitIsSet (registers, n))
2906 return false;
2907
2908 break;
2909
2910 case eEncodingA1:
2911 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2912 n = Bits32 (opcode, 19, 16);
2913 registers = Bits32 (opcode, 15, 0);
2914 wback = BitIsSet (opcode, 21);
2915
2916 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2917 if ((n == 15) || (BitCount (registers) < 1))
2918 return false;
2919
2920 break;
2921
2922 default:
2923 return false;
2924 }
2925
2926 // address = R[n];
2927 int32_t offset = 0;
2928 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2929 if (!success)
2930 return false;
2931
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002932 EmulateInstruction::Context context;
2933 context.type = EmulateInstruction::eContextRegisterStore;
2934 Register base_reg;
2935 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00002936
2937 // for i = 0 to 14
2938 for (int i = 0; i < 14; ++i)
2939 {
2940 int lowest_set_bit = 14;
2941 // if registers<i> == ’1’ then
2942 if (BitIsSet (registers, i))
2943 {
2944 if (i < lowest_set_bit)
2945 lowest_set_bit = i;
2946 // if i == n && wback && i != LowestSetBit(registers) then
2947 if ((i == n) && wback && (i != lowest_set_bit))
2948 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2949 WriteBits32UnknownToMemory (address + offset);
2950 else
2951 {
2952 // MemA[address,4] = R[i];
2953 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2954 if (!success)
2955 return false;
2956
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002957 Register data_reg;
2958 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
2959 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002960 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2961 return false;
2962 }
2963
2964 // address = address + 4;
2965 offset += addr_byte_size;
2966 }
2967 }
2968
2969 // if registers<15> == ’1’ then // Only possible for encoding A1
2970 // MemA[address,4] = PCStoreValue();
2971 if (BitIsSet (registers, 15))
2972 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002973 Register pc_reg;
2974 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
2975 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00002976 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2977 if (!success)
2978 return false;
2979
2980 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2981 return false;
2982 }
2983
2984 // if wback then R[n] = R[n] + 4*BitCount(registers);
2985 if (wback)
2986 {
2987 offset = addr_byte_size * BitCount (registers);
2988 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002989 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002990 addr_t data = address + offset;
2991 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2992 return false;
2993 }
2994 }
2995 return true;
2996}
2997
Caroline Ticeaf556562011-02-15 18:42:15 +00002998// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
2999// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3000// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003001bool
3002EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3003{
3004#if 0
3005 if ConditionPassed() then
3006 EncodingSpecificOperations();
3007 address = R[n] - 4*BitCount(registers) + 4;
3008
3009 for i = 0 to 14
3010 if registers<i> == ’1’ then
3011 if i == n && wback && i != LowestSetBit(registers) then
3012 MemA[address,4] = bits(32) UNKNOWN;
3013 else
3014 MemA[address,4] = R[i];
3015 address = address + 4;
3016
3017 if registers<15> == ’1’ then
3018 MemA[address,4] = PCStoreValue();
3019
3020 if wback then R[n] = R[n] - 4*BitCount(registers);
3021#endif
3022
3023 bool success = false;
3024 const uint32_t opcode = OpcodeAsUnsigned (&success);
3025 if (!success)
3026 return false;
3027
3028 if (ConditionPassed ())
3029 {
3030 uint32_t n;
3031 uint32_t registers = 0;
3032 bool wback;
3033 const uint32_t addr_byte_size = GetAddressByteSize();
3034
3035 // EncodingSpecificOperations();
3036 switch (encoding)
3037 {
3038 case eEncodingA1:
3039 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3040 n = Bits32 (opcode, 19, 16);
3041 registers = Bits32 (opcode, 15, 0);
3042 wback = BitIsSet (opcode, 21);
3043
3044 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3045 if ((n == 15) || (BitCount (registers) < 1))
3046 return false;
3047 break;
3048 default:
3049 return false;
3050 }
3051
3052 // address = R[n] - 4*BitCount(registers) + 4;
3053 int32_t offset = 0;
3054 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3055 if (!success)
3056 return false;
3057
3058 address = address - (addr_byte_size * BitCount (registers)) + 4;
3059
3060 EmulateInstruction::Context context;
3061 context.type = EmulateInstruction::eContextRegisterStore;
3062 Register base_reg;
3063 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3064
3065 // for i = 0 to 14
3066 for (int i = 0; i < 14; ++i)
3067 {
3068 int lowest_bit_set = 14;
3069 // if registers<i> == ’1’ then
3070 if (BitIsSet (registers, i))
3071 {
3072 if (i < lowest_bit_set)
3073 lowest_bit_set = i;
3074 //if i == n && wback && i != LowestSetBit(registers) then
3075 if ((i == n) && wback && (i != lowest_bit_set))
3076 // MemA[address,4] = bits(32) UNKNOWN;
3077 WriteBits32UnknownToMemory (address + offset);
3078 else
3079 {
3080 // MemA[address,4] = R[i];
3081 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3082 if (!success)
3083 return false;
3084
3085 Register data_reg;
3086 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3087 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3088 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3089 return false;
3090 }
3091
3092 // address = address + 4;
3093 offset += addr_byte_size;
3094 }
3095 }
3096
3097 // if registers<15> == ’1’ then
3098 // MemA[address,4] = PCStoreValue();
3099 if (BitIsSet (registers, 15))
3100 {
3101 Register pc_reg;
3102 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3103 context.SetRegisterPlusOffset (pc_reg, 8);
3104 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3105 if (!success)
3106 return false;
3107
3108 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3109 return false;
3110 }
3111
3112 // if wback then R[n] = R[n] - 4*BitCount(registers);
3113 if (wback)
3114 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003115 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003116 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3117 context.SetImmediateSigned (offset);
3118 addr_t data = address + offset;
3119 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3120 return false;
3121 }
3122 }
3123 return true;
3124}
3125
Caroline Ticeaf556562011-02-15 18:42:15 +00003126// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3127// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3128// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003129bool
3130EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3131{
3132#if 0
3133 if ConditionPassed() then
3134 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3135 address = R[n] - 4*BitCount(registers);
3136
3137 for i = 0 to 14
3138 if registers<i> == ’1’ then
3139 if i == n && wback && i != LowestSetBit(registers) then
3140 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3141 else
3142 MemA[address,4] = R[i];
3143 address = address + 4;
3144
3145 if registers<15> == ’1’ then // Only possible for encoding A1
3146 MemA[address,4] = PCStoreValue();
3147
3148 if wback then R[n] = R[n] - 4*BitCount(registers);
3149#endif
3150
3151
3152 bool success = false;
3153 const uint32_t opcode = OpcodeAsUnsigned (&success);
3154 if (!success)
3155 return false;
3156
3157 if (ConditionPassed ())
3158 {
3159 uint32_t n;
3160 uint32_t registers = 0;
3161 bool wback;
3162 const uint32_t addr_byte_size = GetAddressByteSize();
3163
3164 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3165 switch (encoding)
3166 {
3167 case eEncodingT1:
3168 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3169 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3170 {
3171 // See PUSH
3172 }
3173 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3174 n = Bits32 (opcode, 19, 16);
3175 registers = Bits32 (opcode, 15, 0);
3176 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3177 wback = BitIsSet (opcode, 21);
3178 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3179 if ((n == 15) || BitCount (registers) < 2)
3180 return false;
3181 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3182 if (wback && BitIsSet (registers, n))
3183 return false;
3184 break;
3185
3186 case eEncodingA1:
3187 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3188 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3189 {
3190 // See Push
3191 }
3192 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3193 n = Bits32 (opcode, 19, 16);
3194 registers = Bits32 (opcode, 15, 0);
3195 wback = BitIsSet (opcode, 21);
3196 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3197 if ((n == 15) || BitCount (registers) < 1)
3198 return false;
3199 break;
3200
3201 default:
3202 return false;
3203 }
3204
3205 // address = R[n] - 4*BitCount(registers);
3206
3207 int32_t offset = 0;
3208 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3209 if (!success)
3210 return false;
3211
3212 address = address - (addr_byte_size * BitCount (registers));
3213
3214 EmulateInstruction::Context context;
3215 context.type = EmulateInstruction::eContextRegisterStore;
3216 Register base_reg;
3217 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3218
3219 // for i = 0 to 14
3220 for (int i = 0; i < 14; ++i)
3221 {
3222 uint32_t lowest_set_bit = 14;
3223 // if registers<i> == ’1’ then
3224 if (BitIsSet (registers, i))
3225 {
3226 if (i < lowest_set_bit)
3227 lowest_set_bit = i;
3228 // if i == n && wback && i != LowestSetBit(registers) then
3229 if ((i == n) && wback && (i != lowest_set_bit))
3230 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3231 WriteBits32UnknownToMemory (address + offset);
3232 else
3233 {
3234 // MemA[address,4] = R[i];
3235 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3236 if (!success)
3237 return false;
3238
3239 Register data_reg;
3240 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3241 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3242 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3243 return false;
3244 }
3245
3246 // address = address + 4;
3247 offset += addr_byte_size;
3248 }
3249 }
3250
3251 // if registers<15> == ’1’ then // Only possible for encoding A1
3252 // MemA[address,4] = PCStoreValue();
3253 if (BitIsSet (registers, 15))
3254 {
3255 Register pc_reg;
3256 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3257 context.SetRegisterPlusOffset (pc_reg, 8);
3258 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3259 if (!success)
3260 return false;
3261
3262 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3263 return false;
3264 }
3265
3266 // if wback then R[n] = R[n] - 4*BitCount(registers);
3267 if (wback)
3268 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003269 offset = (addr_byte_size * BitCount (registers)) * -1;
3270 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3271 context.SetImmediateSigned (offset);
3272 addr_t data = address + offset;
3273 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3274 return false;
3275 }
3276 }
3277 return true;
3278}
3279
3280// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3281// from a base register. The consecutive memory locations start just above this address, and the address of the last
3282// of those locations can optionally be written back to the base register.
3283bool
3284EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3285{
3286#if 0
3287 if ConditionPassed() then
3288 EncodingSpecificOperations();
3289 address = R[n] + 4;
3290
3291 for i = 0 to 14
3292 if registers<i> == ’1’ then
3293 if i == n && wback && i != LowestSetBit(registers) then
3294 MemA[address,4] = bits(32) UNKNOWN;
3295 else
3296 MemA[address,4] = R[i];
3297 address = address + 4;
3298
3299 if registers<15> == ’1’ then
3300 MemA[address,4] = PCStoreValue();
3301
3302 if wback then R[n] = R[n] + 4*BitCount(registers);
3303#endif
3304
3305 bool success = false;
3306 const uint32_t opcode = OpcodeAsUnsigned (&success);
3307 if (!success)
3308 return false;
3309
3310 if (ConditionPassed())
3311 {
3312 uint32_t n;
3313 uint32_t registers = 0;
3314 bool wback;
3315 const uint32_t addr_byte_size = GetAddressByteSize();
3316
3317 // EncodingSpecificOperations();
3318 switch (encoding)
3319 {
3320 case eEncodingA1:
3321 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3322 n = Bits32 (opcode, 19, 16);
3323 registers = Bits32 (opcode, 15, 0);
3324 wback = BitIsSet (opcode, 21);
3325
3326 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3327 if ((n == 15) && (BitCount (registers) < 1))
3328 return false;
3329 break;
3330 default:
3331 return false;
3332 }
3333 // address = R[n] + 4;
3334
3335 int32_t offset = 0;
3336 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3337 if (!success)
3338 return false;
3339
3340 address = address + addr_byte_size;
3341
3342 EmulateInstruction::Context context;
3343 context.type = EmulateInstruction::eContextRegisterStore;
3344 Register base_reg;
3345 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3346
3347 uint32_t lowest_set_bit = 14;
3348 // for i = 0 to 14
3349 for (int i = 0; i < 14; ++i)
3350 {
3351 // if registers<i> == ’1’ then
3352 if (BitIsSet (registers, i))
3353 {
3354 if (i < lowest_set_bit)
3355 lowest_set_bit = i;
3356 // if i == n && wback && i != LowestSetBit(registers) then
3357 if ((i == n) && wback && (i != lowest_set_bit))
3358 // MemA[address,4] = bits(32) UNKNOWN;
3359 WriteBits32UnknownToMemory (address + offset);
3360 // else
3361 else
3362 {
3363 // MemA[address,4] = R[i];
3364 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3365 if (!success)
3366 return false;
3367
3368 Register data_reg;
3369 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3370 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3371 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3372 return false;
3373 }
3374
3375 // address = address + 4;
3376 offset += addr_byte_size;
3377 }
3378 }
3379
3380 // if registers<15> == ’1’ then
3381 // MemA[address,4] = PCStoreValue();
3382 if (BitIsSet (registers, 15))
3383 {
3384 Register pc_reg;
3385 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3386 context.SetRegisterPlusOffset (pc_reg, 8);
3387 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3388 if (!success)
3389 return false;
3390
3391 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3392 return false;
3393 }
3394
3395 // if wback then R[n] = R[n] + 4*BitCount(registers);
3396 if (wback)
3397 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003398 offset = addr_byte_size * BitCount (registers);
3399 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3400 context.SetImmediateSigned (offset);
3401 addr_t data = address + offset;
3402 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3403 return false;
3404 }
3405 }
3406 return true;
3407}
3408
Caroline Ticeaf556562011-02-15 18:42:15 +00003409
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003410EmulateInstructionARM::ARMOpcode*
3411EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00003412{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003413 static ARMOpcode
3414 g_arm_opcodes[] =
3415 {
3416 //----------------------------------------------------------------------
3417 // Prologue instructions
3418 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00003419
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003420 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00003421 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
3422 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00003423
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003424 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00003425 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
3426 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00003427 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00003428 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
3429 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
3430 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00003431
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003432 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00003433 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00003434
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003435 // push one register
3436 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00003437 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00003438
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003439 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00003440 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3441 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00003442
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003443 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00003444 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003445 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00003446
Johnny Chenc28a76d2011-02-01 18:51:48 +00003447 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
3448 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00003449 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003450 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
3451
3452 //----------------------------------------------------------------------
3453 // Supervisor Call (previously Software Interrupt)
3454 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00003455 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
3456
3457 //----------------------------------------------------------------------
3458 // Branch instructions
3459 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003460 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00003461 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
3462 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3463 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3464 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003465 // for example, "bx lr"
3466 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003467
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003468 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00003469 // Data-processing instructions
3470 //----------------------------------------------------------------------
3471 // move bitwise not
3472 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00003473 // asr (immediate)
3474 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen28070c32011-02-12 01:27:26 +00003475
3476 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003477 // Load instructions
3478 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00003479 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00003480 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00003481 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00003482 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
3483
3484 //----------------------------------------------------------------------
3485 // Store instructions
3486 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00003487 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003488 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00003489 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
3490 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }
Caroline Tice1511f502011-02-15 00:19:42 +00003491
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003492
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003493 };
3494 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
3495
3496 for (size_t i=0; i<k_num_arm_opcodes; ++i)
3497 {
3498 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
3499 return &g_arm_opcodes[i];
3500 }
3501 return NULL;
3502}
Greg Clayton64c84432011-01-21 22:02:52 +00003503
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003504
3505EmulateInstructionARM::ARMOpcode*
3506EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00003507{
Johnny Chenfdd179e2011-01-31 20:09:28 +00003508
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003509 static ARMOpcode
3510 g_thumb_opcodes[] =
3511 {
3512 //----------------------------------------------------------------------
3513 // Prologue instructions
3514 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00003515
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003516 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00003517 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00003518 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
3519 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00003520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003521 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00003522 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00003523 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00003524 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00003525 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
3526 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00003527
Johnny Chenc9de9102011-02-11 19:12:30 +00003528 // PC-relative load into register (see also EmulateAddSPRm)
3529 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00003530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003531 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00003532 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
3533 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003534 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
3535 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003536
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003537 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00003538 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3539 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00003540
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003541 //----------------------------------------------------------------------
3542 // Epilogue instructions
3543 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00003544
Johnny Chenc28a76d2011-02-01 18:51:48 +00003545 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
3546 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00003547 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
3548 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
3549 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
3550 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00003551
3552 //----------------------------------------------------------------------
3553 // Supervisor Call (previously Software Interrupt)
3554 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00003555 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
3556
3557 //----------------------------------------------------------------------
3558 // If Then makes up to four following instructions conditional.
3559 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00003560 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
3561
3562 //----------------------------------------------------------------------
3563 // Branch instructions
3564 //----------------------------------------------------------------------
3565 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
3566 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
3567 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00003568 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003569 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00003570 // J1 == J2 == 1
3571 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3572 // J1 == J2 == 1
3573 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3574 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003575 // for example, "bx lr"
3576 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00003577 // compare and branch
3578 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003579
3580 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00003581 // Data-processing instructions
3582 //----------------------------------------------------------------------
3583 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
3584 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00003585 // move from high register to high register
3586 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
3587 // move from low register to low register
3588 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00003589 // move immediate
3590 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
3591 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00003592 // move bitwise not
3593 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00003594 // compare a register with immediate
3595 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00003596 // compare Rn with Rm (Rn and Rm both from r0-r7)
3597 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
3598 // compare Rn with Rm (Rn and Rm not both from r0-r7)
3599 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00003600 // asr (immediate)
3601 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
3602 { 0x0fef0070, 0x01a00040, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen26863dc2011-02-09 23:43:29 +00003603
3604 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003605 // Load instructions
3606 //----------------------------------------------------------------------
3607 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00003608 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00003609 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00003610 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
3611 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00003612 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
3613
3614 //----------------------------------------------------------------------
3615 // Store instructions
3616 //----------------------------------------------------------------------
3617 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003618 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
3619 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003620
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003621 };
3622
3623 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
3624 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
3625 {
3626 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
3627 return &g_thumb_opcodes[i];
3628 }
3629 return NULL;
3630}
Greg Clayton64c84432011-01-21 22:02:52 +00003631
Greg Clayton31e2a382011-01-30 20:03:56 +00003632bool
3633EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
3634{
3635 m_arm_isa = 0;
3636 const char *triple_cstr = triple.GetCString();
3637 if (triple_cstr)
3638 {
3639 const char *dash = ::strchr (triple_cstr, '-');
3640 if (dash)
3641 {
3642 std::string arch (triple_cstr, dash);
3643 const char *arch_cstr = arch.c_str();
3644 if (strcasecmp(arch_cstr, "armv4t") == 0)
3645 m_arm_isa = ARMv4T;
3646 else if (strcasecmp(arch_cstr, "armv4") == 0)
3647 m_arm_isa = ARMv4;
3648 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
3649 m_arm_isa = ARMv5TEJ;
3650 else if (strcasecmp(arch_cstr, "armv5te") == 0)
3651 m_arm_isa = ARMv5TE;
3652 else if (strcasecmp(arch_cstr, "armv5t") == 0)
3653 m_arm_isa = ARMv5T;
3654 else if (strcasecmp(arch_cstr, "armv6k") == 0)
3655 m_arm_isa = ARMv6K;
3656 else if (strcasecmp(arch_cstr, "armv6") == 0)
3657 m_arm_isa = ARMv6;
3658 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
3659 m_arm_isa = ARMv6T2;
3660 else if (strcasecmp(arch_cstr, "armv7") == 0)
3661 m_arm_isa = ARMv7;
3662 else if (strcasecmp(arch_cstr, "armv8") == 0)
3663 m_arm_isa = ARMv8;
3664 }
3665 }
3666 return m_arm_isa != 0;
3667}
3668
3669
Greg Clayton64c84432011-01-21 22:02:52 +00003670bool
3671EmulateInstructionARM::ReadInstruction ()
3672{
3673 bool success = false;
3674 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
3675 if (success)
3676 {
3677 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
3678 if (success)
3679 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003680 Context read_inst_context;
3681 read_inst_context.type = eContextReadOpcode;
3682 read_inst_context.SetNoArgs ();
3683
Greg Clayton64c84432011-01-21 22:02:52 +00003684 if (m_inst_cpsr & MASK_CPSR_T)
3685 {
3686 m_inst_mode = eModeThumb;
3687 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
3688
3689 if (success)
3690 {
3691 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
3692 {
3693 m_inst.opcode_type = eOpcode16;
3694 m_inst.opcode.inst16 = thumb_opcode;
3695 }
3696 else
3697 {
3698 m_inst.opcode_type = eOpcode32;
3699 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
3700 }
3701 }
3702 }
3703 else
3704 {
3705 m_inst_mode = eModeARM;
3706 m_inst.opcode_type = eOpcode32;
3707 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
3708 }
3709 }
3710 }
3711 if (!success)
3712 {
3713 m_inst_mode = eModeInvalid;
3714 m_inst_pc = LLDB_INVALID_ADDRESS;
3715 }
3716 return success;
3717}
3718
Johnny Chenee9b1f72011-02-09 01:00:31 +00003719uint32_t
3720EmulateInstructionARM::ArchVersion ()
3721{
3722 return m_arm_isa;
3723}
3724
Greg Clayton64c84432011-01-21 22:02:52 +00003725bool
3726EmulateInstructionARM::ConditionPassed ()
3727{
3728 if (m_inst_cpsr == 0)
3729 return false;
3730
3731 const uint32_t cond = CurrentCond ();
3732
3733 if (cond == UINT32_MAX)
3734 return false;
3735
3736 bool result = false;
3737 switch (UnsignedBits(cond, 3, 1))
3738 {
3739 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
3740 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
3741 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
3742 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
3743 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
3744 case 5:
3745 {
3746 bool n = (m_inst_cpsr & MASK_CPSR_N);
3747 bool v = (m_inst_cpsr & MASK_CPSR_V);
3748 result = n == v;
3749 }
3750 break;
3751 case 6:
3752 {
3753 bool n = (m_inst_cpsr & MASK_CPSR_N);
3754 bool v = (m_inst_cpsr & MASK_CPSR_V);
3755 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3756 }
3757 break;
3758 case 7:
3759 result = true;
3760 break;
3761 }
3762
3763 if (cond & 1)
3764 result = !result;
3765 return result;
3766}
3767
Johnny Chen9ee056b2011-02-08 00:06:35 +00003768uint32_t
3769EmulateInstructionARM::CurrentCond ()
3770{
3771 switch (m_inst_mode)
3772 {
3773 default:
3774 case eModeInvalid:
3775 break;
3776
3777 case eModeARM:
3778 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3779
3780 case eModeThumb:
3781 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3782 // 'cond' field of the encoding.
3783 if (m_inst.opcode_type == eOpcode16 &&
3784 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3785 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3786 {
3787 return Bits32(m_inst.opcode.inst16, 11, 7);
3788 }
3789 else if (m_inst.opcode_type == eOpcode32 &&
3790 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3791 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3792 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3793 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3794 {
3795 return Bits32(m_inst.opcode.inst32, 25, 22);
3796 }
3797
3798 return m_it_session.GetCond();
3799 }
3800 return UINT32_MAX; // Return invalid value
3801}
3802
Johnny Chen9ee056b2011-02-08 00:06:35 +00003803bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003804EmulateInstructionARM::InITBlock()
3805{
3806 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3807}
3808
3809bool
3810EmulateInstructionARM::LastInITBlock()
3811{
3812 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3813}
3814
3815bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003816EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3817{
3818 addr_t target;
3819
Johnny Chenee9b1f72011-02-09 01:00:31 +00003820 // Check the current instruction set.
3821 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003822 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003823 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003824 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003825
Johnny Chen9ee056b2011-02-08 00:06:35 +00003826 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003827 return false;
3828
3829 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003830}
3831
3832// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3833bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003834EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003835{
3836 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003837 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3838 // we want to record it and issue a WriteRegister callback so the clients
3839 // can track the mode changes accordingly.
3840 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003841
3842 if (BitIsSet(addr, 0))
3843 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003844 if (CurrentInstrSet() != eModeThumb)
3845 {
3846 SelectInstrSet(eModeThumb);
3847 cpsr_changed = true;
3848 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003849 target = addr & 0xfffffffe;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003850 context.SetModeAndRegister (eModeThumb, reg);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003851 }
3852 else if (BitIsClear(addr, 1))
3853 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003854 if (CurrentInstrSet() != eModeARM)
3855 {
3856 SelectInstrSet(eModeARM);
3857 cpsr_changed = true;
3858 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003859 target = addr & 0xfffffffc;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003860 context.SetModeAndRegister (eModeARM, reg);
Johnny Chen9ee056b2011-02-08 00:06:35 +00003861 }
3862 else
3863 return false; // address<1:0> == '10' => UNPREDICTABLE
3864
Johnny Chen0f309db2011-02-09 19:11:32 +00003865 if (cpsr_changed)
3866 {
Johnny Chen558133b2011-02-09 23:59:17 +00003867 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003868 return false;
3869 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003870 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003871 return false;
3872
3873 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003874}
Greg Clayton64c84432011-01-21 22:02:52 +00003875
Johnny Chenee9b1f72011-02-09 01:00:31 +00003876// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3877bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003878EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chenee9b1f72011-02-09 01:00:31 +00003879{
3880 if (ArchVersion() >= ARMv5T)
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003881 return BXWritePC(context, addr, reg);
Johnny Chenee9b1f72011-02-09 01:00:31 +00003882 else
3883 return BranchWritePC((const Context)context, addr);
3884}
3885
Johnny Chen26863dc2011-02-09 23:43:29 +00003886// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3887bool
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003888EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr, Register &reg)
Johnny Chen26863dc2011-02-09 23:43:29 +00003889{
3890 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003891 return BXWritePC(context, addr, reg);
Johnny Chen26863dc2011-02-09 23:43:29 +00003892 else
3893 return BranchWritePC((const Context)context, addr);
3894}
3895
Johnny Chenee9b1f72011-02-09 01:00:31 +00003896EmulateInstructionARM::Mode
3897EmulateInstructionARM::CurrentInstrSet ()
3898{
3899 return m_inst_mode;
3900}
3901
3902// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003903// ReadInstruction() is performed. This function has a side effect of updating
3904// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003905bool
3906EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3907{
Johnny Chen558133b2011-02-09 23:59:17 +00003908 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003909 switch (arm_or_thumb)
3910 {
3911 default:
3912 return false;
3913 eModeARM:
3914 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003915 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003916 break;
3917 eModeThumb:
3918 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003919 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003920 break;
3921 }
3922 return true;
3923}
3924
Johnny Chenef21b592011-02-10 01:52:38 +00003925// This function returns TRUE if the processor currently provides support for
3926// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3927// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3928bool
3929EmulateInstructionARM::UnalignedSupport()
3930{
3931 return (ArchVersion() >= ARMv7);
3932}
3933
Johnny Chenbf6ad172011-02-11 01:29:53 +00003934// The main addition and subtraction instructions can produce status information
3935// about both unsigned carry and signed overflow conditions. This status
3936// information can be used to synthesize multi-word additions and subtractions.
3937EmulateInstructionARM::AddWithCarryResult
3938EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3939{
3940 uint32_t result;
3941 uint8_t carry_out;
3942 uint8_t overflow;
3943
3944 uint64_t unsigned_sum = x + y + carry_in;
3945 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3946
3947 result = UnsignedBits(unsigned_sum, 31, 0);
3948 carry_out = (result == unsigned_sum ? 0 : 1);
3949 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3950
3951 AddWithCarryResult res = { result, carry_out, overflow };
3952 return res;
3953}
3954
Greg Clayton64c84432011-01-21 22:02:52 +00003955bool
3956EmulateInstructionARM::EvaluateInstruction ()
3957{
Johnny Chenc315f862011-02-05 00:46:10 +00003958 // Advance the ITSTATE bits to their values for the next instruction.
3959 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3960 m_it_session.ITAdvance();
3961
Greg Clayton64c84432011-01-21 22:02:52 +00003962 return false;
3963}