blob: c8755e826846db0d3af2a3e06f08056f488362ab [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 Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chend6c13f02011-02-08 20:36:34 +000026static inline uint32_t Align(uint32_t val, uint32_t alignment)
27{
28 return alignment * (val / alignment);
29}
30
Johnny Chen0e00af22011-02-10 19:40:42 +000031//----------------------------------------------------------------------
32//
33// ITSession implementation
34//
35//----------------------------------------------------------------------
36
Johnny Chen93070472011-02-04 23:02:47 +000037// A8.6.50
38// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
39static unsigned short CountITSize(unsigned ITMask) {
40 // First count the trailing zeros of the IT mask.
41 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
42 if (TZ > 3)
43 {
44 printf("Encoding error: IT Mask '0000'\n");
45 return 0;
46 }
47 return (4 - TZ);
48}
49
50// Init ITState. Note that at least one bit is always 1 in mask.
51bool ITSession::InitIT(unsigned short bits7_0)
52{
53 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
54 if (ITCounter == 0)
55 return false;
56
57 // A8.6.50 IT
58 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
59 if (FirstCond == 0xF)
60 {
61 printf("Encoding error: IT FirstCond '1111'\n");
62 return false;
63 }
64 if (FirstCond == 0xE && ITCounter != 1)
65 {
66 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
67 return false;
68 }
69
70 ITState = bits7_0;
71 return true;
72}
73
74// Update ITState if necessary.
75void ITSession::ITAdvance()
76{
77 assert(ITCounter);
78 --ITCounter;
79 if (ITCounter == 0)
80 ITState = 0;
81 else
82 {
83 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
84 SetBits32(ITState, 4, 0, NewITState4_0);
85 }
86}
87
88// Return true if we're inside an IT Block.
89bool ITSession::InITBlock()
90{
91 return ITCounter != 0;
92}
93
Johnny Chenc315f862011-02-05 00:46:10 +000094// Return true if we're the last instruction inside an IT Block.
95bool ITSession::LastInITBlock()
96{
97 return ITCounter == 1;
98}
99
Johnny Chen93070472011-02-04 23:02:47 +0000100// Get condition bits for the current thumb instruction.
101uint32_t ITSession::GetCond()
102{
Johnny Chenc315f862011-02-05 00:46:10 +0000103 if (InITBlock())
104 return Bits32(ITState, 7, 4);
105 else
106 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000107}
108
Greg Clayton64c84432011-01-21 22:02:52 +0000109// ARM constants used during decoding
110#define REG_RD 0
111#define LDM_REGLIST 1
112#define PC_REG 15
113#define PC_REGLIST_BIT 0x8000
114
Johnny Chen251af6a2011-01-21 22:47:25 +0000115#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000116#define ARMv4T (1u << 1)
117#define ARMv5T (1u << 2)
118#define ARMv5TE (1u << 3)
119#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000120#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000121#define ARMv6K (1u << 6)
122#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000124#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000125#define ARMvAll (0xffffffffu)
126
Johnny Chen9b8d7832011-02-02 01:13:56 +0000127#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
129#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000130
Johnny Chen0e00af22011-02-10 19:40:42 +0000131//----------------------------------------------------------------------
132//
133// EmulateInstructionARM implementation
134//
135//----------------------------------------------------------------------
136
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000137void
138EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000139{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000141
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142void
143EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000144{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145}
146
Caroline Ticefa172202011-02-11 22:49:54 +0000147// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
148bool
149EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
150{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000151 EmulateInstruction::Context context;
152 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
153 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000154
155 uint32_t random_data = rand ();
156 const uint32_t addr_byte_size = GetAddressByteSize();
157
158 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
159 return false;
160
161 return true;
162}
163
Caroline Tice713c2662011-02-11 17:59:55 +0000164// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
165bool
166EmulateInstructionARM::WriteBits32Unknown (int n)
167{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000168 EmulateInstruction::Context context;
169 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
170 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000171
Johnny Chen62ff6f52011-02-11 18:11:22 +0000172 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000173 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
174
175 if (!success)
176 return false;
177
178 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
179 return false;
180
181 return true;
182}
183
Johnny Chen08c25e82011-01-31 18:02:28 +0000184// Push Multiple Registers stores multiple registers to the stack, storing to
185// consecutive memory locations ending just below the address in SP, and updates
186// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000187bool
188EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000189{
190#if 0
191 // ARM pseudo code...
192 if (ConditionPassed())
193 {
194 EncodingSpecificOperations();
195 NullCheckIfThumbEE(13);
196 address = SP - 4*BitCount(registers);
197
198 for (i = 0 to 14)
199 {
200 if (registers<i> == ’1’)
201 {
202 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
203 MemA[address,4] = bits(32) UNKNOWN;
204 else
205 MemA[address,4] = R[i];
206 address = address + 4;
207 }
208 }
209
210 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
211 MemA[address,4] = PCStoreValue();
212
213 SP = SP - 4*BitCount(registers);
214 }
215#endif
216
217 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000218 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000219 if (!success)
220 return false;
221
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000222 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000223 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000224 const uint32_t addr_byte_size = GetAddressByteSize();
225 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000226 if (!success)
227 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000228 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000229 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000230 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000231 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000232 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000233 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000234 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000235 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 // if BitCount(registers) < 1 then UNPREDICTABLE;
237 if (BitCount(registers) < 1)
238 return false;
239 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000240 case eEncodingT2:
241 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000242 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 // if BitCount(registers) < 2 then UNPREDICTABLE;
244 if (BitCount(registers) < 2)
245 return false;
246 break;
247 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000248 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000249 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000250 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000251 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000252 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000253 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000254 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000255 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000256 // Instead of return false, let's handle the following case as well,
257 // which amounts to pushing one reg onto the full descending stacks.
258 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000259 break;
260 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000261 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000262 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000263 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000264 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000265 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000266 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000267 default:
268 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 }
Johnny Chence1ca772011-01-25 01:13:00 +0000270 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000271 addr_t addr = sp - sp_offset;
272 uint32_t i;
273
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000274 EmulateInstruction::Context context;
275 context.type = EmulateInstruction::eContextPushRegisterOnStack;
276 Register dwarf_reg;
277 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000278 for (i=0; i<15; ++i)
279 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000280 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000281 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000282 dwarf_reg.num = dwarf_r0 + i;
283 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
284 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000285 if (!success)
286 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000287 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000288 return false;
289 addr += addr_byte_size;
290 }
291 }
292
Johnny Chen7c1bf922011-02-08 23:49:37 +0000293 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000294 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000295 dwarf_reg.num = dwarf_pc;
296 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000297 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000298 if (!success)
299 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000300 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000301 return false;
302 }
303
304 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000305 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000306
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000307 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310 return true;
311}
312
Johnny Chenef85e912011-01-31 23:07:40 +0000313// Pop Multiple Registers loads multiple registers from the stack, loading from
314// consecutive memory locations staring at the address in SP, and updates
315// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000316bool
317EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000318{
319#if 0
320 // ARM pseudo code...
321 if (ConditionPassed())
322 {
323 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
324 address = SP;
325 for i = 0 to 14
326 if registers<i> == ‘1’ then
327 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
328 if registers<15> == ‘1’ then
329 if UnalignedAllowed then
330 LoadWritePC(MemU[address,4]);
331 else
332 LoadWritePC(MemA[address,4]);
333 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
334 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
335 }
336#endif
337
338 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000339 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000340 if (!success)
341 return false;
342
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000345 const uint32_t addr_byte_size = GetAddressByteSize();
346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349 uint32_t registers = 0;
350 uint32_t Rt; // the destination register
351 switch (encoding) {
352 case eEncodingT1:
353 registers = Bits32(opcode, 7, 0);
354 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000355 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 registers |= (1u << 15);
357 // if BitCount(registers) < 1 then UNPREDICTABLE;
358 if (BitCount(registers) < 1)
359 return false;
360 break;
361 case eEncodingT2:
362 // Ignore bit 13.
363 registers = Bits32(opcode, 15, 0) & ~0x2000;
364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
369 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000370 break;
371 case eEncodingT3:
372 Rt = Bits32(opcode, 15, 12);
373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 if (Rt == 13)
375 return false;
376 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
378 registers = (1u << Rt);
379 break;
380 case eEncodingA1:
381 registers = Bits32(opcode, 15, 0);
382 // Instead of return false, let's handle the following case as well,
383 // which amounts to popping one reg from the full descending stacks.
384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
385
386 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 break;
390 case eEncodingA2:
391 Rt = Bits32(opcode, 15, 12);
392 // if t == 13 then UNPREDICTABLE;
393 if (Rt == dwarf_sp)
394 return false;
395 registers = (1u << Rt);
396 break;
397 default:
398 return false;
399 }
400 addr_t sp_offset = addr_byte_size * BitCount (registers);
401 addr_t addr = sp;
402 uint32_t i, data;
403
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000404 EmulateInstruction::Context context;
405 context.type = EmulateInstruction::eContextPopRegisterOffStack;
406 Register dwarf_reg;
407 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000408 for (i=0; i<15; ++i)
409 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000410 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000411 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000412 dwarf_reg.num = dwarf_r0 + i;
413 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000415 if (!success)
416 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000417 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000418 return false;
419 addr += addr_byte_size;
420 }
421 }
422
Johnny Chen7c1bf922011-02-08 23:49:37 +0000423 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000424 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000425 dwarf_reg.num = dwarf_pc;
426 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000427 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000428 if (!success)
429 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000430 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000431 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000432 return false;
433 addr += addr_byte_size;
434 }
435
436 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000437 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000438
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000439 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000440 return false;
441 }
442 return true;
443}
444
Johnny Chen5b442b72011-01-27 19:34:30 +0000445// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000446// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000447bool
448EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449{
450#if 0
451 // ARM pseudo code...
452 if (ConditionPassed())
453 {
454 EncodingSpecificOperations();
455 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
456 if d == 15 then
457 ALUWritePC(result); // setflags is always FALSE here
458 else
459 R[d] = result;
460 if setflags then
461 APSR.N = result<31>;
462 APSR.Z = IsZeroBit(result);
463 APSR.C = carry;
464 APSR.V = overflow;
465 }
466#endif
467
468 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000470 if (!success)
471 return false;
472
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000474 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000475 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000476 if (!success)
477 return false;
478 uint32_t Rd; // the destination register
479 uint32_t imm32;
480 switch (encoding) {
481 case eEncodingT1:
482 Rd = 7;
483 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
484 break;
485 case eEncodingA1:
486 Rd = Bits32(opcode, 15, 12);
487 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
488 break;
489 default:
490 return false;
491 }
492 addr_t sp_offset = imm32;
493 addr_t addr = sp + sp_offset; // a pointer to the stack area
494
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000495 EmulateInstruction::Context context;
496 context.type = EmulateInstruction::eContextRegisterPlusOffset;
497 Register sp_reg;
498 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
499 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000500
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000501 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000502 return false;
503 }
504 return true;
505}
506
Johnny Chen2ccad832011-01-28 19:57:25 +0000507// Set r7 or ip to the current stack pointer.
508// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000509bool
510EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000511{
512#if 0
513 // ARM pseudo code...
514 if (ConditionPassed())
515 {
516 EncodingSpecificOperations();
517 result = R[m];
518 if d == 15 then
519 ALUWritePC(result); // setflags is always FALSE here
520 else
521 R[d] = result;
522 if setflags then
523 APSR.N = result<31>;
524 APSR.Z = IsZeroBit(result);
525 // APSR.C unchanged
526 // APSR.V unchanged
527 }
528#endif
529
530 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000531 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000532 //if (!success)
533 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000534
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000536 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000537 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000538 if (!success)
539 return false;
540 uint32_t Rd; // the destination register
541 switch (encoding) {
542 case eEncodingT1:
543 Rd = 7;
544 break;
545 case eEncodingA1:
546 Rd = 12;
547 break;
548 default:
549 return false;
550 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000551
552 EmulateInstruction::Context context;
553 context.type = EmulateInstruction::eContextRegisterPlusOffset;
554 Register sp_reg;
555 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
556 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000557
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000559 return false;
560 }
561 return true;
562}
563
Johnny Chen1c13b622011-01-29 00:11:15 +0000564// Move from high register (r8-r15) to low register (r0-r7).
565// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000566bool
567EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000568{
Johnny Chen338bf542011-02-10 19:29:03 +0000569 return EmulateMovRdRm (encoding);
570}
571
572// Move from register to register.
573// MOV (register)
574bool
575EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
576{
Johnny Chen1c13b622011-01-29 00:11:15 +0000577#if 0
578 // ARM pseudo code...
579 if (ConditionPassed())
580 {
581 EncodingSpecificOperations();
582 result = R[m];
583 if d == 15 then
584 ALUWritePC(result); // setflags is always FALSE here
585 else
586 R[d] = result;
587 if setflags then
588 APSR.N = result<31>;
589 APSR.Z = IsZeroBit(result);
590 // APSR.C unchanged
591 // APSR.V unchanged
592 }
593#endif
594
595 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000596 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000597 if (!success)
598 return false;
599
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000600 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 {
602 uint32_t Rm; // the source register
603 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000604 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000605 switch (encoding) {
606 case eEncodingT1:
607 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000608 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000609 setflags = false;
610 break;
611 case eEncodingT2:
612 Rm = Bits32(opcode, 5, 3);
613 Rd = Bits32(opcode, 2, 1);
614 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000615 break;
616 default:
617 return false;
618 }
Johnny Chen338bf542011-02-10 19:29:03 +0000619 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000620 if (!success)
621 return false;
622
623 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000624 EmulateInstruction::Context context;
625 context.type = EmulateInstruction::eContextRegisterPlusOffset;
626 Register dwarf_reg;
627 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
628 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000629
Johnny Chen338bf542011-02-10 19:29:03 +0000630 if (Rd == 15)
631 {
Johnny Chen668b4512011-02-15 21:08:58 +0000632 if (!ALUWritePC (context, reg_value))
Johnny Chen338bf542011-02-10 19:29:03 +0000633 return false;
634 }
635 else
636 {
637 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
638 return false;
639 if (setflags)
640 {
641 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000642 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
643 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000644 if (m_new_inst_cpsr != m_inst_cpsr)
645 {
646 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
647 return false;
648 }
649 }
650 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000651 }
652 return true;
653}
654
Johnny Chen357c30f2011-02-14 22:04:25 +0000655// Move (immediate) writes an immediate value to the destination register. It
656// can optionally update the condition flags based on the value.
657// MOV (immediate)
658bool
659EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
660{
661#if 0
662 // ARM pseudo code...
663 if (ConditionPassed())
664 {
665 EncodingSpecificOperations();
666 result = imm32;
667 if d == 15 then // Can only occur for ARM encoding
668 ALUWritePC(result); // setflags is always FALSE here
669 else
670 R[d] = result;
671 if setflags then
672 APSR.N = result<31>;
673 APSR.Z = IsZeroBit(result);
674 APSR.C = carry;
675 // APSR.V unchanged
676 }
677#endif
678 bool success = false;
679 const uint32_t opcode = OpcodeAsUnsigned (&success);
680 if (!success)
681 return false;
682
683 if (ConditionPassed())
684 {
685 uint32_t Rd; // the destination register
686 uint32_t imm12; // some intermediate result
687 uint32_t imm32; // the immediate value to be written to Rd
688 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
689 bool setflags;
690 switch (encoding) {
691 case eEncodingT1:
692 Rd = Bits32(opcode, 11, 8);
693 setflags = !InITBlock();
694 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
695 carry = Bit32(m_inst_cpsr, CPSR_C);
696 break;
697 case eEncodingT2:
698 Rd = Bits32(opcode, 15, 12);
699 setflags = BitIsSet(opcode, 20);
700 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
701 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000702 if (BadReg(Rd))
703 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000704 break;
705 default:
706 return false;
707 }
708 uint32_t result = imm32;
709
710 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000711 EmulateInstruction::Context context;
712 context.type = EmulateInstruction::eContextImmediate;
713 context.SetNoArgs ();
714
Johnny Chen357c30f2011-02-14 22:04:25 +0000715 if (Rd == 15)
716 {
Johnny Chen668b4512011-02-15 21:08:58 +0000717 if (!ALUWritePC (context, result))
Johnny Chen357c30f2011-02-14 22:04:25 +0000718 return false;
719 }
720 else
721 {
722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
723 return false;
724 if (setflags)
725 {
726 m_new_inst_cpsr = m_inst_cpsr;
727 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
728 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
729 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
730 if (m_new_inst_cpsr != m_inst_cpsr)
731 {
732 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
733 return false;
734 }
735 }
736 }
737 }
738 return true;
739}
740
Johnny Chen28070c32011-02-12 01:27:26 +0000741// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
742// the destination register. It can optionally update the condition flags based
743// on the value.
744// MVN (immediate)
745bool
746EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
747{
748#if 0
749 // ARM pseudo code...
750 if (ConditionPassed())
751 {
752 EncodingSpecificOperations();
753 result = NOT(imm32);
754 if d == 15 then // Can only occur for ARM encoding
755 ALUWritePC(result); // setflags is always FALSE here
756 else
757 R[d] = result;
758 if setflags then
759 APSR.N = result<31>;
760 APSR.Z = IsZeroBit(result);
761 APSR.C = carry;
762 // APSR.V unchanged
763 }
764#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 bool success = false;
766 const uint32_t opcode = OpcodeAsUnsigned (&success);
767 if (!success)
768 return false;
769
770 if (ConditionPassed())
771 {
772 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000773 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
774 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
775 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000776 bool setflags;
777 switch (encoding) {
778 case eEncodingT1:
779 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000780 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000781 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000782 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
783 break;
784 case eEncodingA1:
785 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000786 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000787 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000788 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
789 break;
790 default:
791 return false;
792 }
793 uint32_t result = ~imm32;
794
795 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000796 EmulateInstruction::Context context;
797 context.type = EmulateInstruction::eContextImmediate;
798 context.SetNoArgs ();
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000799
800 if (Rd == 15)
801 {
Johnny Chen668b4512011-02-15 21:08:58 +0000802 if (!ALUWritePC (context, result))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000803 return false;
804 }
805 else
806 {
807 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
808 return false;
809 if (setflags)
810 {
811 m_new_inst_cpsr = m_inst_cpsr;
812 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
813 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
814 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
815 if (m_new_inst_cpsr != m_inst_cpsr)
816 {
817 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
818 return false;
819 }
820 }
821 }
822 }
823 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000824}
825
Johnny Chen788e0552011-01-27 22:52:23 +0000826// PC relative immediate load into register, possibly followed by ADD (SP plus register).
827// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000828bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000829EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000830{
831#if 0
832 // ARM pseudo code...
833 if (ConditionPassed())
834 {
835 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
836 base = Align(PC,4);
837 address = if add then (base + imm32) else (base - imm32);
838 data = MemU[address,4];
839 if t == 15 then
840 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
841 elsif UnalignedSupport() || address<1:0> = ‘00’ then
842 R[t] = data;
843 else // Can only apply before ARMv7
844 if CurrentInstrSet() == InstrSet_ARM then
845 R[t] = ROR(data, 8*UInt(address<1:0>));
846 else
847 R[t] = bits(32) UNKNOWN;
848 }
849#endif
850
851 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000852 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000853 if (!success)
854 return false;
855
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000856 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000857 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000858 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000859 if (!success)
860 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000861
862 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000863 EmulateInstruction::Context context;
864 context.type = EmulateInstruction::eContextRegisterPlusOffset;
865 Register pc_reg;
866 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
867 context.SetRegisterPlusOffset (pc_reg, 0);
868
Johnny Chenc9de9102011-02-11 19:12:30 +0000869 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000870 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000871 bool add; // +imm32 or -imm32?
872 addr_t base; // the base address
873 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000874 uint32_t data; // the literal data value from the PC relative load
875 switch (encoding) {
876 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000877 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000878 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000879 add = true;
880 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000881 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000882 break;
883 case eEncodingT2:
884 Rt = Bits32(opcode, 15, 12);
885 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
886 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000887 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000888 return false;
889 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000890 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000891 break;
892 default:
893 return false;
894 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000895
896 if (add)
897 address = base + imm32;
898 else
899 address = base - imm32;
900 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000901 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000902 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000903
904 if (Rt == 15)
905 {
906 if (Bits32(address, 1, 0) == 0)
907 {
908 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000909 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000910 return false;
911 }
912 else
913 return false;
914 }
915 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
916 {
917 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
918 return false;
919 }
920 else // We don't handle ARM for now.
921 return false;
922
923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000924 return false;
925 }
926 return true;
927}
928
Johnny Chen5b442b72011-01-27 19:34:30 +0000929// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000930// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000931bool
932EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000933{
934#if 0
935 // ARM pseudo code...
936 if (ConditionPassed())
937 {
938 EncodingSpecificOperations();
939 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
940 if d == 15 then // Can only occur for ARM encoding
941 ALUWritePC(result); // setflags is always FALSE here
942 else
943 R[d] = result;
944 if setflags then
945 APSR.N = result<31>;
946 APSR.Z = IsZeroBit(result);
947 APSR.C = carry;
948 APSR.V = overflow;
949 }
950#endif
951
952 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000953 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000954 if (!success)
955 return false;
956
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000957 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000958 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000959 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000960 if (!success)
961 return false;
962 uint32_t imm32; // the immediate operand
963 switch (encoding) {
964 case eEncodingT2:
965 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
966 break;
967 default:
968 return false;
969 }
970 addr_t sp_offset = imm32;
971 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
972
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000973 EmulateInstruction::Context context;
974 context.type = EmulateInstruction::eContextAdjustStackPointer;
975 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000976
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000977 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000978 return false;
979 }
980 return true;
981}
982
983// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000984// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000985bool
986EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000987{
988#if 0
989 // ARM pseudo code...
990 if (ConditionPassed())
991 {
992 EncodingSpecificOperations();
993 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
994 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
995 if d == 15 then
996 ALUWritePC(result); // setflags is always FALSE here
997 else
998 R[d] = result;
999 if setflags then
1000 APSR.N = result<31>;
1001 APSR.Z = IsZeroBit(result);
1002 APSR.C = carry;
1003 APSR.V = overflow;
1004 }
1005#endif
1006
1007 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001008 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001009 if (!success)
1010 return false;
1011
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001012 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001013 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001014 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001015 if (!success)
1016 return false;
1017 uint32_t Rm; // the second operand
1018 switch (encoding) {
1019 case eEncodingT2:
1020 Rm = Bits32(opcode, 6, 3);
1021 break;
1022 default:
1023 return false;
1024 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001025 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001026 if (!success)
1027 return false;
1028
1029 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1030
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001031 EmulateInstruction::Context context;
1032 context.type = EmulateInstruction::eContextAdjustStackPointer;
1033 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001034
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001035 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001036 return false;
1037 }
1038 return true;
1039}
1040
Johnny Chen9b8d7832011-02-02 01:13:56 +00001041// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1042// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1043// from Thumb to ARM.
1044// BLX (immediate)
1045bool
1046EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1047{
1048#if 0
1049 // ARM pseudo code...
1050 if (ConditionPassed())
1051 {
1052 EncodingSpecificOperations();
1053 if CurrentInstrSet() == InstrSet_ARM then
1054 LR = PC - 4;
1055 else
1056 LR = PC<31:1> : '1';
1057 if targetInstrSet == InstrSet_ARM then
1058 targetAddress = Align(PC,4) + imm32;
1059 else
1060 targetAddress = PC + imm32;
1061 SelectInstrSet(targetInstrSet);
1062 BranchWritePC(targetAddress);
1063 }
1064#endif
1065
1066 bool success = false;
1067 const uint32_t opcode = OpcodeAsUnsigned (&success);
1068 if (!success)
1069 return false;
1070
1071 if (ConditionPassed())
1072 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001073 EmulateInstruction::Context context;
1074 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001075 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001076 if (!success)
1077 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001078 addr_t lr; // next instruction address
1079 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001080 int32_t imm32; // PC-relative offset
1081 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001082 case eEncodingT1:
1083 {
1084 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001085 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001086 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001087 uint32_t J1 = Bit32(opcode, 13);
1088 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001089 uint32_t imm11 = Bits32(opcode, 10, 0);
1090 uint32_t I1 = !(J1 ^ S);
1091 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001092 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001093 imm32 = llvm::SignExtend32<25>(imm25);
1094 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001095 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001096 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001097 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001098 break;
1099 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001100 case eEncodingT2:
1101 {
1102 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001103 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001104 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001105 uint32_t J1 = Bit32(opcode, 13);
1106 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001107 uint32_t imm10L = Bits32(opcode, 10, 1);
1108 uint32_t I1 = !(J1 ^ S);
1109 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001110 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001111 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001112 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001113 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001114 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001115 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001116 break;
1117 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001118 case eEncodingA1:
1119 lr = pc + 4; // return address
1120 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001121 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001122 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001123 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001124 case eEncodingA2:
1125 lr = pc + 4; // return address
1126 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1127 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001128 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001129 break;
1130 default:
1131 return false;
1132 }
1133 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1134 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001135 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001136 return false;
1137 }
1138 return true;
1139}
1140
1141// Branch with Link and Exchange (register) calls a subroutine at an address and
1142// instruction set specified by a register.
1143// BLX (register)
1144bool
1145EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1146{
1147#if 0
1148 // ARM pseudo code...
1149 if (ConditionPassed())
1150 {
1151 EncodingSpecificOperations();
1152 target = R[m];
1153 if CurrentInstrSet() == InstrSet_ARM then
1154 next_instr_addr = PC - 4;
1155 LR = next_instr_addr;
1156 else
1157 next_instr_addr = PC - 2;
1158 LR = next_instr_addr<31:1> : ‘1’;
1159 BXWritePC(target);
1160 }
1161#endif
1162
1163 bool success = false;
1164 const uint32_t opcode = OpcodeAsUnsigned (&success);
1165 if (!success)
1166 return false;
1167
1168 if (ConditionPassed())
1169 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001170 EmulateInstruction::Context context;
1171 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001172 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1173 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001174 if (!success)
1175 return false;
1176 uint32_t Rm; // the register with the target address
1177 switch (encoding) {
1178 case eEncodingT1:
1179 lr = (pc + 2) | 1u; // return address
1180 Rm = Bits32(opcode, 6, 3);
1181 // if m == 15 then UNPREDICTABLE;
1182 if (Rm == 15)
1183 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001184 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001185 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001186 break;
1187 case eEncodingA1:
1188 lr = pc + 4; // return address
1189 Rm = Bits32(opcode, 3, 0);
1190 // if m == 15 then UNPREDICTABLE;
1191 if (Rm == 15)
1192 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001193 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001194 default:
1195 return false;
1196 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001197 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1198 if (!success)
1199 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001200 Register dwarf_reg;
1201 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1202 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001203 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1204 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001205 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001206 return false;
1207 }
1208 return true;
1209}
1210
Johnny Chenab3b3512011-02-12 00:10:51 +00001211// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1212// BX
1213bool
1214EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1215{
1216#if 0
1217 // ARM pseudo code...
1218 if (ConditionPassed())
1219 {
1220 EncodingSpecificOperations();
1221 BXWritePC(R[m]);
1222 }
1223#endif
1224
1225 bool success = false;
1226 const uint32_t opcode = OpcodeAsUnsigned (&success);
1227 if (!success)
1228 return false;
1229
1230 if (ConditionPassed())
1231 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001232 EmulateInstruction::Context context;
1233 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001234 uint32_t Rm; // the register with the target address
1235 switch (encoding) {
1236 case eEncodingT1:
1237 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001238 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001239 return false;
1240 break;
1241 case eEncodingA1:
1242 Rm = Bits32(opcode, 3, 0);
1243 break;
1244 default:
1245 return false;
1246 }
1247 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1248 if (!success)
1249 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001250
1251 Register dwarf_reg;
1252 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001253 context.SetRegister (dwarf_reg);
1254 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001255 return false;
1256 }
1257 return true;
1258}
1259
Johnny Chen0d0148e2011-01-28 02:26:08 +00001260// Set r7 to point to some ip offset.
1261// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001262bool
1263EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001264{
1265#if 0
1266 // ARM pseudo code...
1267 if (ConditionPassed())
1268 {
1269 EncodingSpecificOperations();
1270 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1271 if d == 15 then // Can only occur for ARM encoding
1272 ALUWritePC(result); // setflags is always FALSE here
1273 else
1274 R[d] = result;
1275 if setflags then
1276 APSR.N = result<31>;
1277 APSR.Z = IsZeroBit(result);
1278 APSR.C = carry;
1279 APSR.V = overflow;
1280 }
1281#endif
1282
1283 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001284 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001285 if (!success)
1286 return false;
1287
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001288 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001289 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001290 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001291 if (!success)
1292 return false;
1293 uint32_t imm32;
1294 switch (encoding) {
1295 case eEncodingA1:
1296 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1297 break;
1298 default:
1299 return false;
1300 }
1301 addr_t ip_offset = imm32;
1302 addr_t addr = ip - ip_offset; // the adjusted ip value
1303
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 EmulateInstruction::Context context;
1305 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1306 Register dwarf_reg;
1307 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1308 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001309
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001311 return false;
1312 }
1313 return true;
1314}
1315
1316// Set ip to point to some stack offset.
1317// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001318bool
1319EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001320{
1321#if 0
1322 // ARM pseudo code...
1323 if (ConditionPassed())
1324 {
1325 EncodingSpecificOperations();
1326 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1327 if d == 15 then // Can only occur for ARM encoding
1328 ALUWritePC(result); // setflags is always FALSE here
1329 else
1330 R[d] = result;
1331 if setflags then
1332 APSR.N = result<31>;
1333 APSR.Z = IsZeroBit(result);
1334 APSR.C = carry;
1335 APSR.V = overflow;
1336 }
1337#endif
1338
1339 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001340 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001341 if (!success)
1342 return false;
1343
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001344 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001345 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347 if (!success)
1348 return false;
1349 uint32_t imm32;
1350 switch (encoding) {
1351 case eEncodingA1:
1352 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1353 break;
1354 default:
1355 return false;
1356 }
1357 addr_t sp_offset = imm32;
1358 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1359
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001360 EmulateInstruction::Context context;
1361 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1362 Register dwarf_reg;
1363 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1364 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001365
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001367 return false;
1368 }
1369 return true;
1370}
1371
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001372// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001373bool
1374EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001375{
1376#if 0
1377 // ARM pseudo code...
1378 if (ConditionPassed())
1379 {
1380 EncodingSpecificOperations();
1381 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1382 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001383 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001384 else
1385 R[d] = result;
1386 if setflags then
1387 APSR.N = result<31>;
1388 APSR.Z = IsZeroBit(result);
1389 APSR.C = carry;
1390 APSR.V = overflow;
1391 }
1392#endif
1393
1394 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001395 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001396 if (!success)
1397 return false;
1398
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001399 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001400 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001401 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001402 if (!success)
1403 return false;
1404 uint32_t imm32;
1405 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001406 case eEncodingT1:
1407 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001408 case eEncodingT2:
1409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1410 break;
1411 case eEncodingT3:
1412 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1413 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001414 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001415 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416 break;
1417 default:
1418 return false;
1419 }
1420 addr_t sp_offset = imm32;
1421 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1422
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001423 EmulateInstruction::Context context;
1424 context.type = EmulateInstruction::eContextAdjustStackPointer;
1425 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001426
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001427 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001428 return false;
1429 }
1430 return true;
1431}
1432
Johnny Chen08c25e82011-01-31 18:02:28 +00001433// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001434bool
1435EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001436{
1437#if 0
1438 // ARM pseudo code...
1439 if (ConditionPassed())
1440 {
1441 EncodingSpecificOperations();
1442 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1443 address = if index then offset_addr else R[n];
1444 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1445 if wback then R[n] = offset_addr;
1446 }
1447#endif
1448
1449 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001450 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001451 if (!success)
1452 return false;
1453
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001454 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001455 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001456 const uint32_t addr_byte_size = GetAddressByteSize();
1457 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001458 if (!success)
1459 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001460 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001461 uint32_t imm12;
1462 switch (encoding) {
1463 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001464 Rt = Bits32(opcode, 15, 12);
1465 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001466 break;
1467 default:
1468 return false;
1469 }
1470 addr_t sp_offset = imm12;
1471 addr_t addr = sp - sp_offset;
1472
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001473 EmulateInstruction::Context context;
1474 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1475 Register dwarf_reg;
1476 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001477 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001478 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001479 dwarf_reg.num = dwarf_r0 + Rt;
1480 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1481 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001482 if (!success)
1483 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001484 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001485 return false;
1486 }
1487 else
1488 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001489 dwarf_reg.num = dwarf_pc;
1490 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001491 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001492 if (!success)
1493 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001494 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001495 return false;
1496 }
1497
1498 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001499 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001500
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001501 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001502 return false;
1503 }
1504 return true;
1505}
1506
Johnny Chen08c25e82011-01-31 18:02:28 +00001507// Vector Push stores multiple extension registers to the stack.
1508// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001509bool
1510EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001511{
1512#if 0
1513 // ARM pseudo code...
1514 if (ConditionPassed())
1515 {
1516 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1517 address = SP - imm32;
1518 SP = SP - imm32;
1519 if single_regs then
1520 for r = 0 to regs-1
1521 MemA[address,4] = S[d+r]; address = address+4;
1522 else
1523 for r = 0 to regs-1
1524 // Store as two word-aligned words in the correct order for current endianness.
1525 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1526 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1527 address = address+8;
1528 }
1529#endif
1530
1531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001533 if (!success)
1534 return false;
1535
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001536 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001537 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001538 const uint32_t addr_byte_size = GetAddressByteSize();
1539 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001540 if (!success)
1541 return false;
1542 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001543 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001544 uint32_t imm32; // stack offset
1545 uint32_t regs; // number of registers
1546 switch (encoding) {
1547 case eEncodingT1:
1548 case eEncodingA1:
1549 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001550 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001551 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1552 // If UInt(imm8) is odd, see "FSTMX".
1553 regs = Bits32(opcode, 7, 0) / 2;
1554 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1555 if (regs == 0 || regs > 16 || (d + regs) > 32)
1556 return false;
1557 break;
1558 case eEncodingT2:
1559 case eEncodingA2:
1560 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001561 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001562 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1563 regs = Bits32(opcode, 7, 0);
1564 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1565 if (regs == 0 || regs > 16 || (d + regs) > 32)
1566 return false;
1567 break;
1568 default:
1569 return false;
1570 }
1571 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1572 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1573 addr_t sp_offset = imm32;
1574 addr_t addr = sp - sp_offset;
1575 uint32_t i;
1576
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001577 EmulateInstruction::Context context;
1578 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1579 Register dwarf_reg;
1580 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001581 for (i=d; i<regs; ++i)
1582 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001583 dwarf_reg.num = start_reg + i;
1584 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001585 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001586 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001587 if (!success)
1588 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001589 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001590 return false;
1591 addr += reg_byte_size;
1592 }
1593
1594 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001595 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001596
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001597 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001598 return false;
1599 }
1600 return true;
1601}
1602
Johnny Chen587a0a42011-02-01 18:35:28 +00001603// Vector Pop loads multiple extension registers from the stack.
1604// It also updates SP to point just above the loaded data.
1605bool
1606EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1607{
1608#if 0
1609 // ARM pseudo code...
1610 if (ConditionPassed())
1611 {
1612 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1613 address = SP;
1614 SP = SP + imm32;
1615 if single_regs then
1616 for r = 0 to regs-1
1617 S[d+r] = MemA[address,4]; address = address+4;
1618 else
1619 for r = 0 to regs-1
1620 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1621 // Combine the word-aligned words in the correct order for current endianness.
1622 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1623 }
1624#endif
1625
1626 bool success = false;
1627 const uint32_t opcode = OpcodeAsUnsigned (&success);
1628 if (!success)
1629 return false;
1630
1631 if (ConditionPassed())
1632 {
1633 const uint32_t addr_byte_size = GetAddressByteSize();
1634 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1635 if (!success)
1636 return false;
1637 bool single_regs;
1638 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1639 uint32_t imm32; // stack offset
1640 uint32_t regs; // number of registers
1641 switch (encoding) {
1642 case eEncodingT1:
1643 case eEncodingA1:
1644 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001645 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001646 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1647 // If UInt(imm8) is odd, see "FLDMX".
1648 regs = Bits32(opcode, 7, 0) / 2;
1649 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1650 if (regs == 0 || regs > 16 || (d + regs) > 32)
1651 return false;
1652 break;
1653 case eEncodingT2:
1654 case eEncodingA2:
1655 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001656 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001657 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1658 regs = Bits32(opcode, 7, 0);
1659 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1660 if (regs == 0 || regs > 16 || (d + regs) > 32)
1661 return false;
1662 break;
1663 default:
1664 return false;
1665 }
1666 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1667 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1668 addr_t sp_offset = imm32;
1669 addr_t addr = sp;
1670 uint32_t i;
1671 uint64_t data; // uint64_t to accomodate 64-bit registers.
1672
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001673 EmulateInstruction::Context context;
1674 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1675 Register dwarf_reg;
1676 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001677 for (i=d; i<regs; ++i)
1678 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679 dwarf_reg.num = start_reg + i;
1680 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chen587a0a42011-02-01 18:35:28 +00001681 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1682 if (!success)
1683 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001684 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001685 return false;
1686 addr += reg_byte_size;
1687 }
1688
1689 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001690 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001691
1692 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1693 return false;
1694 }
1695 return true;
1696}
1697
Johnny Chenb77be412011-02-04 00:40:18 +00001698// SVC (previously SWI)
1699bool
1700EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1701{
1702#if 0
1703 // ARM pseudo code...
1704 if (ConditionPassed())
1705 {
1706 EncodingSpecificOperations();
1707 CallSupervisor();
1708 }
1709#endif
1710
1711 bool success = false;
1712 const uint32_t opcode = OpcodeAsUnsigned (&success);
1713 if (!success)
1714 return false;
1715
1716 if (ConditionPassed())
1717 {
1718 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1719 addr_t lr; // next instruction address
1720 if (!success)
1721 return false;
1722 uint32_t imm32; // the immediate constant
1723 uint32_t mode; // ARM or Thumb mode
1724 switch (encoding) {
1725 case eEncodingT1:
1726 lr = (pc + 2) | 1u; // return address
1727 imm32 = Bits32(opcode, 7, 0);
1728 mode = eModeThumb;
1729 break;
1730 case eEncodingA1:
1731 lr = pc + 4; // return address
1732 imm32 = Bits32(opcode, 23, 0);
1733 mode = eModeARM;
1734 break;
1735 default:
1736 return false;
1737 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001738
1739 EmulateInstruction::Context context;
1740 context.type = EmulateInstruction::eContextSupervisorCall;
1741 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001742 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1743 return false;
1744 }
1745 return true;
1746}
1747
Johnny Chenc315f862011-02-05 00:46:10 +00001748// If Then makes up to four following instructions (the IT block) conditional.
1749bool
1750EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1751{
1752#if 0
1753 // ARM pseudo code...
1754 EncodingSpecificOperations();
1755 ITSTATE.IT<7:0> = firstcond:mask;
1756#endif
1757
1758 bool success = false;
1759 const uint32_t opcode = OpcodeAsUnsigned (&success);
1760 if (!success)
1761 return false;
1762
1763 m_it_session.InitIT(Bits32(opcode, 7, 0));
1764 return true;
1765}
1766
Johnny Chen3b620b32011-02-07 20:11:47 +00001767// Branch causes a branch to a target address.
1768bool
1769EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1770{
1771#if 0
1772 // ARM pseudo code...
1773 if (ConditionPassed())
1774 {
1775 EncodingSpecificOperations();
1776 BranchWritePC(PC + imm32);
1777 }
1778#endif
1779
1780 bool success = false;
1781 const uint32_t opcode = OpcodeAsUnsigned (&success);
1782 if (!success)
1783 return false;
1784
Johnny Chen9ee056b2011-02-08 00:06:35 +00001785 if (ConditionPassed())
1786 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001787 EmulateInstruction::Context context;
1788 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001789 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001790 if (!success)
1791 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001792 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001793 int32_t imm32; // PC-relative offset
1794 switch (encoding) {
1795 case eEncodingT1:
1796 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1797 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1798 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001799 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001800 break;
1801 case eEncodingT2:
1802 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1803 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001804 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001805 break;
1806 case eEncodingT3:
1807 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1808 {
Johnny Chenbd599902011-02-10 21:39:01 +00001809 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001810 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001811 uint32_t J1 = Bit32(opcode, 13);
1812 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001813 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001814 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001815 imm32 = llvm::SignExtend32<21>(imm21);
1816 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001817 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001818 break;
1819 }
1820 case eEncodingT4:
1821 {
Johnny Chenbd599902011-02-10 21:39:01 +00001822 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001823 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001824 uint32_t J1 = Bit32(opcode, 13);
1825 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001826 uint32_t imm11 = Bits32(opcode, 10, 0);
1827 uint32_t I1 = !(J1 ^ S);
1828 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001829 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001830 imm32 = llvm::SignExtend32<25>(imm25);
1831 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001832 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001833 break;
1834 }
1835 case eEncodingA1:
1836 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1837 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001838 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001839 break;
1840 default:
1841 return false;
1842 }
1843 if (!BranchWritePC(context, target))
1844 return false;
1845 }
1846 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001847}
1848
Johnny Chen53ebab72011-02-08 23:21:57 +00001849// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1850// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1851// CBNZ, CBZ
1852bool
1853EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1854{
1855#if 0
1856 // ARM pseudo code...
1857 EncodingSpecificOperations();
1858 if nonzero ^ IsZero(R[n]) then
1859 BranchWritePC(PC + imm32);
1860#endif
1861
1862 bool success = false;
1863 const uint32_t opcode = OpcodeAsUnsigned (&success);
1864 if (!success)
1865 return false;
1866
1867 // Read the register value from the operand register Rn.
1868 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1869 if (!success)
1870 return false;
1871
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001872 EmulateInstruction::Context context;
1873 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001874 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1875 if (!success)
1876 return false;
1877
1878 addr_t target; // target address
1879 uint32_t imm32; // PC-relative offset to branch forward
1880 bool nonzero;
1881 switch (encoding) {
1882 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001883 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001884 nonzero = BitIsSet(opcode, 11);
1885 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001886 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001887 break;
1888 default:
1889 return false;
1890 }
1891 if (nonzero ^ (reg_val == 0))
1892 if (!BranchWritePC(context, target))
1893 return false;
1894
1895 return true;
1896}
1897
Johnny Chen26863dc2011-02-09 23:43:29 +00001898// ADD <Rdn>, <Rm>
1899// where <Rdn> the destination register is also the first operand register
1900// and <Rm> is the second operand register.
1901bool
1902EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1903{
1904#if 0
1905 // ARM pseudo code...
1906 if ConditionPassed() then
1907 EncodingSpecificOperations();
1908 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1909 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1910 if d == 15 then
1911 ALUWritePC(result); // setflags is always FALSE here
1912 else
1913 R[d] = result;
1914 if setflags then
1915 APSR.N = result<31>;
1916 APSR.Z = IsZeroBit(result);
1917 APSR.C = carry;
1918 APSR.V = overflow;
1919#endif
1920
1921 bool success = false;
1922 const uint32_t opcode = OpcodeAsUnsigned (&success);
1923 if (!success)
1924 return false;
1925
1926 if (ConditionPassed())
1927 {
1928 uint32_t Rd, Rn, Rm;
1929 //bool setflags = false;
1930 switch (encoding)
1931 {
1932 case eEncodingT2:
1933 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001934 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001935 Rm = Bits32(opcode, 6, 3);
1936 if (Rn == 15 && Rm == 15)
1937 return false;
1938 break;
1939 default:
1940 return false;
1941 }
1942
1943 int32_t result, val1, val2;
1944 // Read the first operand.
1945 if (Rn == 15)
1946 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1947 else
1948 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1949 if (!success)
1950 return false;
1951
1952 // Read the second operand.
1953 if (Rm == 15)
1954 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1955 else
1956 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1957 if (!success)
1958 return false;
1959
1960 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001961
1962 EmulateInstruction::Context context;
1963 context.type = EmulateInstruction::eContextImmediate;
1964 context.SetNoArgs ();
Johnny Chen26863dc2011-02-09 23:43:29 +00001965
1966 if (Rd == 15)
1967 {
Johnny Chen668b4512011-02-15 21:08:58 +00001968 if (!ALUWritePC (context, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001969 return false;
1970 }
1971 else
1972 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001973 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001974 return false;
1975 }
1976 }
1977 return true;
1978}
1979
Johnny Chene4a4d302011-02-11 21:53:58 +00001980// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001981bool
1982EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1983{
1984#if 0
1985 // ARM pseudo code...
1986 if ConditionPassed() then
1987 EncodingSpecificOperations();
1988 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1989 APSR.N = result<31>;
1990 APSR.Z = IsZeroBit(result);
1991 APSR.C = carry;
1992 APSR.V = overflow;
1993#endif
1994
1995 bool success = false;
1996 const uint32_t opcode = OpcodeAsUnsigned (&success);
1997 if (!success)
1998 return false;
1999
2000 uint32_t Rn; // the first operand
2001 uint32_t imm32; // the immediate value to be compared with
2002 switch (encoding) {
2003 case eEncodingT1:
2004 Rn = Bits32(opcode, 10, 8);
2005 imm32 = Bits32(opcode, 7, 0);
2006 break;
2007 default:
2008 return false;
2009 }
2010 // Read the register value from the operand register Rn.
2011 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2012 if (!success)
2013 return false;
2014
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002015 EmulateInstruction::Context context;
2016 context.type = EmulateInstruction::eContextImmediate;
2017 context.SetNoArgs ();
2018
Johnny Chend4dc4442011-02-11 02:02:56 +00002019 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2020 m_new_inst_cpsr = m_inst_cpsr;
2021 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2022 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2023 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2024 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2025 if (m_new_inst_cpsr != m_inst_cpsr)
2026 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002027 EmulateInstruction::Context context;
2028 context.type = EmulateInstruction::eContextImmediate;
2029 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002030 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2031 return false;
2032 }
2033 return true;
2034}
2035
Johnny Chene4a4d302011-02-11 21:53:58 +00002036// CMP (register)
2037bool
2038EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2039{
2040#if 0
2041 // ARM pseudo code...
2042 if ConditionPassed() then
2043 EncodingSpecificOperations();
2044 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2045 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2046 APSR.N = result<31>;
2047 APSR.Z = IsZeroBit(result);
2048 APSR.C = carry;
2049 APSR.V = overflow;
2050#endif
2051
2052 bool success = false;
2053 const uint32_t opcode = OpcodeAsUnsigned (&success);
2054 if (!success)
2055 return false;
2056
2057 uint32_t Rn; // the first operand
2058 uint32_t Rm; // the second operand
2059 switch (encoding) {
2060 case eEncodingT1:
2061 Rn = Bits32(opcode, 2, 0);
2062 Rm = Bits32(opcode, 5, 3);
2063 break;
2064 case eEncodingT2:
2065 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2066 Rm = Bits32(opcode, 6, 3);
2067 if (Rn < 8 && Rm < 8)
2068 return false;
2069 if (Rn == 15 || Rm == 15)
2070 return false;
2071 break;
2072 default:
2073 return false;
2074 }
2075 // Read the register value from register Rn.
2076 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2077 if (!success)
2078 return false;
2079 // Read the register value from register Rm.
2080 // The register value is not being shifted since we don't handle ARM for now.
2081 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2082 if (!success)
2083 return false;
2084
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002085 EmulateInstruction::Context context;
2086 context.type = EmulateInstruction::eContextImmediate;
2087 context.SetNoArgs();
2088
Johnny Chene4a4d302011-02-11 21:53:58 +00002089 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2090 m_new_inst_cpsr = m_inst_cpsr;
2091 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2092 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2093 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2094 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2095 if (m_new_inst_cpsr != m_inst_cpsr)
2096 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002097 EmulateInstruction::Context context;
2098 context.type = EmulateInstruction::eContextImmediate;
2099 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002100 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2101 return false;
2102 }
2103 return true;
2104}
2105
Johnny Chen82f16aa2011-02-15 20:10:55 +00002106// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2107// shifting in copies of its sign bit, and writes the result to the destination register. It can
2108// optionally update the condition flags based on the result.
2109bool
2110EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2111{
2112#if 0
2113 // ARM pseudo code...
2114 if ConditionPassed() then
2115 EncodingSpecificOperations();
2116 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2117 if d == 15 then // Can only occur for ARM encoding
2118 ALUWritePC(result); // setflags is always FALSE here
2119 else
2120 R[d] = result;
2121 if setflags then
2122 APSR.N = result<31>;
2123 APSR.Z = IsZeroBit(result);
2124 APSR.C = carry;
2125 // APSR.V unchanged
2126#endif
2127
Johnny Chen41a0a152011-02-16 01:27:54 +00002128 return EmulateShiftImm(encoding, SRType_ASR);
2129}
2130
2131// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2132// shifting in copies of its sign bit, and writes the result to the destination register.
2133// The variable number of bits is read from the bottom byte of a register. It can optionally update
2134// the condition flags based on the result.
2135bool
2136EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2137{
2138#if 0
2139 // ARM pseudo code...
2140 if ConditionPassed() then
2141 EncodingSpecificOperations();
2142 shift_n = UInt(R[m]<7:0>);
2143 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2144 R[d] = result;
2145 if setflags then
2146 APSR.N = result<31>;
2147 APSR.Z = IsZeroBit(result);
2148 APSR.C = carry;
2149 // APSR.V unchanged
2150#endif
2151
2152 return EmulateShiftReg(encoding, SRType_ASR);
2153}
2154
2155// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2156// shifting in zeros, and writes the result to the destination register. It can optionally
2157// update the condition flags based on the result.
2158bool
2159EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2160{
2161#if 0
2162 // ARM pseudo code...
2163 if ConditionPassed() then
2164 EncodingSpecificOperations();
2165 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2166 if d == 15 then // Can only occur for ARM encoding
2167 ALUWritePC(result); // setflags is always FALSE here
2168 else
2169 R[d] = result;
2170 if setflags then
2171 APSR.N = result<31>;
2172 APSR.Z = IsZeroBit(result);
2173 APSR.C = carry;
2174 // APSR.V unchanged
2175#endif
2176
2177 return EmulateShiftImm(encoding, SRType_LSL);
2178}
2179
2180// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2181// shifting in zeros, and writes the result to the destination register. The variable number
2182// of bits is read from the bottom byte of a register. It can optionally update the condition
2183// flags based on the result.
2184bool
2185EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2186{
2187#if 0
2188 // ARM pseudo code...
2189 if ConditionPassed() then
2190 EncodingSpecificOperations();
2191 shift_n = UInt(R[m]<7:0>);
2192 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2193 R[d] = result;
2194 if setflags then
2195 APSR.N = result<31>;
2196 APSR.Z = IsZeroBit(result);
2197 APSR.C = carry;
2198 // APSR.V unchanged
2199#endif
2200
2201 return EmulateShiftReg(encoding, SRType_LSL);
2202}
2203
2204// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2205// shifting in zeros, and writes the result to the destination register. It can optionally
2206// update the condition flags based on the result.
2207bool
2208EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2209{
2210#if 0
2211 // ARM pseudo code...
2212 if ConditionPassed() then
2213 EncodingSpecificOperations();
2214 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2215 if d == 15 then // Can only occur for ARM encoding
2216 ALUWritePC(result); // setflags is always FALSE here
2217 else
2218 R[d] = result;
2219 if setflags then
2220 APSR.N = result<31>;
2221 APSR.Z = IsZeroBit(result);
2222 APSR.C = carry;
2223 // APSR.V unchanged
2224#endif
2225
2226 return EmulateShiftImm(encoding, SRType_LSR);
2227}
2228
2229// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2230// shifting in zeros, and writes the result to the destination register. The variable number
2231// of bits is read from the bottom byte of a register. It can optionally update the condition
2232// flags based on the result.
2233bool
2234EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2235{
2236#if 0
2237 // ARM pseudo code...
2238 if ConditionPassed() then
2239 EncodingSpecificOperations();
2240 shift_n = UInt(R[m]<7:0>);
2241 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2242 R[d] = result;
2243 if setflags then
2244 APSR.N = result<31>;
2245 APSR.Z = IsZeroBit(result);
2246 APSR.C = carry;
2247 // APSR.V unchanged
2248#endif
2249
2250 return EmulateShiftReg(encoding, SRType_LSR);
2251}
2252
2253bool
2254EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2255{
2256 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2257
Johnny Chen82f16aa2011-02-15 20:10:55 +00002258 bool success = false;
2259 const uint32_t opcode = OpcodeAsUnsigned (&success);
2260 if (!success)
2261 return false;
2262
2263 if (ConditionPassed())
2264 {
Johnny Chene7f89532011-02-15 23:22:46 +00002265 uint32_t Rd; // the destination register
2266 uint32_t Rm; // the first operand register
2267 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002268 uint32_t carry; // the carry bit after the shift operation
2269 bool setflags;
2270 switch (encoding) {
2271 case eEncodingT1:
2272 Rd = Bits32(opcode, 2, 0);
2273 Rm = Bits32(opcode, 5, 3);
2274 setflags = !InITBlock();
2275 imm5 = Bits32(opcode, 10, 6);
2276 break;
2277 case eEncodingT2:
2278 Rd = Bits32(opcode, 11, 8);
2279 Rm = Bits32(opcode, 3, 0);
2280 setflags = BitIsSet(opcode, 20);
2281 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2282 if (BadReg(Rd) || BadReg(Rm))
2283 return false;
2284 break;
2285 case eEncodingA1:
2286 Rd = Bits32(opcode, 15, 12);
2287 Rm = Bits32(opcode, 3, 0);
2288 setflags = BitIsSet(opcode, 20);
2289 imm5 = Bits32(opcode, 11, 7);
2290 break;
2291 default:
2292 return false;
2293 }
2294
2295 // Get the first operand.
2296 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2297 if (!success)
2298 return false;
2299
2300 // Decode the shift amount.
Johnny Chen41a0a152011-02-16 01:27:54 +00002301 uint32_t amt = DecodeImmShift(shift_type, imm5);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002302
Johnny Chen41a0a152011-02-16 01:27:54 +00002303 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002304
2305 // The context specifies that an immediate is to be moved into Rd.
2306 EmulateInstruction::Context context;
2307 context.type = EmulateInstruction::eContextImmediate;
2308 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002309
2310 if (Rd == 15)
2311 {
Johnny Chen668b4512011-02-15 21:08:58 +00002312 if (!ALUWritePC (context, result))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002313 return false;
2314 }
2315 else
2316 {
2317 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
2318 return false;
2319 if (setflags)
2320 {
2321 m_new_inst_cpsr = m_inst_cpsr;
2322 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
2323 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
2324 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
2325 if (m_new_inst_cpsr != m_inst_cpsr)
2326 {
2327 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2328 return false;
2329 }
2330 }
2331 }
2332 }
2333 return true;
2334}
2335
Johnny Chene7f89532011-02-15 23:22:46 +00002336bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002337EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002338{
Johnny Chen41a0a152011-02-16 01:27:54 +00002339 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002340
2341 bool success = false;
2342 const uint32_t opcode = OpcodeAsUnsigned (&success);
2343 if (!success)
2344 return false;
2345
2346 if (ConditionPassed())
2347 {
2348 uint32_t Rd; // the destination register
2349 uint32_t Rn; // the first operand register
2350 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2351 uint32_t carry; // the carry bit after the shift operation
2352 bool setflags;
2353 switch (encoding) {
2354 case eEncodingT1:
2355 Rd = Bits32(opcode, 2, 0);
2356 Rn = Rd;
2357 Rm = Bits32(opcode, 5, 3);
2358 setflags = !InITBlock();
2359 break;
2360 case eEncodingT2:
2361 Rd = Bits32(opcode, 11, 8);
2362 Rn = Bits32(opcode, 19, 16);
2363 Rm = Bits32(opcode, 3, 0);
2364 setflags = BitIsSet(opcode, 20);
2365 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2366 return false;
2367 break;
2368 case eEncodingA1:
2369 Rd = Bits32(opcode, 15, 12);
2370 Rn = Bits32(opcode, 3, 0);
2371 Rm = Bits32(opcode, 11, 8);
2372 setflags = BitIsSet(opcode, 20);
2373 if (Rd == 15 || Rn == 15 || Rm == 15)
2374 return false;
2375 break;
2376 default:
2377 return false;
2378 }
2379
2380 // Get the first operand.
2381 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2382 if (!success)
2383 return false;
2384 // Get the Rm register content.
2385 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2386 if (!success)
2387 return false;
2388
2389 // Get the shift amount.
2390 uint32_t amt = Bits32(val, 7, 0);
2391
Johnny Chen41a0a152011-02-16 01:27:54 +00002392 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002393
2394 // The context specifies that an immediate is to be moved into Rd.
2395 EmulateInstruction::Context context;
2396 context.type = EmulateInstruction::eContextImmediate;
2397 context.SetNoArgs ();
2398
2399 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
2400 return false;
2401 if (setflags)
2402 {
2403 m_new_inst_cpsr = m_inst_cpsr;
2404 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
2405 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
2406 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
2407 if (m_new_inst_cpsr != m_inst_cpsr)
2408 {
2409 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2410 return false;
2411 }
2412 }
2413 }
2414 return true;
2415}
2416
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002417// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002418// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002419// can be written back to the base register.
2420bool
2421EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2422{
2423#if 0
2424 // ARM pseudo code...
2425 if ConditionPassed()
2426 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2427 address = R[n];
2428
2429 for i = 0 to 14
2430 if registers<i> == '1' then
2431 R[i] = MemA[address, 4]; address = address + 4;
2432 if registers<15> == '1' then
2433 LoadWritePC (MemA[address, 4]);
2434
2435 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2436 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2437
2438#endif
2439
2440 bool success = false;
2441 const uint32_t opcode = OpcodeAsUnsigned (&success);
2442 if (!success)
2443 return false;
2444
2445 if (ConditionPassed())
2446 {
2447 uint32_t n;
2448 uint32_t registers = 0;
2449 bool wback;
2450 const uint32_t addr_byte_size = GetAddressByteSize();
2451 switch (encoding)
2452 {
2453 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002454 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002455 n = Bits32 (opcode, 10, 8);
2456 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002457 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002458 wback = BitIsClear (registers, n);
2459 // if BitCount(registers) < 1 then UNPREDICTABLE;
2460 if (BitCount(registers) < 1)
2461 return false;
2462 break;
2463 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002464 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2465 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002466 n = Bits32 (opcode, 19, 16);
2467 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002468 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002469 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002470
2471 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002472 if ((n == 15)
2473 || (BitCount (registers) < 2)
2474 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2475 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002476
2477 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002478 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002479 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002480
2481 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002482 if (wback
2483 && BitIsSet (registers, n))
2484 return false;
2485 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002486
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002487 case eEncodingA1:
2488 n = Bits32 (opcode, 19, 16);
2489 registers = Bits32 (opcode, 15, 0);
2490 wback = BitIsSet (opcode, 21);
2491 if ((n == 15)
2492 || (BitCount (registers) < 1))
2493 return false;
2494 break;
2495 default:
2496 return false;
2497 }
2498
2499 int32_t offset = 0;
2500 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2501 if (!success)
2502 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002503
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002504 EmulateInstruction::Context context;
2505 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2506 Register dwarf_reg;
2507 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2508 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002509
2510 for (int i = 0; i < 14; ++i)
2511 {
2512 if (BitIsSet (registers, i))
2513 {
Caroline Tice85aab332011-02-08 23:56:10 +00002514 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002515 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002516 if (wback && (n == 13)) // Pop Instruction
2517 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2518
2519 // R[i] = MemA [address, 4]; address = address + 4;
2520 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2521 if (!success)
2522 return false;
2523
2524 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2525 return false;
2526
2527 offset += addr_byte_size;
2528 }
2529 }
2530
2531 if (BitIsSet (registers, 15))
2532 {
2533 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002534 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002535 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002536 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2537 if (!success)
2538 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002539 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002540 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002541 return false;
2542 }
2543
2544 if (wback && BitIsClear (registers, n))
2545 {
Caroline Ticefa172202011-02-11 22:49:54 +00002546 // R[n] = R[n] + 4 * BitCount (registers)
2547 int32_t offset = addr_byte_size * BitCount (registers);
2548 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002549 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002550
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002551 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2552 return false;
2553 }
2554 if (wback && BitIsSet (registers, n))
2555 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002556 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002557 }
2558 return true;
2559}
Caroline Tice713c2662011-02-11 17:59:55 +00002560
2561// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2562// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2563// can optionally be written back tot he base registers.
2564bool
2565EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2566{
2567#if 0
2568 // ARM pseudo code...
2569 if ConditionPassed() then
2570 EncodingSpecificOperations();
2571 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002572
Caroline Tice713c2662011-02-11 17:59:55 +00002573 for i = 0 to 14
2574 if registers<i> == ’1’ then
2575 R[i] = MemA[address,4]; address = address + 4;
2576
2577 if registers<15> == ’1’ then
2578 LoadWritePC(MemA[address,4]);
2579
2580 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2581 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2582#endif
2583
2584 bool success = false;
2585 const uint32_t opcode = OpcodeAsUnsigned (&success);
2586 if (!success)
2587 return false;
2588
2589 if (ConditionPassed())
2590 {
2591 uint32_t n;
2592 uint32_t registers = 0;
2593 bool wback;
2594 const uint32_t addr_byte_size = GetAddressByteSize();
2595
2596 // EncodingSpecificOperations();
2597 switch (encoding)
2598 {
2599 case eEncodingA1:
2600 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2601 n = Bits32 (opcode, 19, 16);
2602 registers = Bits32 (opcode, 15, 0);
2603 wback = BitIsSet (opcode, 21);
2604
2605 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2606 if ((n == 15) || (BitCount (registers) < 1))
2607 return false;
2608
2609 break;
2610
2611 default:
2612 return false;
2613 }
2614 // address = R[n] - 4*BitCount(registers) + 4;
2615
2616 int32_t offset = 0;
2617 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2618
2619 if (!success)
2620 return false;
2621
2622 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2623
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002624 EmulateInstruction::Context context;
2625 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2626 Register dwarf_reg;
2627 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2628 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002629
2630 // for i = 0 to 14
2631 for (int i = 0; i < 14; ++i)
2632 {
2633 // if registers<i> == ’1’ then
2634 if (BitIsSet (registers, i))
2635 {
2636 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002637 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002638 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2639 if (!success)
2640 return false;
2641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2642 return false;
2643 offset += addr_byte_size;
2644 }
2645 }
2646
2647 // if registers<15> == ’1’ then
2648 // LoadWritePC(MemA[address,4]);
2649 if (BitIsSet (registers, 15))
2650 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002651 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002652 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2653 if (!success)
2654 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002655 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002656 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002657 return false;
2658 }
2659
2660 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2661 if (wback && BitIsClear (registers, n))
2662 {
Caroline Tice713c2662011-02-11 17:59:55 +00002663 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2664 if (!success)
2665 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002666
2667 offset = (addr_byte_size * BitCount (registers)) * -1;
2668 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002669 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002670 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002671 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2672 return false;
2673 }
2674
2675 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2676 if (wback && BitIsSet (registers, n))
2677 return WriteBits32Unknown (n);
2678 }
2679 return true;
2680}
2681
2682// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2683// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2684// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002685bool
2686EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2687{
2688#if 0
2689 // ARM pseudo code...
2690 if ConditionPassed() then
2691 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2692 address = R[n] - 4*BitCount(registers);
2693
2694 for i = 0 to 14
2695 if registers<i> == ’1’ then
2696 R[i] = MemA[address,4]; address = address + 4;
2697 if registers<15> == ’1’ then
2698 LoadWritePC(MemA[address,4]);
2699
2700 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2701 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2702#endif
2703
2704 bool success = false;
2705 const uint32_t opcode = OpcodeAsUnsigned (&success);
2706 if (!success)
2707 return false;
2708
2709 if (ConditionPassed())
2710 {
2711 uint32_t n;
2712 uint32_t registers = 0;
2713 bool wback;
2714 const uint32_t addr_byte_size = GetAddressByteSize();
2715 switch (encoding)
2716 {
2717 case eEncodingT1:
2718 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2719 n = Bits32 (opcode, 19, 16);
2720 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002721 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002722 wback = BitIsSet (opcode, 21);
2723
2724 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2725 if ((n == 15)
2726 || (BitCount (registers) < 2)
2727 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2728 return false;
2729
2730 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002731 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002732 return false;
2733
2734 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2735 if (wback && BitIsSet (registers, n))
2736 return false;
2737
2738 break;
2739
2740 case eEncodingA1:
2741 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2742 n = Bits32 (opcode, 19, 16);
2743 registers = Bits32 (opcode, 15, 0);
2744 wback = BitIsSet (opcode, 21);
2745
2746 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2747 if ((n == 15) || (BitCount (registers) < 1))
2748 return false;
2749
2750 break;
2751
2752 default:
2753 return false;
2754 }
2755
Caroline Tice713c2662011-02-11 17:59:55 +00002756 // address = R[n] - 4*BitCount(registers);
2757
Caroline Tice0b29e242011-02-08 23:16:02 +00002758 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002759 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2760
2761 if (!success)
2762 return false;
2763
2764 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002765 EmulateInstruction::Context context;
2766 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2767 Register dwarf_reg;
2768 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2769 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002770
2771 for (int i = 0; i < 14; ++i)
2772 {
2773 if (BitIsSet (registers, i))
2774 {
2775 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002776 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002777 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2778 if (!success)
2779 return false;
2780
2781 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2782 return false;
2783
2784 offset += addr_byte_size;
2785 }
2786 }
2787
2788 // if registers<15> == ’1’ then
2789 // LoadWritePC(MemA[address,4]);
2790 if (BitIsSet (registers, 15))
2791 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002792 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002793 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2794 if (!success)
2795 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002796 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002797 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002798 return false;
2799 }
2800
2801 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2802 if (wback && BitIsClear (registers, n))
2803 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002804 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2805 if (!success)
2806 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002807
2808 offset = (addr_byte_size * BitCount (registers)) * -1;
2809 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002810 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002811 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002812 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2813 return false;
2814 }
2815
2816 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2817 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002818 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002819 }
2820 return true;
2821}
Caroline Tice85aab332011-02-08 23:56:10 +00002822
Caroline Tice713c2662011-02-11 17:59:55 +00002823// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2824// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2825// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002826bool
2827EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2828{
2829#if 0
2830 if ConditionPassed() then
2831 EncodingSpecificOperations();
2832 address = R[n] + 4;
2833
2834 for i = 0 to 14
2835 if registers<i> == ’1’ then
2836 R[i] = MemA[address,4]; address = address + 4;
2837 if registers<15> == ’1’ then
2838 LoadWritePC(MemA[address,4]);
2839
2840 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2841 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2842#endif
2843
2844 bool success = false;
2845 const uint32_t opcode = OpcodeAsUnsigned (&success);
2846 if (!success)
2847 return false;
2848
2849 if (ConditionPassed())
2850 {
2851 uint32_t n;
2852 uint32_t registers = 0;
2853 bool wback;
2854 const uint32_t addr_byte_size = GetAddressByteSize();
2855 switch (encoding)
2856 {
2857 case eEncodingA1:
2858 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2859 n = Bits32 (opcode, 19, 16);
2860 registers = Bits32 (opcode, 15, 0);
2861 wback = BitIsSet (opcode, 21);
2862
2863 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2864 if ((n == 15) || (BitCount (registers) < 1))
2865 return false;
2866
2867 break;
2868 default:
2869 return false;
2870 }
2871 // address = R[n] + 4;
2872
2873 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002874 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2875
2876 if (!success)
2877 return false;
2878
2879 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002880
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002881 EmulateInstruction::Context context;
2882 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2883 Register dwarf_reg;
2884 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2885 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002886
2887 for (int i = 0; i < 14; ++i)
2888 {
2889 if (BitIsSet (registers, i))
2890 {
2891 // R[i] = MemA[address,4]; address = address + 4;
2892
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002893 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002894 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2895 if (!success)
2896 return false;
2897
2898 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2899 return false;
2900
2901 offset += addr_byte_size;
2902 }
2903 }
2904
2905 // if registers<15> == ’1’ then
2906 // LoadWritePC(MemA[address,4]);
2907 if (BitIsSet (registers, 15))
2908 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002909 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002910 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2911 if (!success)
2912 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002913 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002914 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002915 return false;
2916 }
2917
2918 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2919 if (wback && BitIsClear (registers, n))
2920 {
Caroline Tice85aab332011-02-08 23:56:10 +00002921 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2922 if (!success)
2923 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002924
2925 offset = addr_byte_size * BitCount (registers);
2926 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002927 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002928 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002929 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2930 return false;
2931 }
2932
2933 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2934 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002935 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002936 }
2937 return true;
2938}
Caroline Tice0b29e242011-02-08 23:16:02 +00002939
Johnny Chenef21b592011-02-10 01:52:38 +00002940// Load Register (immediate) calculates an address from a base register value and
2941// an immediate offset, loads a word from memory, and writes to a register.
2942// LDR (immediate, Thumb)
2943bool
2944EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2945{
2946#if 0
2947 // ARM pseudo code...
2948 if (ConditionPassed())
2949 {
2950 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2951 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2952 address = if index then offset_addr else R[n];
2953 data = MemU[address,4];
2954 if wback then R[n] = offset_addr;
2955 if t == 15 then
2956 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2957 elsif UnalignedSupport() || address<1:0> = '00' then
2958 R[t] = data;
2959 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2960 }
2961#endif
2962
2963 bool success = false;
2964 const uint32_t opcode = OpcodeAsUnsigned (&success);
2965 if (!success)
2966 return false;
2967
2968 if (ConditionPassed())
2969 {
2970 uint32_t Rt; // the destination register
2971 uint32_t Rn; // the base register
2972 uint32_t imm32; // the immediate offset used to form the address
2973 addr_t offset_addr; // the offset address
2974 addr_t address; // the calculated address
2975 uint32_t data; // the literal data value from memory load
2976 bool add, index, wback;
2977 switch (encoding) {
2978 case eEncodingT1:
2979 Rt = Bits32(opcode, 5, 3);
2980 Rn = Bits32(opcode, 2, 0);
2981 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2982 // index = TRUE; add = TRUE; wback = FALSE
2983 add = true;
2984 index = true;
2985 wback = false;
2986 break;
2987 default:
2988 return false;
2989 }
2990 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2991 if (!success)
2992 return false;
2993 if (add)
2994 offset_addr = base + imm32;
2995 else
2996 offset_addr = base - imm32;
2997
2998 address = (index ? offset_addr : base);
2999
3000 if (wback)
3001 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003002 EmulateInstruction::Context ctx;
3003 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3004 Register dwarf_reg;
3005 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3006 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3007
Johnny Chenef21b592011-02-10 01:52:38 +00003008 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3009 return false;
3010 }
3011
3012 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003013 EmulateInstruction::Context context;
3014 context.type = EmulateInstruction::eContextImmediate;
3015 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003016
3017 // Read memory from the address.
3018 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
3019 if (!success)
3020 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003021
3022 if (Rt == 15)
3023 {
3024 if (Bits32(address, 1, 0) == 0)
3025 {
Johnny Chen668b4512011-02-15 21:08:58 +00003026 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003027 return false;
3028 }
3029 else
3030 return false;
3031 }
3032 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3033 {
3034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3035 return false;
3036 }
3037 else
3038 return false;
3039 }
3040 return true;
3041}
3042
Caroline Ticeaf556562011-02-15 18:42:15 +00003043// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3044// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3045// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003046bool
3047EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3048{
3049#if 0
3050 if ConditionPassed() then
3051 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3052 address = R[n];
3053
3054 for i = 0 to 14
3055 if registers<i> == ’1’ then
3056 if i == n && wback && i != LowestSetBit(registers) then
3057 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3058 else
3059 MemA[address,4] = R[i];
3060 address = address + 4;
3061
3062 if registers<15> == ’1’ then // Only possible for encoding A1
3063 MemA[address,4] = PCStoreValue();
3064 if wback then R[n] = R[n] + 4*BitCount(registers);
3065#endif
3066
3067 bool success = false;
3068 const uint32_t opcode = OpcodeAsUnsigned (&success);
3069 if (!success)
3070 return false;
3071
3072 if (ConditionPassed ())
3073 {
3074 uint32_t n;
3075 uint32_t registers = 0;
3076 bool wback;
3077 const uint32_t addr_byte_size = GetAddressByteSize();
3078
3079 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3080 switch (encoding)
3081 {
3082 case eEncodingT1:
3083 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3084 n = Bits32 (opcode, 10, 8);
3085 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003086 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003087 wback = true;
3088
3089 // if BitCount(registers) < 1 then UNPREDICTABLE;
3090 if (BitCount (registers) < 1)
3091 return false;
3092
3093 break;
3094
3095 case eEncodingT2:
3096 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3097 n = Bits32 (opcode, 19, 16);
3098 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003099 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003100 wback = BitIsSet (opcode, 21);
3101
3102 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3103 if ((n == 15) || (BitCount (registers) < 2))
3104 return false;
3105
3106 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3107 if (wback && BitIsSet (registers, n))
3108 return false;
3109
3110 break;
3111
3112 case eEncodingA1:
3113 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3114 n = Bits32 (opcode, 19, 16);
3115 registers = Bits32 (opcode, 15, 0);
3116 wback = BitIsSet (opcode, 21);
3117
3118 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3119 if ((n == 15) || (BitCount (registers) < 1))
3120 return false;
3121
3122 break;
3123
3124 default:
3125 return false;
3126 }
3127
3128 // address = R[n];
3129 int32_t offset = 0;
3130 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3131 if (!success)
3132 return false;
3133
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003134 EmulateInstruction::Context context;
3135 context.type = EmulateInstruction::eContextRegisterStore;
3136 Register base_reg;
3137 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003138
3139 // for i = 0 to 14
3140 for (int i = 0; i < 14; ++i)
3141 {
3142 int lowest_set_bit = 14;
3143 // if registers<i> == ’1’ then
3144 if (BitIsSet (registers, i))
3145 {
3146 if (i < lowest_set_bit)
3147 lowest_set_bit = i;
3148 // if i == n && wback && i != LowestSetBit(registers) then
3149 if ((i == n) && wback && (i != lowest_set_bit))
3150 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3151 WriteBits32UnknownToMemory (address + offset);
3152 else
3153 {
3154 // MemA[address,4] = R[i];
3155 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3156 if (!success)
3157 return false;
3158
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003159 Register data_reg;
3160 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3161 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003162 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3163 return false;
3164 }
3165
3166 // address = address + 4;
3167 offset += addr_byte_size;
3168 }
3169 }
3170
3171 // if registers<15> == ’1’ then // Only possible for encoding A1
3172 // MemA[address,4] = PCStoreValue();
3173 if (BitIsSet (registers, 15))
3174 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003175 Register pc_reg;
3176 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3177 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003178 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3179 if (!success)
3180 return false;
3181
3182 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3183 return false;
3184 }
3185
3186 // if wback then R[n] = R[n] + 4*BitCount(registers);
3187 if (wback)
3188 {
3189 offset = addr_byte_size * BitCount (registers);
3190 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003191 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003192 addr_t data = address + offset;
3193 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3194 return false;
3195 }
3196 }
3197 return true;
3198}
3199
Caroline Ticeaf556562011-02-15 18:42:15 +00003200// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3201// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3202// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003203bool
3204EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3205{
3206#if 0
3207 if ConditionPassed() then
3208 EncodingSpecificOperations();
3209 address = R[n] - 4*BitCount(registers) + 4;
3210
3211 for i = 0 to 14
3212 if registers<i> == ’1’ then
3213 if i == n && wback && i != LowestSetBit(registers) then
3214 MemA[address,4] = bits(32) UNKNOWN;
3215 else
3216 MemA[address,4] = R[i];
3217 address = address + 4;
3218
3219 if registers<15> == ’1’ then
3220 MemA[address,4] = PCStoreValue();
3221
3222 if wback then R[n] = R[n] - 4*BitCount(registers);
3223#endif
3224
3225 bool success = false;
3226 const uint32_t opcode = OpcodeAsUnsigned (&success);
3227 if (!success)
3228 return false;
3229
3230 if (ConditionPassed ())
3231 {
3232 uint32_t n;
3233 uint32_t registers = 0;
3234 bool wback;
3235 const uint32_t addr_byte_size = GetAddressByteSize();
3236
3237 // EncodingSpecificOperations();
3238 switch (encoding)
3239 {
3240 case eEncodingA1:
3241 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3242 n = Bits32 (opcode, 19, 16);
3243 registers = Bits32 (opcode, 15, 0);
3244 wback = BitIsSet (opcode, 21);
3245
3246 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3247 if ((n == 15) || (BitCount (registers) < 1))
3248 return false;
3249 break;
3250 default:
3251 return false;
3252 }
3253
3254 // address = R[n] - 4*BitCount(registers) + 4;
3255 int32_t offset = 0;
3256 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3257 if (!success)
3258 return false;
3259
3260 address = address - (addr_byte_size * BitCount (registers)) + 4;
3261
3262 EmulateInstruction::Context context;
3263 context.type = EmulateInstruction::eContextRegisterStore;
3264 Register base_reg;
3265 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3266
3267 // for i = 0 to 14
3268 for (int i = 0; i < 14; ++i)
3269 {
3270 int lowest_bit_set = 14;
3271 // if registers<i> == ’1’ then
3272 if (BitIsSet (registers, i))
3273 {
3274 if (i < lowest_bit_set)
3275 lowest_bit_set = i;
3276 //if i == n && wback && i != LowestSetBit(registers) then
3277 if ((i == n) && wback && (i != lowest_bit_set))
3278 // MemA[address,4] = bits(32) UNKNOWN;
3279 WriteBits32UnknownToMemory (address + offset);
3280 else
3281 {
3282 // MemA[address,4] = R[i];
3283 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3284 if (!success)
3285 return false;
3286
3287 Register data_reg;
3288 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3289 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3290 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3291 return false;
3292 }
3293
3294 // address = address + 4;
3295 offset += addr_byte_size;
3296 }
3297 }
3298
3299 // if registers<15> == ’1’ then
3300 // MemA[address,4] = PCStoreValue();
3301 if (BitIsSet (registers, 15))
3302 {
3303 Register pc_reg;
3304 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3305 context.SetRegisterPlusOffset (pc_reg, 8);
3306 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3307 if (!success)
3308 return false;
3309
3310 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3311 return false;
3312 }
3313
3314 // if wback then R[n] = R[n] - 4*BitCount(registers);
3315 if (wback)
3316 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003317 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003318 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3319 context.SetImmediateSigned (offset);
3320 addr_t data = address + offset;
3321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3322 return false;
3323 }
3324 }
3325 return true;
3326}
3327
Caroline Ticeaf556562011-02-15 18:42:15 +00003328// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3329// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3330// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003331bool
3332EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3333{
3334#if 0
3335 if ConditionPassed() then
3336 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3337 address = R[n] - 4*BitCount(registers);
3338
3339 for i = 0 to 14
3340 if registers<i> == ’1’ then
3341 if i == n && wback && i != LowestSetBit(registers) then
3342 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3343 else
3344 MemA[address,4] = R[i];
3345 address = address + 4;
3346
3347 if registers<15> == ’1’ then // Only possible for encoding A1
3348 MemA[address,4] = PCStoreValue();
3349
3350 if wback then R[n] = R[n] - 4*BitCount(registers);
3351#endif
3352
3353
3354 bool success = false;
3355 const uint32_t opcode = OpcodeAsUnsigned (&success);
3356 if (!success)
3357 return false;
3358
3359 if (ConditionPassed ())
3360 {
3361 uint32_t n;
3362 uint32_t registers = 0;
3363 bool wback;
3364 const uint32_t addr_byte_size = GetAddressByteSize();
3365
3366 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3367 switch (encoding)
3368 {
3369 case eEncodingT1:
3370 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3371 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3372 {
3373 // See PUSH
3374 }
3375 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3376 n = Bits32 (opcode, 19, 16);
3377 registers = Bits32 (opcode, 15, 0);
3378 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3379 wback = BitIsSet (opcode, 21);
3380 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3381 if ((n == 15) || BitCount (registers) < 2)
3382 return false;
3383 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3384 if (wback && BitIsSet (registers, n))
3385 return false;
3386 break;
3387
3388 case eEncodingA1:
3389 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3390 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3391 {
3392 // See Push
3393 }
3394 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3395 n = Bits32 (opcode, 19, 16);
3396 registers = Bits32 (opcode, 15, 0);
3397 wback = BitIsSet (opcode, 21);
3398 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3399 if ((n == 15) || BitCount (registers) < 1)
3400 return false;
3401 break;
3402
3403 default:
3404 return false;
3405 }
3406
3407 // address = R[n] - 4*BitCount(registers);
3408
3409 int32_t offset = 0;
3410 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3411 if (!success)
3412 return false;
3413
3414 address = address - (addr_byte_size * BitCount (registers));
3415
3416 EmulateInstruction::Context context;
3417 context.type = EmulateInstruction::eContextRegisterStore;
3418 Register base_reg;
3419 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3420
3421 // for i = 0 to 14
3422 for (int i = 0; i < 14; ++i)
3423 {
3424 uint32_t lowest_set_bit = 14;
3425 // if registers<i> == ’1’ then
3426 if (BitIsSet (registers, i))
3427 {
3428 if (i < lowest_set_bit)
3429 lowest_set_bit = i;
3430 // if i == n && wback && i != LowestSetBit(registers) then
3431 if ((i == n) && wback && (i != lowest_set_bit))
3432 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3433 WriteBits32UnknownToMemory (address + offset);
3434 else
3435 {
3436 // MemA[address,4] = R[i];
3437 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3438 if (!success)
3439 return false;
3440
3441 Register data_reg;
3442 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3443 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3444 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3445 return false;
3446 }
3447
3448 // address = address + 4;
3449 offset += addr_byte_size;
3450 }
3451 }
3452
3453 // if registers<15> == ’1’ then // Only possible for encoding A1
3454 // MemA[address,4] = PCStoreValue();
3455 if (BitIsSet (registers, 15))
3456 {
3457 Register pc_reg;
3458 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3459 context.SetRegisterPlusOffset (pc_reg, 8);
3460 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3461 if (!success)
3462 return false;
3463
3464 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3465 return false;
3466 }
3467
3468 // if wback then R[n] = R[n] - 4*BitCount(registers);
3469 if (wback)
3470 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003471 offset = (addr_byte_size * BitCount (registers)) * -1;
3472 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3473 context.SetImmediateSigned (offset);
3474 addr_t data = address + offset;
3475 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3476 return false;
3477 }
3478 }
3479 return true;
3480}
3481
3482// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3483// from a base register. The consecutive memory locations start just above this address, and the address of the last
3484// of those locations can optionally be written back to the base register.
3485bool
3486EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3487{
3488#if 0
3489 if ConditionPassed() then
3490 EncodingSpecificOperations();
3491 address = R[n] + 4;
3492
3493 for i = 0 to 14
3494 if registers<i> == ’1’ then
3495 if i == n && wback && i != LowestSetBit(registers) then
3496 MemA[address,4] = bits(32) UNKNOWN;
3497 else
3498 MemA[address,4] = R[i];
3499 address = address + 4;
3500
3501 if registers<15> == ’1’ then
3502 MemA[address,4] = PCStoreValue();
3503
3504 if wback then R[n] = R[n] + 4*BitCount(registers);
3505#endif
3506
3507 bool success = false;
3508 const uint32_t opcode = OpcodeAsUnsigned (&success);
3509 if (!success)
3510 return false;
3511
3512 if (ConditionPassed())
3513 {
3514 uint32_t n;
3515 uint32_t registers = 0;
3516 bool wback;
3517 const uint32_t addr_byte_size = GetAddressByteSize();
3518
3519 // EncodingSpecificOperations();
3520 switch (encoding)
3521 {
3522 case eEncodingA1:
3523 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3524 n = Bits32 (opcode, 19, 16);
3525 registers = Bits32 (opcode, 15, 0);
3526 wback = BitIsSet (opcode, 21);
3527
3528 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3529 if ((n == 15) && (BitCount (registers) < 1))
3530 return false;
3531 break;
3532 default:
3533 return false;
3534 }
3535 // address = R[n] + 4;
3536
3537 int32_t offset = 0;
3538 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3539 if (!success)
3540 return false;
3541
3542 address = address + addr_byte_size;
3543
3544 EmulateInstruction::Context context;
3545 context.type = EmulateInstruction::eContextRegisterStore;
3546 Register base_reg;
3547 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3548
3549 uint32_t lowest_set_bit = 14;
3550 // for i = 0 to 14
3551 for (int i = 0; i < 14; ++i)
3552 {
3553 // if registers<i> == ’1’ then
3554 if (BitIsSet (registers, i))
3555 {
3556 if (i < lowest_set_bit)
3557 lowest_set_bit = i;
3558 // if i == n && wback && i != LowestSetBit(registers) then
3559 if ((i == n) && wback && (i != lowest_set_bit))
3560 // MemA[address,4] = bits(32) UNKNOWN;
3561 WriteBits32UnknownToMemory (address + offset);
3562 // else
3563 else
3564 {
3565 // MemA[address,4] = R[i];
3566 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3567 if (!success)
3568 return false;
3569
3570 Register data_reg;
3571 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3572 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3573 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3574 return false;
3575 }
3576
3577 // address = address + 4;
3578 offset += addr_byte_size;
3579 }
3580 }
3581
3582 // if registers<15> == ’1’ then
3583 // MemA[address,4] = PCStoreValue();
3584 if (BitIsSet (registers, 15))
3585 {
3586 Register pc_reg;
3587 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3588 context.SetRegisterPlusOffset (pc_reg, 8);
3589 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3590 if (!success)
3591 return false;
3592
3593 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3594 return false;
3595 }
3596
3597 // if wback then R[n] = R[n] + 4*BitCount(registers);
3598 if (wback)
3599 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003600 offset = addr_byte_size * BitCount (registers);
3601 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3602 context.SetImmediateSigned (offset);
3603 addr_t data = address + offset;
3604 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3605 return false;
3606 }
3607 }
3608 return true;
3609}
Caroline Tice7fac8572011-02-15 22:53:54 +00003610
3611// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3612// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3613bool
3614EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3615{
3616#if 0
3617 if ConditionPassed() then
3618 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3619 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3620 address = if index then offset_addr else R[n];
3621 if UnalignedSupport() || address<1:0> == ’00’ then
3622 MemU[address,4] = R[t];
3623 else // Can only occur before ARMv7
3624 MemU[address,4] = bits(32) UNKNOWN;
3625 if wback then R[n] = offset_addr;
3626#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003627
Caroline Tice7fac8572011-02-15 22:53:54 +00003628 bool success = false;
3629 const uint32_t opcode = OpcodeAsUnsigned (&success);
3630 if (!success)
3631 return false;
3632
3633 if (ConditionPassed())
3634 {
3635 const uint32_t addr_byte_size = GetAddressByteSize();
3636
3637 uint32_t t;
3638 uint32_t n;
3639 uint32_t imm32;
3640 bool index;
3641 bool add;
3642 bool wback;
3643 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3644 switch (encoding)
3645 {
3646 case eEncodingT1:
3647 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3648 t = Bits32 (opcode, 2, 0);
3649 n = Bits32 (opcode, 5, 3);
3650 imm32 = Bits32 (opcode, 10, 6) << 2;
3651
3652 // index = TRUE; add = TRUE; wback = FALSE;
3653 index = true;
3654 add = false;
3655 wback = false;
3656 break;
3657
3658 case eEncodingT2:
3659 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3660 t = Bits32 (opcode, 10, 8);
3661 n = 13;
3662 imm32 = Bits32 (opcode, 7, 0) << 2;
3663
3664 // index = TRUE; add = TRUE; wback = FALSE;
3665 index = true;
3666 add = true;
3667 wback = false;
3668 break;
3669
3670 case eEncodingT3:
3671 // if Rn == ’1111’ then UNDEFINED;
3672 if (Bits32 (opcode, 19, 16) == 15)
3673 return false;
3674
3675 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3676 t = Bits32 (opcode, 15, 12);
3677 n = Bits32 (opcode, 19, 16);
3678 imm32 = Bits32 (opcode, 11, 0);
3679
3680 // index = TRUE; add = TRUE; wback = FALSE;
3681 index = true;
3682 add = true;
3683 wback = false;
3684
3685 // if t == 15 then UNPREDICTABLE;
3686 if (t == 15)
3687 return false;
3688 break;
3689
3690 case eEncodingT4:
3691 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3692 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3693 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3694 if ((Bits32 (opcode, 19, 16) == 15)
3695 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3696 return false;
3697
3698 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3699 t = Bits32 (opcode, 15, 12);
3700 n = Bits32 (opcode, 19, 16);
3701 imm32 = Bits32 (opcode, 7, 0);
3702
3703 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3704 index = BitIsSet (opcode, 10);
3705 add = BitIsSet (opcode, 9);
3706 wback = BitIsSet (opcode, 8);
3707
3708 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3709 if ((t == 15) || (wback && (n == t)))
3710 return false;
3711 break;
3712
3713 default:
3714 return false;
3715 }
3716
3717 addr_t offset_addr;
3718 addr_t address;
3719
3720 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3721 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3722 if (!success)
3723 return false;
3724
3725 if (add)
3726 offset_addr = base_address + imm32;
3727 else
3728 offset_addr = base_address - imm32;
3729
3730 // address = if index then offset_addr else R[n];
3731 if (index)
3732 address = offset_addr;
3733 else
3734 address = base_address;
3735
3736 EmulateInstruction::Context context;
3737 context.type = eContextRegisterStore;
3738 Register base_reg;
3739 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3740
3741 // if UnalignedSupport() || address<1:0> == ’00’ then
3742 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3743 {
3744 // MemU[address,4] = R[t];
3745 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3746 if (!success)
3747 return false;
3748
3749 Register data_reg;
3750 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3751 int32_t offset = address - base_address;
3752 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3753 if (!WriteMemoryUnsigned (context, address, data, addr_byte_size))
3754 return false;
3755 }
3756 else
3757 {
3758 // MemU[address,4] = bits(32) UNKNOWN;
3759 WriteBits32UnknownToMemory (address);
3760 }
3761
3762 // if wback then R[n] = offset_addr;
3763 if (wback)
3764 {
3765 context.type = eContextRegisterLoad;
3766 context.SetAddress (offset_addr);
3767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3768 return false;
3769 }
3770 }
3771 return true;
3772}
Caroline Ticeaf556562011-02-15 18:42:15 +00003773
Caroline Tice3fd63e92011-02-16 00:33:43 +00003774// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3775// word from a register to memory. The offset register value can optionally be shifted.
3776bool
3777EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3778{
3779#if 0
3780 if ConditionPassed() then
3781 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3782 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3783 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3784 address = if index then offset_addr else R[n];
3785 if t == 15 then // Only possible for encoding A1
3786 data = PCStoreValue();
3787 else
3788 data = R[t];
3789 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3790 MemU[address,4] = data;
3791 else // Can only occur before ARMv7
3792 MemU[address,4] = bits(32) UNKNOWN;
3793 if wback then R[n] = offset_addr;
3794#endif
3795
3796 bool success = false;
3797 const uint32_t opcode = OpcodeAsUnsigned (&success);
3798 if (!success)
3799 return false;
3800
3801 if (ConditionPassed())
3802 {
3803 const uint32_t addr_byte_size = GetAddressByteSize();
3804
3805 uint32_t t;
3806 uint32_t n;
3807 uint32_t m;
3808 ARM_ShifterType shift_t;
3809 uint32_t shift_n;
3810 bool index;
3811 bool add;
3812 bool wback;
3813
3814 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3815 switch (encoding)
3816 {
3817 case eEncodingT1:
3818 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3819 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3820 t = Bits32 (opcode, 2, 0);
3821 n = Bits32 (opcode, 5, 3);
3822 m = Bits32 (opcode, 8, 6);
3823
3824 // index = TRUE; add = TRUE; wback = FALSE;
3825 index = true;
3826 add = true;
3827 wback = false;
3828
3829 // (shift_t, shift_n) = (SRType_LSL, 0);
3830 shift_t = SRType_LSL;
3831 shift_n = 0;
3832 break;
3833
3834 case eEncodingT2:
3835 // if Rn == ’1111’ then UNDEFINED;
3836 if (Bits32 (opcode, 19, 16) == 15)
3837 return false;
3838
3839 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3840 t = Bits32 (opcode, 15, 12);
3841 n = Bits32 (opcode, 19, 16);
3842 m = Bits32 (opcode, 3, 0);
3843
3844 // index = TRUE; add = TRUE; wback = FALSE;
3845 index = true;
3846 add = true;
3847 wback = false;
3848
3849 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3850 shift_t = SRType_LSL;
3851 shift_n = Bits32 (opcode, 5, 4);
3852
3853 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3854 if ((t == 15) || (BadReg (m)))
3855 return false;
3856 break;
3857
3858 case eEncodingA1:
3859 {
3860 // if P == ’0’ && W == ’1’ then SEE STRT;
3861 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3862 t = Bits32 (opcode, 15, 12);
3863 n = Bits32 (opcode, 19, 16);
3864 m = Bits32 (opcode, 3, 0);
3865
3866 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3867 index = BitIsSet (opcode, 24);
3868 add = BitIsSet (opcode, 23);
3869 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3870
3871 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3872 uint32_t typ = Bits32 (opcode, 6, 5);
3873 uint32_t imm5 = Bits32 (opcode, 11, 7);
3874 shift_n = DecodeImmShift(typ, imm5, shift_t);
3875
3876 // if m == 15 then UNPREDICTABLE;
3877 if (m == 15)
3878 return false;
3879
3880 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3881 if (wback && ((n == 15) || (n == t)))
3882 return false;
3883
3884 break;
3885 }
3886 default:
3887 return false;
3888 }
3889
3890 addr_t offset_addr;
3891 addr_t address;
3892 int32_t offset = 0;
3893
3894 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3895 if (!success)
3896 return false;
3897
3898 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3899 if (!success)
3900 return false;
3901
3902 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
3903 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
3904
3905 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3906 if (add)
3907 offset_addr = base_address + offset;
3908 else
3909 offset_addr = base_address - offset;
3910
3911 // address = if index then offset_addr else R[n];
3912 if (index)
3913 address = offset_addr;
3914 else
3915 address = base_address;
3916
3917 uint32_t data;
3918 // if t == 15 then // Only possible for encoding A1
3919 if (t == 15)
3920 // data = PCStoreValue();
3921 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3922 else
3923 // data = R[t];
3924 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3925
3926 if (!success)
3927 return false;
3928
3929 EmulateInstruction::Context context;
3930 context.type = eContextRegisterStore;
3931
3932 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3933 if (UnalignedSupport ()
3934 || (BitIsClear (address, 1) && BitIsClear (address, 0))
3935 || CurrentInstrSet() == eModeARM)
3936 {
3937 // MemU[address,4] = data;
3938
3939 Register base_reg;
3940 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3941
3942 Register data_reg;
3943 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3944
3945 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
3946 if (!WriteMemoryUnsigned (context, address, data, addr_byte_size))
3947 return false;
3948
3949 }
3950 else
3951 // MemU[address,4] = bits(32) UNKNOWN;
3952 WriteBits32UnknownToMemory (address);
3953
3954 // if wback then R[n] = offset_addr;
3955 if (wback)
3956 {
3957 context.type = eContextRegisterLoad;
3958 context.SetAddress (offset_addr);
3959 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3960 return false;
3961 }
3962
3963 }
3964 return true;
3965}
3966
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003967EmulateInstructionARM::ARMOpcode*
3968EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00003969{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003970 static ARMOpcode
3971 g_arm_opcodes[] =
3972 {
3973 //----------------------------------------------------------------------
3974 // Prologue instructions
3975 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00003976
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003977 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00003978 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
3979 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00003980
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003981 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00003982 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
3983 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00003984 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00003985 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
3986 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
3987 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00003988
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003989 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00003990 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00003991
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003992 // push one register
3993 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00003994 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00003995
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003996 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00003997 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
3998 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00003999
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004000 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004001 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004002 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004003
Johnny Chenc28a76d2011-02-01 18:51:48 +00004004 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
4005 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004006 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004007 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4008
4009 //----------------------------------------------------------------------
4010 // Supervisor Call (previously Software Interrupt)
4011 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004012 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4013
4014 //----------------------------------------------------------------------
4015 // Branch instructions
4016 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004017 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004018 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4019 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4020 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4021 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004022 // for example, "bx lr"
4023 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004024
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004025 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004026 // Data-processing instructions
4027 //----------------------------------------------------------------------
4028 // move bitwise not
4029 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004030 // asr (immediate)
4031 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004032 // asr (immediate)
4033 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004034
4035 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004036 // Load instructions
4037 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004038 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004039 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004040 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004041 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4042
4043 //----------------------------------------------------------------------
4044 // Store instructions
4045 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004046 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004047 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004048 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004049 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4050 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004051
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004052
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004053 };
4054 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4055
4056 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4057 {
4058 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4059 return &g_arm_opcodes[i];
4060 }
4061 return NULL;
4062}
Greg Clayton64c84432011-01-21 22:02:52 +00004063
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004064
4065EmulateInstructionARM::ARMOpcode*
4066EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004067{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004068
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004069 static ARMOpcode
4070 g_thumb_opcodes[] =
4071 {
4072 //----------------------------------------------------------------------
4073 // Prologue instructions
4074 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004075
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004076 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004077 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004078 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
4079 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004080
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004081 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004082 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004083 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00004084 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004085 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
4086 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004087
Johnny Chenc9de9102011-02-11 19:12:30 +00004088 // PC-relative load into register (see also EmulateAddSPRm)
4089 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004090
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004091 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004092 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
4093 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004094 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
4095 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004096
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004097 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004098 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4099 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004100
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004101 //----------------------------------------------------------------------
4102 // Epilogue instructions
4103 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004104
Johnny Chenc28a76d2011-02-01 18:51:48 +00004105 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
4106 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004107 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
4108 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
4109 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4110 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004111
4112 //----------------------------------------------------------------------
4113 // Supervisor Call (previously Software Interrupt)
4114 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004115 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4116
4117 //----------------------------------------------------------------------
4118 // If Then makes up to four following instructions conditional.
4119 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004120 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4121
4122 //----------------------------------------------------------------------
4123 // Branch instructions
4124 //----------------------------------------------------------------------
4125 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4126 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4127 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004128 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004129 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004130 // J1 == J2 == 1
4131 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4132 // J1 == J2 == 1
4133 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4134 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004135 // for example, "bx lr"
4136 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004137 // compare and branch
4138 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004139
4140 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004141 // Data-processing instructions
4142 //----------------------------------------------------------------------
4143 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
4144 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004145 // move from high register to high register
4146 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
4147 // move from low register to low register
4148 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004149 // move immediate
4150 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
4151 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004152 // move bitwise not
4153 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004154 // compare a register with immediate
4155 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004156 // compare Rn with Rm (Rn and Rm both from r0-r7)
4157 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
4158 // compare Rn with Rm (Rn and Rm not both from r0-r7)
4159 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004160 // asr (immediate)
4161 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004162 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004163 // asr (register)
4164 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4165 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004166
4167 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004168 // Load instructions
4169 //----------------------------------------------------------------------
4170 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004171 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004172 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004173 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4174 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004175 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4176
4177 //----------------------------------------------------------------------
4178 // Store instructions
4179 //----------------------------------------------------------------------
4180 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004181 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004182 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4183 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4184 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4185 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004186 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4187 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
4188 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004189 };
4190
4191 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4192 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4193 {
4194 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4195 return &g_thumb_opcodes[i];
4196 }
4197 return NULL;
4198}
Greg Clayton64c84432011-01-21 22:02:52 +00004199
Greg Clayton31e2a382011-01-30 20:03:56 +00004200bool
Greg Clayton395fc332011-02-15 21:59:32 +00004201EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004202{
4203 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004204 const char *arch_cstr = arch.AsCString ();
4205 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004206 {
Greg Clayton395fc332011-02-15 21:59:32 +00004207 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4208 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4209 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4210 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4211 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4212 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4213 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4214 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4215 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4216 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004217 }
4218 return m_arm_isa != 0;
4219}
4220
4221
Greg Clayton64c84432011-01-21 22:02:52 +00004222bool
4223EmulateInstructionARM::ReadInstruction ()
4224{
4225 bool success = false;
4226 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4227 if (success)
4228 {
4229 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4230 if (success)
4231 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004232 Context read_inst_context;
4233 read_inst_context.type = eContextReadOpcode;
4234 read_inst_context.SetNoArgs ();
4235
Greg Clayton64c84432011-01-21 22:02:52 +00004236 if (m_inst_cpsr & MASK_CPSR_T)
4237 {
4238 m_inst_mode = eModeThumb;
4239 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
4240
4241 if (success)
4242 {
4243 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4244 {
4245 m_inst.opcode_type = eOpcode16;
4246 m_inst.opcode.inst16 = thumb_opcode;
4247 }
4248 else
4249 {
4250 m_inst.opcode_type = eOpcode32;
4251 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
4252 }
4253 }
4254 }
4255 else
4256 {
4257 m_inst_mode = eModeARM;
4258 m_inst.opcode_type = eOpcode32;
4259 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
4260 }
4261 }
4262 }
4263 if (!success)
4264 {
4265 m_inst_mode = eModeInvalid;
4266 m_inst_pc = LLDB_INVALID_ADDRESS;
4267 }
4268 return success;
4269}
4270
Johnny Chenee9b1f72011-02-09 01:00:31 +00004271uint32_t
4272EmulateInstructionARM::ArchVersion ()
4273{
4274 return m_arm_isa;
4275}
4276
Greg Clayton64c84432011-01-21 22:02:52 +00004277bool
4278EmulateInstructionARM::ConditionPassed ()
4279{
4280 if (m_inst_cpsr == 0)
4281 return false;
4282
4283 const uint32_t cond = CurrentCond ();
4284
4285 if (cond == UINT32_MAX)
4286 return false;
4287
4288 bool result = false;
4289 switch (UnsignedBits(cond, 3, 1))
4290 {
4291 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4292 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4293 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4294 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4295 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4296 case 5:
4297 {
4298 bool n = (m_inst_cpsr & MASK_CPSR_N);
4299 bool v = (m_inst_cpsr & MASK_CPSR_V);
4300 result = n == v;
4301 }
4302 break;
4303 case 6:
4304 {
4305 bool n = (m_inst_cpsr & MASK_CPSR_N);
4306 bool v = (m_inst_cpsr & MASK_CPSR_V);
4307 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4308 }
4309 break;
4310 case 7:
4311 result = true;
4312 break;
4313 }
4314
4315 if (cond & 1)
4316 result = !result;
4317 return result;
4318}
4319
Johnny Chen9ee056b2011-02-08 00:06:35 +00004320uint32_t
4321EmulateInstructionARM::CurrentCond ()
4322{
4323 switch (m_inst_mode)
4324 {
4325 default:
4326 case eModeInvalid:
4327 break;
4328
4329 case eModeARM:
4330 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4331
4332 case eModeThumb:
4333 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4334 // 'cond' field of the encoding.
4335 if (m_inst.opcode_type == eOpcode16 &&
4336 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4337 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4338 {
4339 return Bits32(m_inst.opcode.inst16, 11, 7);
4340 }
4341 else if (m_inst.opcode_type == eOpcode32 &&
4342 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4343 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4344 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4345 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4346 {
4347 return Bits32(m_inst.opcode.inst32, 25, 22);
4348 }
4349
4350 return m_it_session.GetCond();
4351 }
4352 return UINT32_MAX; // Return invalid value
4353}
4354
Johnny Chen9ee056b2011-02-08 00:06:35 +00004355bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004356EmulateInstructionARM::InITBlock()
4357{
4358 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4359}
4360
4361bool
4362EmulateInstructionARM::LastInITBlock()
4363{
4364 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4365}
4366
4367bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004368EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4369{
4370 addr_t target;
4371
Johnny Chenee9b1f72011-02-09 01:00:31 +00004372 // Check the current instruction set.
4373 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004374 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004375 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004376 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004377
Johnny Chen9ee056b2011-02-08 00:06:35 +00004378 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004379 return false;
4380
4381 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004382}
4383
4384// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4385bool
Johnny Chen668b4512011-02-15 21:08:58 +00004386EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004387{
4388 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004389 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4390 // we want to record it and issue a WriteRegister callback so the clients
4391 // can track the mode changes accordingly.
4392 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004393
4394 if (BitIsSet(addr, 0))
4395 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004396 if (CurrentInstrSet() != eModeThumb)
4397 {
4398 SelectInstrSet(eModeThumb);
4399 cpsr_changed = true;
4400 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004401 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004402 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004403 }
4404 else if (BitIsClear(addr, 1))
4405 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004406 if (CurrentInstrSet() != eModeARM)
4407 {
4408 SelectInstrSet(eModeARM);
4409 cpsr_changed = true;
4410 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004411 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004412 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004413 }
4414 else
4415 return false; // address<1:0> == '10' => UNPREDICTABLE
4416
Johnny Chen0f309db2011-02-09 19:11:32 +00004417 if (cpsr_changed)
4418 {
Johnny Chen558133b2011-02-09 23:59:17 +00004419 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004420 return false;
4421 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004422 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004423 return false;
4424
4425 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004426}
Greg Clayton64c84432011-01-21 22:02:52 +00004427
Johnny Chenee9b1f72011-02-09 01:00:31 +00004428// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4429bool
Johnny Chen668b4512011-02-15 21:08:58 +00004430EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004431{
4432 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004433 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004434 else
4435 return BranchWritePC((const Context)context, addr);
4436}
4437
Johnny Chen26863dc2011-02-09 23:43:29 +00004438// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4439bool
Johnny Chen668b4512011-02-15 21:08:58 +00004440EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004441{
4442 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004443 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004444 else
4445 return BranchWritePC((const Context)context, addr);
4446}
4447
Johnny Chenee9b1f72011-02-09 01:00:31 +00004448EmulateInstructionARM::Mode
4449EmulateInstructionARM::CurrentInstrSet ()
4450{
4451 return m_inst_mode;
4452}
4453
4454// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004455// ReadInstruction() is performed. This function has a side effect of updating
4456// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004457bool
4458EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4459{
Johnny Chen558133b2011-02-09 23:59:17 +00004460 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004461 switch (arm_or_thumb)
4462 {
4463 default:
4464 return false;
4465 eModeARM:
4466 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004467 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004468 break;
4469 eModeThumb:
4470 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004471 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004472 break;
4473 }
4474 return true;
4475}
4476
Johnny Chenef21b592011-02-10 01:52:38 +00004477// This function returns TRUE if the processor currently provides support for
4478// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4479// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4480bool
4481EmulateInstructionARM::UnalignedSupport()
4482{
4483 return (ArchVersion() >= ARMv7);
4484}
4485
Johnny Chenbf6ad172011-02-11 01:29:53 +00004486// The main addition and subtraction instructions can produce status information
4487// about both unsigned carry and signed overflow conditions. This status
4488// information can be used to synthesize multi-word additions and subtractions.
4489EmulateInstructionARM::AddWithCarryResult
4490EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4491{
4492 uint32_t result;
4493 uint8_t carry_out;
4494 uint8_t overflow;
4495
4496 uint64_t unsigned_sum = x + y + carry_in;
4497 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4498
4499 result = UnsignedBits(unsigned_sum, 31, 0);
4500 carry_out = (result == unsigned_sum ? 0 : 1);
4501 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4502
4503 AddWithCarryResult res = { result, carry_out, overflow };
4504 return res;
4505}
4506
Greg Clayton64c84432011-01-21 22:02:52 +00004507bool
4508EmulateInstructionARM::EvaluateInstruction ()
4509{
Johnny Chenc315f862011-02-05 00:46:10 +00004510 // Advance the ITSTATE bits to their values for the next instruction.
4511 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4512 m_it_session.ITAdvance();
4513
Greg Clayton64c84432011-01-21 22:02:52 +00004514 return false;
4515}