blob: b45244ba10f5c4cc10764249980e2c914a9d4e3b [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 Chenca67d1c2011-02-17 01:35:27 +0000619 uint32_t result = 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 Chenca67d1c2011-02-17 01:35:27 +0000629
630 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags))
631 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000632 }
633 return true;
634}
635
Johnny Chen357c30f2011-02-14 22:04:25 +0000636// Move (immediate) writes an immediate value to the destination register. It
637// can optionally update the condition flags based on the value.
638// MOV (immediate)
639bool
640EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
641{
642#if 0
643 // ARM pseudo code...
644 if (ConditionPassed())
645 {
646 EncodingSpecificOperations();
647 result = imm32;
648 if d == 15 then // Can only occur for ARM encoding
649 ALUWritePC(result); // setflags is always FALSE here
650 else
651 R[d] = result;
652 if setflags then
653 APSR.N = result<31>;
654 APSR.Z = IsZeroBit(result);
655 APSR.C = carry;
656 // APSR.V unchanged
657 }
658#endif
659 bool success = false;
660 const uint32_t opcode = OpcodeAsUnsigned (&success);
661 if (!success)
662 return false;
663
664 if (ConditionPassed())
665 {
666 uint32_t Rd; // the destination register
667 uint32_t imm12; // some intermediate result
668 uint32_t imm32; // the immediate value to be written to Rd
669 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
670 bool setflags;
671 switch (encoding) {
672 case eEncodingT1:
673 Rd = Bits32(opcode, 11, 8);
674 setflags = !InITBlock();
675 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
676 carry = Bit32(m_inst_cpsr, CPSR_C);
677 break;
678 case eEncodingT2:
679 Rd = Bits32(opcode, 15, 12);
680 setflags = BitIsSet(opcode, 20);
681 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
682 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000683 if (BadReg(Rd))
684 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000685 break;
686 default:
687 return false;
688 }
689 uint32_t result = imm32;
690
691 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000692 EmulateInstruction::Context context;
693 context.type = EmulateInstruction::eContextImmediate;
694 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000695
696 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
697 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000698 }
699 return true;
700}
701
Johnny Chen28070c32011-02-12 01:27:26 +0000702// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
703// the destination register. It can optionally update the condition flags based
704// on the value.
705// MVN (immediate)
706bool
707EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
708{
709#if 0
710 // ARM pseudo code...
711 if (ConditionPassed())
712 {
713 EncodingSpecificOperations();
714 result = NOT(imm32);
715 if d == 15 then // Can only occur for ARM encoding
716 ALUWritePC(result); // setflags is always FALSE here
717 else
718 R[d] = result;
719 if setflags then
720 APSR.N = result<31>;
721 APSR.Z = IsZeroBit(result);
722 APSR.C = carry;
723 // APSR.V unchanged
724 }
725#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000726 bool success = false;
727 const uint32_t opcode = OpcodeAsUnsigned (&success);
728 if (!success)
729 return false;
730
731 if (ConditionPassed())
732 {
733 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000734 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
735 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
736 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000737 bool setflags;
738 switch (encoding) {
739 case eEncodingT1:
740 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000741 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000742 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000743 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
744 break;
745 case eEncodingA1:
746 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000747 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000748 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000749 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
750 break;
751 default:
752 return false;
753 }
754 uint32_t result = ~imm32;
755
756 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000757 EmulateInstruction::Context context;
758 context.type = EmulateInstruction::eContextImmediate;
759 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000760
761 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
762 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000763 }
764 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000765}
766
Johnny Chen788e0552011-01-27 22:52:23 +0000767// PC relative immediate load into register, possibly followed by ADD (SP plus register).
768// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000769bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000770EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000771{
772#if 0
773 // ARM pseudo code...
774 if (ConditionPassed())
775 {
776 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
777 base = Align(PC,4);
778 address = if add then (base + imm32) else (base - imm32);
779 data = MemU[address,4];
780 if t == 15 then
781 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
782 elsif UnalignedSupport() || address<1:0> = ‘00’ then
783 R[t] = data;
784 else // Can only apply before ARMv7
785 if CurrentInstrSet() == InstrSet_ARM then
786 R[t] = ROR(data, 8*UInt(address<1:0>));
787 else
788 R[t] = bits(32) UNKNOWN;
789 }
790#endif
791
792 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000793 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000794 if (!success)
795 return false;
796
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000797 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000798 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000799 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000800 if (!success)
801 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000802
803 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000804 EmulateInstruction::Context context;
805 context.type = EmulateInstruction::eContextRegisterPlusOffset;
806 Register pc_reg;
807 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
808 context.SetRegisterPlusOffset (pc_reg, 0);
809
Johnny Chenc9de9102011-02-11 19:12:30 +0000810 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000811 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000812 bool add; // +imm32 or -imm32?
813 addr_t base; // the base address
814 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000815 uint32_t data; // the literal data value from the PC relative load
816 switch (encoding) {
817 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000818 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000819 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000820 add = true;
821 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000822 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000823 break;
824 case eEncodingT2:
825 Rt = Bits32(opcode, 15, 12);
826 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
827 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000828 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000829 return false;
830 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000831 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000832 break;
833 default:
834 return false;
835 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000836
837 if (add)
838 address = base + imm32;
839 else
840 address = base - imm32;
841 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000842 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000843 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000844
845 if (Rt == 15)
846 {
847 if (Bits32(address, 1, 0) == 0)
848 {
849 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000850 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000851 return false;
852 }
853 else
854 return false;
855 }
856 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
857 {
858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
859 return false;
860 }
861 else // We don't handle ARM for now.
862 return false;
863
864 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000865 return false;
866 }
867 return true;
868}
869
Johnny Chen5b442b72011-01-27 19:34:30 +0000870// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000871// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000872bool
873EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000874{
875#if 0
876 // ARM pseudo code...
877 if (ConditionPassed())
878 {
879 EncodingSpecificOperations();
880 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
881 if d == 15 then // Can only occur for ARM encoding
882 ALUWritePC(result); // setflags is always FALSE here
883 else
884 R[d] = result;
885 if setflags then
886 APSR.N = result<31>;
887 APSR.Z = IsZeroBit(result);
888 APSR.C = carry;
889 APSR.V = overflow;
890 }
891#endif
892
893 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000894 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000895 if (!success)
896 return false;
897
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000898 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000899 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000900 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000901 if (!success)
902 return false;
903 uint32_t imm32; // the immediate operand
904 switch (encoding) {
905 case eEncodingT2:
906 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
907 break;
908 default:
909 return false;
910 }
911 addr_t sp_offset = imm32;
912 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
913
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000914 EmulateInstruction::Context context;
915 context.type = EmulateInstruction::eContextAdjustStackPointer;
916 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000917
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000918 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000919 return false;
920 }
921 return true;
922}
923
924// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000925// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000926bool
927EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000928{
929#if 0
930 // ARM pseudo code...
931 if (ConditionPassed())
932 {
933 EncodingSpecificOperations();
934 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
935 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
936 if d == 15 then
937 ALUWritePC(result); // setflags is always FALSE here
938 else
939 R[d] = result;
940 if setflags then
941 APSR.N = result<31>;
942 APSR.Z = IsZeroBit(result);
943 APSR.C = carry;
944 APSR.V = overflow;
945 }
946#endif
947
948 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000949 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000950 if (!success)
951 return false;
952
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000953 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000954 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000955 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000956 if (!success)
957 return false;
958 uint32_t Rm; // the second operand
959 switch (encoding) {
960 case eEncodingT2:
961 Rm = Bits32(opcode, 6, 3);
962 break;
963 default:
964 return false;
965 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000966 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000967 if (!success)
968 return false;
969
970 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
971
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000972 EmulateInstruction::Context context;
973 context.type = EmulateInstruction::eContextAdjustStackPointer;
974 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000975
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000976 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000977 return false;
978 }
979 return true;
980}
981
Johnny Chen9b8d7832011-02-02 01:13:56 +0000982// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
983// at a PC-relative address, and changes instruction set from ARM to Thumb, or
984// from Thumb to ARM.
985// BLX (immediate)
986bool
987EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
988{
989#if 0
990 // ARM pseudo code...
991 if (ConditionPassed())
992 {
993 EncodingSpecificOperations();
994 if CurrentInstrSet() == InstrSet_ARM then
995 LR = PC - 4;
996 else
997 LR = PC<31:1> : '1';
998 if targetInstrSet == InstrSet_ARM then
999 targetAddress = Align(PC,4) + imm32;
1000 else
1001 targetAddress = PC + imm32;
1002 SelectInstrSet(targetInstrSet);
1003 BranchWritePC(targetAddress);
1004 }
1005#endif
1006
1007 bool success = false;
1008 const uint32_t opcode = OpcodeAsUnsigned (&success);
1009 if (!success)
1010 return false;
1011
1012 if (ConditionPassed())
1013 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001014 EmulateInstruction::Context context;
1015 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001016 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001017 if (!success)
1018 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001019 addr_t lr; // next instruction address
1020 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001021 int32_t imm32; // PC-relative offset
1022 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001023 case eEncodingT1:
1024 {
1025 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001026 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001027 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001028 uint32_t J1 = Bit32(opcode, 13);
1029 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001030 uint32_t imm11 = Bits32(opcode, 10, 0);
1031 uint32_t I1 = !(J1 ^ S);
1032 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001033 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001034 imm32 = llvm::SignExtend32<25>(imm25);
1035 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001036 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001037 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001038 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001039 break;
1040 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001041 case eEncodingT2:
1042 {
1043 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001044 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001045 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001046 uint32_t J1 = Bit32(opcode, 13);
1047 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001048 uint32_t imm10L = Bits32(opcode, 10, 1);
1049 uint32_t I1 = !(J1 ^ S);
1050 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001051 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001052 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001053 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001054 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001055 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001056 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001057 break;
1058 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001059 case eEncodingA1:
1060 lr = pc + 4; // return address
1061 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001062 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001063 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001064 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001065 case eEncodingA2:
1066 lr = pc + 4; // return address
1067 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1068 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001069 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001070 break;
1071 default:
1072 return false;
1073 }
1074 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1075 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001076 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001077 return false;
1078 }
1079 return true;
1080}
1081
1082// Branch with Link and Exchange (register) calls a subroutine at an address and
1083// instruction set specified by a register.
1084// BLX (register)
1085bool
1086EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1087{
1088#if 0
1089 // ARM pseudo code...
1090 if (ConditionPassed())
1091 {
1092 EncodingSpecificOperations();
1093 target = R[m];
1094 if CurrentInstrSet() == InstrSet_ARM then
1095 next_instr_addr = PC - 4;
1096 LR = next_instr_addr;
1097 else
1098 next_instr_addr = PC - 2;
1099 LR = next_instr_addr<31:1> : ‘1’;
1100 BXWritePC(target);
1101 }
1102#endif
1103
1104 bool success = false;
1105 const uint32_t opcode = OpcodeAsUnsigned (&success);
1106 if (!success)
1107 return false;
1108
1109 if (ConditionPassed())
1110 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001111 EmulateInstruction::Context context;
1112 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001113 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1114 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001115 if (!success)
1116 return false;
1117 uint32_t Rm; // the register with the target address
1118 switch (encoding) {
1119 case eEncodingT1:
1120 lr = (pc + 2) | 1u; // return address
1121 Rm = Bits32(opcode, 6, 3);
1122 // if m == 15 then UNPREDICTABLE;
1123 if (Rm == 15)
1124 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001125 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001126 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001127 break;
1128 case eEncodingA1:
1129 lr = pc + 4; // return address
1130 Rm = Bits32(opcode, 3, 0);
1131 // if m == 15 then UNPREDICTABLE;
1132 if (Rm == 15)
1133 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001134 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001135 default:
1136 return false;
1137 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001138 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1139 if (!success)
1140 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001141 Register dwarf_reg;
1142 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1143 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001144 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1145 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001146 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001147 return false;
1148 }
1149 return true;
1150}
1151
Johnny Chenab3b3512011-02-12 00:10:51 +00001152// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1153// BX
1154bool
1155EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1156{
1157#if 0
1158 // ARM pseudo code...
1159 if (ConditionPassed())
1160 {
1161 EncodingSpecificOperations();
1162 BXWritePC(R[m]);
1163 }
1164#endif
1165
1166 bool success = false;
1167 const uint32_t opcode = OpcodeAsUnsigned (&success);
1168 if (!success)
1169 return false;
1170
1171 if (ConditionPassed())
1172 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001173 EmulateInstruction::Context context;
1174 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001175 uint32_t Rm; // the register with the target address
1176 switch (encoding) {
1177 case eEncodingT1:
1178 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001179 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001180 return false;
1181 break;
1182 case eEncodingA1:
1183 Rm = Bits32(opcode, 3, 0);
1184 break;
1185 default:
1186 return false;
1187 }
1188 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1189 if (!success)
1190 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001191
1192 Register dwarf_reg;
1193 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001194 context.SetRegister (dwarf_reg);
1195 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001196 return false;
1197 }
1198 return true;
1199}
1200
Johnny Chen0d0148e2011-01-28 02:26:08 +00001201// Set r7 to point to some ip offset.
1202// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001203bool
1204EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001205{
1206#if 0
1207 // ARM pseudo code...
1208 if (ConditionPassed())
1209 {
1210 EncodingSpecificOperations();
1211 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1212 if d == 15 then // Can only occur for ARM encoding
1213 ALUWritePC(result); // setflags is always FALSE here
1214 else
1215 R[d] = result;
1216 if setflags then
1217 APSR.N = result<31>;
1218 APSR.Z = IsZeroBit(result);
1219 APSR.C = carry;
1220 APSR.V = overflow;
1221 }
1222#endif
1223
1224 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001225 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001226 if (!success)
1227 return false;
1228
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001229 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001230 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001231 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001232 if (!success)
1233 return false;
1234 uint32_t imm32;
1235 switch (encoding) {
1236 case eEncodingA1:
1237 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1238 break;
1239 default:
1240 return false;
1241 }
1242 addr_t ip_offset = imm32;
1243 addr_t addr = ip - ip_offset; // the adjusted ip value
1244
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001245 EmulateInstruction::Context context;
1246 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1247 Register dwarf_reg;
1248 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1249 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001250
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001251 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001252 return false;
1253 }
1254 return true;
1255}
1256
1257// Set ip to point to some stack offset.
1258// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001259bool
1260EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001261{
1262#if 0
1263 // ARM pseudo code...
1264 if (ConditionPassed())
1265 {
1266 EncodingSpecificOperations();
1267 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1268 if d == 15 then // Can only occur for ARM encoding
1269 ALUWritePC(result); // setflags is always FALSE here
1270 else
1271 R[d] = result;
1272 if setflags then
1273 APSR.N = result<31>;
1274 APSR.Z = IsZeroBit(result);
1275 APSR.C = carry;
1276 APSR.V = overflow;
1277 }
1278#endif
1279
1280 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001281 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001282 if (!success)
1283 return false;
1284
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001285 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001286 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001287 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001288 if (!success)
1289 return false;
1290 uint32_t imm32;
1291 switch (encoding) {
1292 case eEncodingA1:
1293 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1294 break;
1295 default:
1296 return false;
1297 }
1298 addr_t sp_offset = imm32;
1299 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1300
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001301 EmulateInstruction::Context context;
1302 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1303 Register dwarf_reg;
1304 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1305 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001306
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001308 return false;
1309 }
1310 return true;
1311}
1312
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001313// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001314bool
1315EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001316{
1317#if 0
1318 // ARM pseudo code...
1319 if (ConditionPassed())
1320 {
1321 EncodingSpecificOperations();
1322 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1323 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001324 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001325 else
1326 R[d] = result;
1327 if setflags then
1328 APSR.N = result<31>;
1329 APSR.Z = IsZeroBit(result);
1330 APSR.C = carry;
1331 APSR.V = overflow;
1332 }
1333#endif
1334
1335 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001336 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001337 if (!success)
1338 return false;
1339
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001340 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001341 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001342 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001343 if (!success)
1344 return false;
1345 uint32_t imm32;
1346 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001347 case eEncodingT1:
1348 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001349 case eEncodingT2:
1350 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1351 break;
1352 case eEncodingT3:
1353 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1354 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001355 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001356 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001357 break;
1358 default:
1359 return false;
1360 }
1361 addr_t sp_offset = imm32;
1362 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1363
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001364 EmulateInstruction::Context context;
1365 context.type = EmulateInstruction::eContextAdjustStackPointer;
1366 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001367
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001368 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001369 return false;
1370 }
1371 return true;
1372}
1373
Johnny Chen08c25e82011-01-31 18:02:28 +00001374// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001375bool
1376EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001377{
1378#if 0
1379 // ARM pseudo code...
1380 if (ConditionPassed())
1381 {
1382 EncodingSpecificOperations();
1383 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1384 address = if index then offset_addr else R[n];
1385 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1386 if wback then R[n] = offset_addr;
1387 }
1388#endif
1389
1390 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001391 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001392 if (!success)
1393 return false;
1394
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001395 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001396 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001397 const uint32_t addr_byte_size = GetAddressByteSize();
1398 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001399 if (!success)
1400 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001401 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001402 uint32_t imm12;
1403 switch (encoding) {
1404 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001405 Rt = Bits32(opcode, 15, 12);
1406 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001407 break;
1408 default:
1409 return false;
1410 }
1411 addr_t sp_offset = imm12;
1412 addr_t addr = sp - sp_offset;
1413
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001414 EmulateInstruction::Context context;
1415 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1416 Register dwarf_reg;
1417 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001418 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001419 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001420 dwarf_reg.num = dwarf_r0 + Rt;
1421 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1422 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001423 if (!success)
1424 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001425 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001426 return false;
1427 }
1428 else
1429 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001430 dwarf_reg.num = dwarf_pc;
1431 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001432 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001433 if (!success)
1434 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001435 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001436 return false;
1437 }
1438
1439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001440 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001441
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001443 return false;
1444 }
1445 return true;
1446}
1447
Johnny Chen08c25e82011-01-31 18:02:28 +00001448// Vector Push stores multiple extension registers to the stack.
1449// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001450bool
1451EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001452{
1453#if 0
1454 // ARM pseudo code...
1455 if (ConditionPassed())
1456 {
1457 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1458 address = SP - imm32;
1459 SP = SP - imm32;
1460 if single_regs then
1461 for r = 0 to regs-1
1462 MemA[address,4] = S[d+r]; address = address+4;
1463 else
1464 for r = 0 to regs-1
1465 // Store as two word-aligned words in the correct order for current endianness.
1466 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1467 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1468 address = address+8;
1469 }
1470#endif
1471
1472 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001473 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001474 if (!success)
1475 return false;
1476
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001477 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001478 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001479 const uint32_t addr_byte_size = GetAddressByteSize();
1480 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001481 if (!success)
1482 return false;
1483 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001484 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001485 uint32_t imm32; // stack offset
1486 uint32_t regs; // number of registers
1487 switch (encoding) {
1488 case eEncodingT1:
1489 case eEncodingA1:
1490 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001491 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001492 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1493 // If UInt(imm8) is odd, see "FSTMX".
1494 regs = Bits32(opcode, 7, 0) / 2;
1495 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1496 if (regs == 0 || regs > 16 || (d + regs) > 32)
1497 return false;
1498 break;
1499 case eEncodingT2:
1500 case eEncodingA2:
1501 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001502 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001503 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1504 regs = Bits32(opcode, 7, 0);
1505 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1506 if (regs == 0 || regs > 16 || (d + regs) > 32)
1507 return false;
1508 break;
1509 default:
1510 return false;
1511 }
1512 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1513 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1514 addr_t sp_offset = imm32;
1515 addr_t addr = sp - sp_offset;
1516 uint32_t i;
1517
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001518 EmulateInstruction::Context context;
1519 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1520 Register dwarf_reg;
1521 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001522 for (i=d; i<regs; ++i)
1523 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001524 dwarf_reg.num = start_reg + i;
1525 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001526 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001527 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001528 if (!success)
1529 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001530 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001531 return false;
1532 addr += reg_byte_size;
1533 }
1534
1535 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001536 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001537
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001538 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001539 return false;
1540 }
1541 return true;
1542}
1543
Johnny Chen587a0a42011-02-01 18:35:28 +00001544// Vector Pop loads multiple extension registers from the stack.
1545// It also updates SP to point just above the loaded data.
1546bool
1547EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1548{
1549#if 0
1550 // ARM pseudo code...
1551 if (ConditionPassed())
1552 {
1553 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1554 address = SP;
1555 SP = SP + imm32;
1556 if single_regs then
1557 for r = 0 to regs-1
1558 S[d+r] = MemA[address,4]; address = address+4;
1559 else
1560 for r = 0 to regs-1
1561 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1562 // Combine the word-aligned words in the correct order for current endianness.
1563 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1564 }
1565#endif
1566
1567 bool success = false;
1568 const uint32_t opcode = OpcodeAsUnsigned (&success);
1569 if (!success)
1570 return false;
1571
1572 if (ConditionPassed())
1573 {
1574 const uint32_t addr_byte_size = GetAddressByteSize();
1575 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1576 if (!success)
1577 return false;
1578 bool single_regs;
1579 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1580 uint32_t imm32; // stack offset
1581 uint32_t regs; // number of registers
1582 switch (encoding) {
1583 case eEncodingT1:
1584 case eEncodingA1:
1585 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001586 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001587 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1588 // If UInt(imm8) is odd, see "FLDMX".
1589 regs = Bits32(opcode, 7, 0) / 2;
1590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1591 if (regs == 0 || regs > 16 || (d + regs) > 32)
1592 return false;
1593 break;
1594 case eEncodingT2:
1595 case eEncodingA2:
1596 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001597 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001598 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1599 regs = Bits32(opcode, 7, 0);
1600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1601 if (regs == 0 || regs > 16 || (d + regs) > 32)
1602 return false;
1603 break;
1604 default:
1605 return false;
1606 }
1607 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1608 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1609 addr_t sp_offset = imm32;
1610 addr_t addr = sp;
1611 uint32_t i;
1612 uint64_t data; // uint64_t to accomodate 64-bit registers.
1613
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001614 EmulateInstruction::Context context;
1615 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1616 Register dwarf_reg;
1617 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001618 for (i=d; i<regs; ++i)
1619 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001620 dwarf_reg.num = start_reg + i;
1621 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chen587a0a42011-02-01 18:35:28 +00001622 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1623 if (!success)
1624 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001625 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001626 return false;
1627 addr += reg_byte_size;
1628 }
1629
1630 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001631 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001632
1633 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1634 return false;
1635 }
1636 return true;
1637}
1638
Johnny Chenb77be412011-02-04 00:40:18 +00001639// SVC (previously SWI)
1640bool
1641EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1642{
1643#if 0
1644 // ARM pseudo code...
1645 if (ConditionPassed())
1646 {
1647 EncodingSpecificOperations();
1648 CallSupervisor();
1649 }
1650#endif
1651
1652 bool success = false;
1653 const uint32_t opcode = OpcodeAsUnsigned (&success);
1654 if (!success)
1655 return false;
1656
1657 if (ConditionPassed())
1658 {
1659 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1660 addr_t lr; // next instruction address
1661 if (!success)
1662 return false;
1663 uint32_t imm32; // the immediate constant
1664 uint32_t mode; // ARM or Thumb mode
1665 switch (encoding) {
1666 case eEncodingT1:
1667 lr = (pc + 2) | 1u; // return address
1668 imm32 = Bits32(opcode, 7, 0);
1669 mode = eModeThumb;
1670 break;
1671 case eEncodingA1:
1672 lr = pc + 4; // return address
1673 imm32 = Bits32(opcode, 23, 0);
1674 mode = eModeARM;
1675 break;
1676 default:
1677 return false;
1678 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679
1680 EmulateInstruction::Context context;
1681 context.type = EmulateInstruction::eContextSupervisorCall;
1682 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001683 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1684 return false;
1685 }
1686 return true;
1687}
1688
Johnny Chenc315f862011-02-05 00:46:10 +00001689// If Then makes up to four following instructions (the IT block) conditional.
1690bool
1691EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1692{
1693#if 0
1694 // ARM pseudo code...
1695 EncodingSpecificOperations();
1696 ITSTATE.IT<7:0> = firstcond:mask;
1697#endif
1698
1699 bool success = false;
1700 const uint32_t opcode = OpcodeAsUnsigned (&success);
1701 if (!success)
1702 return false;
1703
1704 m_it_session.InitIT(Bits32(opcode, 7, 0));
1705 return true;
1706}
1707
Johnny Chen3b620b32011-02-07 20:11:47 +00001708// Branch causes a branch to a target address.
1709bool
1710EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1711{
1712#if 0
1713 // ARM pseudo code...
1714 if (ConditionPassed())
1715 {
1716 EncodingSpecificOperations();
1717 BranchWritePC(PC + imm32);
1718 }
1719#endif
1720
1721 bool success = false;
1722 const uint32_t opcode = OpcodeAsUnsigned (&success);
1723 if (!success)
1724 return false;
1725
Johnny Chen9ee056b2011-02-08 00:06:35 +00001726 if (ConditionPassed())
1727 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001728 EmulateInstruction::Context context;
1729 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001730 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001731 if (!success)
1732 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001733 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001734 int32_t imm32; // PC-relative offset
1735 switch (encoding) {
1736 case eEncodingT1:
1737 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1738 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1739 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001740 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001741 break;
1742 case eEncodingT2:
1743 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1744 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001745 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001746 break;
1747 case eEncodingT3:
1748 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1749 {
Johnny Chenbd599902011-02-10 21:39:01 +00001750 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001751 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001752 uint32_t J1 = Bit32(opcode, 13);
1753 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001754 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001755 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001756 imm32 = llvm::SignExtend32<21>(imm21);
1757 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001758 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001759 break;
1760 }
1761 case eEncodingT4:
1762 {
Johnny Chenbd599902011-02-10 21:39:01 +00001763 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001764 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001765 uint32_t J1 = Bit32(opcode, 13);
1766 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001767 uint32_t imm11 = Bits32(opcode, 10, 0);
1768 uint32_t I1 = !(J1 ^ S);
1769 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001770 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001771 imm32 = llvm::SignExtend32<25>(imm25);
1772 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001773 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001774 break;
1775 }
1776 case eEncodingA1:
1777 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1778 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001779 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001780 break;
1781 default:
1782 return false;
1783 }
1784 if (!BranchWritePC(context, target))
1785 return false;
1786 }
1787 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001788}
1789
Johnny Chen53ebab72011-02-08 23:21:57 +00001790// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1791// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1792// CBNZ, CBZ
1793bool
1794EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1795{
1796#if 0
1797 // ARM pseudo code...
1798 EncodingSpecificOperations();
1799 if nonzero ^ IsZero(R[n]) then
1800 BranchWritePC(PC + imm32);
1801#endif
1802
1803 bool success = false;
1804 const uint32_t opcode = OpcodeAsUnsigned (&success);
1805 if (!success)
1806 return false;
1807
1808 // Read the register value from the operand register Rn.
1809 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1810 if (!success)
1811 return false;
1812
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001813 EmulateInstruction::Context context;
1814 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001815 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1816 if (!success)
1817 return false;
1818
1819 addr_t target; // target address
1820 uint32_t imm32; // PC-relative offset to branch forward
1821 bool nonzero;
1822 switch (encoding) {
1823 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001824 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001825 nonzero = BitIsSet(opcode, 11);
1826 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001827 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001828 break;
1829 default:
1830 return false;
1831 }
1832 if (nonzero ^ (reg_val == 0))
1833 if (!BranchWritePC(context, target))
1834 return false;
1835
1836 return true;
1837}
1838
Johnny Chen26863dc2011-02-09 23:43:29 +00001839// ADD <Rdn>, <Rm>
1840// where <Rdn> the destination register is also the first operand register
1841// and <Rm> is the second operand register.
1842bool
1843EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1844{
1845#if 0
1846 // ARM pseudo code...
1847 if ConditionPassed() then
1848 EncodingSpecificOperations();
1849 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1850 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1851 if d == 15 then
1852 ALUWritePC(result); // setflags is always FALSE here
1853 else
1854 R[d] = result;
1855 if setflags then
1856 APSR.N = result<31>;
1857 APSR.Z = IsZeroBit(result);
1858 APSR.C = carry;
1859 APSR.V = overflow;
1860#endif
1861
1862 bool success = false;
1863 const uint32_t opcode = OpcodeAsUnsigned (&success);
1864 if (!success)
1865 return false;
1866
1867 if (ConditionPassed())
1868 {
1869 uint32_t Rd, Rn, Rm;
Johnny Chenca67d1c2011-02-17 01:35:27 +00001870 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00001871 switch (encoding)
1872 {
1873 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00001874 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001875 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00001876 setflags = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001877 if (Rn == 15 && Rm == 15)
1878 return false;
1879 break;
1880 default:
1881 return false;
1882 }
1883
1884 int32_t result, val1, val2;
1885 // Read the first operand.
1886 if (Rn == 15)
1887 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1888 else
1889 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1890 if (!success)
1891 return false;
1892
1893 // Read the second operand.
1894 if (Rm == 15)
1895 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1896 else
1897 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1898 if (!success)
1899 return false;
1900
Johnny Chenca67d1c2011-02-17 01:35:27 +00001901 // TODO: Handle the case where Rm needs to be shifted properly.
1902 AddWithCarryResult res = AddWithCarry(val1, val2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001903 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001904
1905 EmulateInstruction::Context context;
1906 context.type = EmulateInstruction::eContextImmediate;
1907 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001908
1909 if (!WriteCoreRegisterWithFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1910 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001911 }
1912 return true;
1913}
1914
Johnny Chene4a4d302011-02-11 21:53:58 +00001915// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001916bool
1917EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1918{
1919#if 0
1920 // ARM pseudo code...
1921 if ConditionPassed() then
1922 EncodingSpecificOperations();
1923 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1924 APSR.N = result<31>;
1925 APSR.Z = IsZeroBit(result);
1926 APSR.C = carry;
1927 APSR.V = overflow;
1928#endif
1929
1930 bool success = false;
1931 const uint32_t opcode = OpcodeAsUnsigned (&success);
1932 if (!success)
1933 return false;
1934
1935 uint32_t Rn; // the first operand
1936 uint32_t imm32; // the immediate value to be compared with
1937 switch (encoding) {
1938 case eEncodingT1:
1939 Rn = Bits32(opcode, 10, 8);
1940 imm32 = Bits32(opcode, 7, 0);
1941 break;
1942 default:
1943 return false;
1944 }
1945 // Read the register value from the operand register Rn.
1946 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1947 if (!success)
1948 return false;
1949
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001950 EmulateInstruction::Context context;
1951 context.type = EmulateInstruction::eContextImmediate;
1952 context.SetNoArgs ();
1953
Johnny Chend4dc4442011-02-11 02:02:56 +00001954 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1955 m_new_inst_cpsr = m_inst_cpsr;
1956 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1957 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1958 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1959 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1960 if (m_new_inst_cpsr != m_inst_cpsr)
1961 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001962 EmulateInstruction::Context context;
1963 context.type = EmulateInstruction::eContextImmediate;
1964 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00001965 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1966 return false;
1967 }
1968 return true;
1969}
1970
Johnny Chene4a4d302011-02-11 21:53:58 +00001971// CMP (register)
1972bool
1973EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1974{
1975#if 0
1976 // ARM pseudo code...
1977 if ConditionPassed() then
1978 EncodingSpecificOperations();
1979 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1980 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1981 APSR.N = result<31>;
1982 APSR.Z = IsZeroBit(result);
1983 APSR.C = carry;
1984 APSR.V = overflow;
1985#endif
1986
1987 bool success = false;
1988 const uint32_t opcode = OpcodeAsUnsigned (&success);
1989 if (!success)
1990 return false;
1991
1992 uint32_t Rn; // the first operand
1993 uint32_t Rm; // the second operand
1994 switch (encoding) {
1995 case eEncodingT1:
1996 Rn = Bits32(opcode, 2, 0);
1997 Rm = Bits32(opcode, 5, 3);
1998 break;
1999 case eEncodingT2:
2000 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2001 Rm = Bits32(opcode, 6, 3);
2002 if (Rn < 8 && Rm < 8)
2003 return false;
2004 if (Rn == 15 || Rm == 15)
2005 return false;
2006 break;
2007 default:
2008 return false;
2009 }
2010 // Read the register value from register Rn.
2011 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2012 if (!success)
2013 return false;
2014 // Read the register value from register Rm.
2015 // The register value is not being shifted since we don't handle ARM for now.
2016 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2017 if (!success)
2018 return false;
2019
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002020 EmulateInstruction::Context context;
2021 context.type = EmulateInstruction::eContextImmediate;
2022 context.SetNoArgs();
2023
Johnny Chene4a4d302011-02-11 21:53:58 +00002024 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2025 m_new_inst_cpsr = m_inst_cpsr;
2026 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2027 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2028 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2029 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2030 if (m_new_inst_cpsr != m_inst_cpsr)
2031 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002032 EmulateInstruction::Context context;
2033 context.type = EmulateInstruction::eContextImmediate;
2034 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002035 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2036 return false;
2037 }
2038 return true;
2039}
2040
Johnny Chen82f16aa2011-02-15 20:10:55 +00002041// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2042// shifting in copies of its sign bit, and writes the result to the destination register. It can
2043// optionally update the condition flags based on the result.
2044bool
2045EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2046{
2047#if 0
2048 // ARM pseudo code...
2049 if ConditionPassed() then
2050 EncodingSpecificOperations();
2051 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2052 if d == 15 then // Can only occur for ARM encoding
2053 ALUWritePC(result); // setflags is always FALSE here
2054 else
2055 R[d] = result;
2056 if setflags then
2057 APSR.N = result<31>;
2058 APSR.Z = IsZeroBit(result);
2059 APSR.C = carry;
2060 // APSR.V unchanged
2061#endif
2062
Johnny Chen41a0a152011-02-16 01:27:54 +00002063 return EmulateShiftImm(encoding, SRType_ASR);
2064}
2065
2066// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2067// shifting in copies of its sign bit, and writes the result to the destination register.
2068// The variable number of bits is read from the bottom byte of a register. It can optionally update
2069// the condition flags based on the result.
2070bool
2071EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2072{
2073#if 0
2074 // ARM pseudo code...
2075 if ConditionPassed() then
2076 EncodingSpecificOperations();
2077 shift_n = UInt(R[m]<7:0>);
2078 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2079 R[d] = result;
2080 if setflags then
2081 APSR.N = result<31>;
2082 APSR.Z = IsZeroBit(result);
2083 APSR.C = carry;
2084 // APSR.V unchanged
2085#endif
2086
2087 return EmulateShiftReg(encoding, SRType_ASR);
2088}
2089
2090// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2091// shifting in zeros, and writes the result to the destination register. It can optionally
2092// update the condition flags based on the result.
2093bool
2094EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2095{
2096#if 0
2097 // ARM pseudo code...
2098 if ConditionPassed() then
2099 EncodingSpecificOperations();
2100 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2101 if d == 15 then // Can only occur for ARM encoding
2102 ALUWritePC(result); // setflags is always FALSE here
2103 else
2104 R[d] = result;
2105 if setflags then
2106 APSR.N = result<31>;
2107 APSR.Z = IsZeroBit(result);
2108 APSR.C = carry;
2109 // APSR.V unchanged
2110#endif
2111
2112 return EmulateShiftImm(encoding, SRType_LSL);
2113}
2114
2115// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2116// shifting in zeros, and writes the result to the destination register. The variable number
2117// of bits is read from the bottom byte of a register. It can optionally update the condition
2118// flags based on the result.
2119bool
2120EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2121{
2122#if 0
2123 // ARM pseudo code...
2124 if ConditionPassed() then
2125 EncodingSpecificOperations();
2126 shift_n = UInt(R[m]<7:0>);
2127 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2128 R[d] = result;
2129 if setflags then
2130 APSR.N = result<31>;
2131 APSR.Z = IsZeroBit(result);
2132 APSR.C = carry;
2133 // APSR.V unchanged
2134#endif
2135
2136 return EmulateShiftReg(encoding, SRType_LSL);
2137}
2138
2139// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2140// shifting in zeros, and writes the result to the destination register. It can optionally
2141// update the condition flags based on the result.
2142bool
2143EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2144{
2145#if 0
2146 // ARM pseudo code...
2147 if ConditionPassed() then
2148 EncodingSpecificOperations();
2149 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2150 if d == 15 then // Can only occur for ARM encoding
2151 ALUWritePC(result); // setflags is always FALSE here
2152 else
2153 R[d] = result;
2154 if setflags then
2155 APSR.N = result<31>;
2156 APSR.Z = IsZeroBit(result);
2157 APSR.C = carry;
2158 // APSR.V unchanged
2159#endif
2160
2161 return EmulateShiftImm(encoding, SRType_LSR);
2162}
2163
2164// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2165// shifting in zeros, and writes the result to the destination register. The variable number
2166// of bits is read from the bottom byte of a register. It can optionally update the condition
2167// flags based on the result.
2168bool
2169EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2170{
2171#if 0
2172 // ARM pseudo code...
2173 if ConditionPassed() then
2174 EncodingSpecificOperations();
2175 shift_n = UInt(R[m]<7:0>);
2176 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2177 R[d] = result;
2178 if setflags then
2179 APSR.N = result<31>;
2180 APSR.Z = IsZeroBit(result);
2181 APSR.C = carry;
2182 // APSR.V unchanged
2183#endif
2184
2185 return EmulateShiftReg(encoding, SRType_LSR);
2186}
2187
Johnny Cheneeab4852011-02-16 22:14:44 +00002188// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2189// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2190// It can optionally update the condition flags based on the result.
2191bool
2192EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2193{
2194#if 0
2195 // ARM pseudo code...
2196 if ConditionPassed() then
2197 EncodingSpecificOperations();
2198 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2199 if d == 15 then // Can only occur for ARM encoding
2200 ALUWritePC(result); // setflags is always FALSE here
2201 else
2202 R[d] = result;
2203 if setflags then
2204 APSR.N = result<31>;
2205 APSR.Z = IsZeroBit(result);
2206 APSR.C = carry;
2207 // APSR.V unchanged
2208#endif
2209
2210 return EmulateShiftImm(encoding, SRType_ROR);
2211}
2212
2213// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2214// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2215// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2216// flags based on the result.
2217bool
2218EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2219{
2220#if 0
2221 // ARM pseudo code...
2222 if ConditionPassed() then
2223 EncodingSpecificOperations();
2224 shift_n = UInt(R[m]<7:0>);
2225 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2226 R[d] = result;
2227 if setflags then
2228 APSR.N = result<31>;
2229 APSR.Z = IsZeroBit(result);
2230 APSR.C = carry;
2231 // APSR.V unchanged
2232#endif
2233
2234 return EmulateShiftReg(encoding, SRType_ROR);
2235}
2236
2237// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2238// with the carry flag shifted into bit [31].
2239//
2240// RRX can optionally update the condition flags based on the result.
2241// In that case, bit [0] is shifted into the carry flag.
2242bool
2243EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2244{
2245#if 0
2246 // ARM pseudo code...
2247 if ConditionPassed() then
2248 EncodingSpecificOperations();
2249 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2250 if d == 15 then // Can only occur for ARM encoding
2251 ALUWritePC(result); // setflags is always FALSE here
2252 else
2253 R[d] = result;
2254 if setflags then
2255 APSR.N = result<31>;
2256 APSR.Z = IsZeroBit(result);
2257 APSR.C = carry;
2258 // APSR.V unchanged
2259#endif
2260
2261 return EmulateShiftImm(encoding, SRType_RRX);
2262}
2263
Johnny Chen41a0a152011-02-16 01:27:54 +00002264bool
2265EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2266{
2267 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2268
Johnny Chen82f16aa2011-02-15 20:10:55 +00002269 bool success = false;
2270 const uint32_t opcode = OpcodeAsUnsigned (&success);
2271 if (!success)
2272 return false;
2273
2274 if (ConditionPassed())
2275 {
Johnny Chene7f89532011-02-15 23:22:46 +00002276 uint32_t Rd; // the destination register
2277 uint32_t Rm; // the first operand register
2278 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002279 uint32_t carry; // the carry bit after the shift operation
2280 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002281
2282 // Special case handling!
2283 // A8.6.139 ROR (immediate) -- Encoding T1
2284 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2285 {
2286 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2287 // have the same decoding of bit fields as the other Thumb2 shift operations.
2288 encoding = eEncodingT2;
2289 }
2290
Johnny Chen82f16aa2011-02-15 20:10:55 +00002291 switch (encoding) {
2292 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002293 // Due to the above special case handling!
2294 assert(shift_type != SRType_ROR);
2295
Johnny Chen82f16aa2011-02-15 20:10:55 +00002296 Rd = Bits32(opcode, 2, 0);
2297 Rm = Bits32(opcode, 5, 3);
2298 setflags = !InITBlock();
2299 imm5 = Bits32(opcode, 10, 6);
2300 break;
2301 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002302 // A8.6.141 RRX
2303 assert(shift_type != SRType_RRX);
2304
Johnny Chen82f16aa2011-02-15 20:10:55 +00002305 Rd = Bits32(opcode, 11, 8);
2306 Rm = Bits32(opcode, 3, 0);
2307 setflags = BitIsSet(opcode, 20);
2308 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2309 if (BadReg(Rd) || BadReg(Rm))
2310 return false;
2311 break;
2312 case eEncodingA1:
2313 Rd = Bits32(opcode, 15, 12);
2314 Rm = Bits32(opcode, 3, 0);
2315 setflags = BitIsSet(opcode, 20);
2316 imm5 = Bits32(opcode, 11, 7);
2317 break;
2318 default:
2319 return false;
2320 }
2321
Johnny Cheneeab4852011-02-16 22:14:44 +00002322 // A8.6.139 ROR (immediate)
2323 if (shift_type == SRType_ROR && imm5 == 0)
2324 shift_type = SRType_RRX;
2325
Johnny Chen82f16aa2011-02-15 20:10:55 +00002326 // Get the first operand.
2327 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2328 if (!success)
2329 return false;
2330
Johnny Cheneeab4852011-02-16 22:14:44 +00002331 // Decode the shift amount if not RRX.
2332 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002333
Johnny Chen41a0a152011-02-16 01:27:54 +00002334 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002335
2336 // The context specifies that an immediate is to be moved into Rd.
2337 EmulateInstruction::Context context;
2338 context.type = EmulateInstruction::eContextImmediate;
2339 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002340
Johnny Chenca67d1c2011-02-17 01:35:27 +00002341 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
2342 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002343 }
2344 return true;
2345}
2346
Johnny Chene7f89532011-02-15 23:22:46 +00002347bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002348EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002349{
Johnny Chen41a0a152011-02-16 01:27:54 +00002350 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002351
2352 bool success = false;
2353 const uint32_t opcode = OpcodeAsUnsigned (&success);
2354 if (!success)
2355 return false;
2356
2357 if (ConditionPassed())
2358 {
2359 uint32_t Rd; // the destination register
2360 uint32_t Rn; // the first operand register
2361 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2362 uint32_t carry; // the carry bit after the shift operation
2363 bool setflags;
2364 switch (encoding) {
2365 case eEncodingT1:
2366 Rd = Bits32(opcode, 2, 0);
2367 Rn = Rd;
2368 Rm = Bits32(opcode, 5, 3);
2369 setflags = !InITBlock();
2370 break;
2371 case eEncodingT2:
2372 Rd = Bits32(opcode, 11, 8);
2373 Rn = Bits32(opcode, 19, 16);
2374 Rm = Bits32(opcode, 3, 0);
2375 setflags = BitIsSet(opcode, 20);
2376 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2377 return false;
2378 break;
2379 case eEncodingA1:
2380 Rd = Bits32(opcode, 15, 12);
2381 Rn = Bits32(opcode, 3, 0);
2382 Rm = Bits32(opcode, 11, 8);
2383 setflags = BitIsSet(opcode, 20);
2384 if (Rd == 15 || Rn == 15 || Rm == 15)
2385 return false;
2386 break;
2387 default:
2388 return false;
2389 }
2390
2391 // Get the first operand.
2392 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2393 if (!success)
2394 return false;
2395 // Get the Rm register content.
2396 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2397 if (!success)
2398 return false;
2399
2400 // Get the shift amount.
2401 uint32_t amt = Bits32(val, 7, 0);
2402
Johnny Chen41a0a152011-02-16 01:27:54 +00002403 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002404
2405 // The context specifies that an immediate is to be moved into Rd.
2406 EmulateInstruction::Context context;
2407 context.type = EmulateInstruction::eContextImmediate;
2408 context.SetNoArgs ();
2409
Johnny Chenca67d1c2011-02-17 01:35:27 +00002410 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002411 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002412 }
2413 return true;
2414}
2415
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002416// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002417// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002418// can be written back to the base register.
2419bool
2420EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2421{
2422#if 0
2423 // ARM pseudo code...
2424 if ConditionPassed()
2425 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2426 address = R[n];
2427
2428 for i = 0 to 14
2429 if registers<i> == '1' then
2430 R[i] = MemA[address, 4]; address = address + 4;
2431 if registers<15> == '1' then
2432 LoadWritePC (MemA[address, 4]);
2433
2434 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2435 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2436
2437#endif
2438
2439 bool success = false;
2440 const uint32_t opcode = OpcodeAsUnsigned (&success);
2441 if (!success)
2442 return false;
2443
2444 if (ConditionPassed())
2445 {
2446 uint32_t n;
2447 uint32_t registers = 0;
2448 bool wback;
2449 const uint32_t addr_byte_size = GetAddressByteSize();
2450 switch (encoding)
2451 {
2452 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002453 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002454 n = Bits32 (opcode, 10, 8);
2455 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002456 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002457 wback = BitIsClear (registers, n);
2458 // if BitCount(registers) < 1 then UNPREDICTABLE;
2459 if (BitCount(registers) < 1)
2460 return false;
2461 break;
2462 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002463 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2464 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002465 n = Bits32 (opcode, 19, 16);
2466 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002467 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002468 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002469
2470 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002471 if ((n == 15)
2472 || (BitCount (registers) < 2)
2473 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2474 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002475
2476 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002477 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002478 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002479
2480 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002481 if (wback
2482 && BitIsSet (registers, n))
2483 return false;
2484 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002485
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002486 case eEncodingA1:
2487 n = Bits32 (opcode, 19, 16);
2488 registers = Bits32 (opcode, 15, 0);
2489 wback = BitIsSet (opcode, 21);
2490 if ((n == 15)
2491 || (BitCount (registers) < 1))
2492 return false;
2493 break;
2494 default:
2495 return false;
2496 }
2497
2498 int32_t offset = 0;
2499 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2500 if (!success)
2501 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002502
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002503 EmulateInstruction::Context context;
2504 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2505 Register dwarf_reg;
2506 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2507 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002508
2509 for (int i = 0; i < 14; ++i)
2510 {
2511 if (BitIsSet (registers, i))
2512 {
Caroline Tice85aab332011-02-08 23:56:10 +00002513 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002514 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002515 if (wback && (n == 13)) // Pop Instruction
2516 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2517
2518 // R[i] = MemA [address, 4]; address = address + 4;
2519 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2520 if (!success)
2521 return false;
2522
2523 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2524 return false;
2525
2526 offset += addr_byte_size;
2527 }
2528 }
2529
2530 if (BitIsSet (registers, 15))
2531 {
2532 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002533 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002534 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002535 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2536 if (!success)
2537 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002538 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002539 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002540 return false;
2541 }
2542
2543 if (wback && BitIsClear (registers, n))
2544 {
Caroline Ticefa172202011-02-11 22:49:54 +00002545 // R[n] = R[n] + 4 * BitCount (registers)
2546 int32_t offset = addr_byte_size * BitCount (registers);
2547 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002548 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002549
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2551 return false;
2552 }
2553 if (wback && BitIsSet (registers, n))
2554 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002555 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002556 }
2557 return true;
2558}
Caroline Tice713c2662011-02-11 17:59:55 +00002559
2560// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2561// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2562// can optionally be written back tot he base registers.
2563bool
2564EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2565{
2566#if 0
2567 // ARM pseudo code...
2568 if ConditionPassed() then
2569 EncodingSpecificOperations();
2570 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002571
Caroline Tice713c2662011-02-11 17:59:55 +00002572 for i = 0 to 14
2573 if registers<i> == ’1’ then
2574 R[i] = MemA[address,4]; address = address + 4;
2575
2576 if registers<15> == ’1’ then
2577 LoadWritePC(MemA[address,4]);
2578
2579 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2580 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2581#endif
2582
2583 bool success = false;
2584 const uint32_t opcode = OpcodeAsUnsigned (&success);
2585 if (!success)
2586 return false;
2587
2588 if (ConditionPassed())
2589 {
2590 uint32_t n;
2591 uint32_t registers = 0;
2592 bool wback;
2593 const uint32_t addr_byte_size = GetAddressByteSize();
2594
2595 // EncodingSpecificOperations();
2596 switch (encoding)
2597 {
2598 case eEncodingA1:
2599 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2600 n = Bits32 (opcode, 19, 16);
2601 registers = Bits32 (opcode, 15, 0);
2602 wback = BitIsSet (opcode, 21);
2603
2604 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2605 if ((n == 15) || (BitCount (registers) < 1))
2606 return false;
2607
2608 break;
2609
2610 default:
2611 return false;
2612 }
2613 // address = R[n] - 4*BitCount(registers) + 4;
2614
2615 int32_t offset = 0;
2616 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2617
2618 if (!success)
2619 return false;
2620
2621 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2622
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002623 EmulateInstruction::Context context;
2624 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2625 Register dwarf_reg;
2626 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2627 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002628
2629 // for i = 0 to 14
2630 for (int i = 0; i < 14; ++i)
2631 {
2632 // if registers<i> == ’1’ then
2633 if (BitIsSet (registers, i))
2634 {
2635 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002636 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002637 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2638 if (!success)
2639 return false;
2640 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2641 return false;
2642 offset += addr_byte_size;
2643 }
2644 }
2645
2646 // if registers<15> == ’1’ then
2647 // LoadWritePC(MemA[address,4]);
2648 if (BitIsSet (registers, 15))
2649 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002650 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002651 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2652 if (!success)
2653 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002654 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002655 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002656 return false;
2657 }
2658
2659 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2660 if (wback && BitIsClear (registers, n))
2661 {
Caroline Tice713c2662011-02-11 17:59:55 +00002662 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2663 if (!success)
2664 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002665
2666 offset = (addr_byte_size * BitCount (registers)) * -1;
2667 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002668 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002669 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002670 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2671 return false;
2672 }
2673
2674 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2675 if (wback && BitIsSet (registers, n))
2676 return WriteBits32Unknown (n);
2677 }
2678 return true;
2679}
2680
2681// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2682// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2683// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002684bool
2685EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2686{
2687#if 0
2688 // ARM pseudo code...
2689 if ConditionPassed() then
2690 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2691 address = R[n] - 4*BitCount(registers);
2692
2693 for i = 0 to 14
2694 if registers<i> == ’1’ then
2695 R[i] = MemA[address,4]; address = address + 4;
2696 if registers<15> == ’1’ then
2697 LoadWritePC(MemA[address,4]);
2698
2699 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2700 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2701#endif
2702
2703 bool success = false;
2704 const uint32_t opcode = OpcodeAsUnsigned (&success);
2705 if (!success)
2706 return false;
2707
2708 if (ConditionPassed())
2709 {
2710 uint32_t n;
2711 uint32_t registers = 0;
2712 bool wback;
2713 const uint32_t addr_byte_size = GetAddressByteSize();
2714 switch (encoding)
2715 {
2716 case eEncodingT1:
2717 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2718 n = Bits32 (opcode, 19, 16);
2719 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002720 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002721 wback = BitIsSet (opcode, 21);
2722
2723 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2724 if ((n == 15)
2725 || (BitCount (registers) < 2)
2726 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2727 return false;
2728
2729 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002730 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002731 return false;
2732
2733 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2734 if (wback && BitIsSet (registers, n))
2735 return false;
2736
2737 break;
2738
2739 case eEncodingA1:
2740 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2741 n = Bits32 (opcode, 19, 16);
2742 registers = Bits32 (opcode, 15, 0);
2743 wback = BitIsSet (opcode, 21);
2744
2745 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2746 if ((n == 15) || (BitCount (registers) < 1))
2747 return false;
2748
2749 break;
2750
2751 default:
2752 return false;
2753 }
2754
Caroline Tice713c2662011-02-11 17:59:55 +00002755 // address = R[n] - 4*BitCount(registers);
2756
Caroline Tice0b29e242011-02-08 23:16:02 +00002757 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002758 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2759
2760 if (!success)
2761 return false;
2762
2763 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002764 EmulateInstruction::Context context;
2765 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2766 Register dwarf_reg;
2767 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2768 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002769
2770 for (int i = 0; i < 14; ++i)
2771 {
2772 if (BitIsSet (registers, i))
2773 {
2774 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002775 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002776 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2777 if (!success)
2778 return false;
2779
2780 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2781 return false;
2782
2783 offset += addr_byte_size;
2784 }
2785 }
2786
2787 // if registers<15> == ’1’ then
2788 // LoadWritePC(MemA[address,4]);
2789 if (BitIsSet (registers, 15))
2790 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002791 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002792 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2793 if (!success)
2794 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002795 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002796 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002797 return false;
2798 }
2799
2800 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2801 if (wback && BitIsClear (registers, n))
2802 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002803 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2804 if (!success)
2805 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002806
2807 offset = (addr_byte_size * BitCount (registers)) * -1;
2808 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002809 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002810 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002811 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2812 return false;
2813 }
2814
2815 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2816 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002817 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002818 }
2819 return true;
2820}
Caroline Tice85aab332011-02-08 23:56:10 +00002821
Caroline Tice713c2662011-02-11 17:59:55 +00002822// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2823// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2824// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002825bool
2826EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2827{
2828#if 0
2829 if ConditionPassed() then
2830 EncodingSpecificOperations();
2831 address = R[n] + 4;
2832
2833 for i = 0 to 14
2834 if registers<i> == ’1’ then
2835 R[i] = MemA[address,4]; address = address + 4;
2836 if registers<15> == ’1’ then
2837 LoadWritePC(MemA[address,4]);
2838
2839 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2840 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2841#endif
2842
2843 bool success = false;
2844 const uint32_t opcode = OpcodeAsUnsigned (&success);
2845 if (!success)
2846 return false;
2847
2848 if (ConditionPassed())
2849 {
2850 uint32_t n;
2851 uint32_t registers = 0;
2852 bool wback;
2853 const uint32_t addr_byte_size = GetAddressByteSize();
2854 switch (encoding)
2855 {
2856 case eEncodingA1:
2857 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2858 n = Bits32 (opcode, 19, 16);
2859 registers = Bits32 (opcode, 15, 0);
2860 wback = BitIsSet (opcode, 21);
2861
2862 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2863 if ((n == 15) || (BitCount (registers) < 1))
2864 return false;
2865
2866 break;
2867 default:
2868 return false;
2869 }
2870 // address = R[n] + 4;
2871
2872 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002873 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2874
2875 if (!success)
2876 return false;
2877
2878 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002879
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002880 EmulateInstruction::Context context;
2881 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2882 Register dwarf_reg;
2883 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2884 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002885
2886 for (int i = 0; i < 14; ++i)
2887 {
2888 if (BitIsSet (registers, i))
2889 {
2890 // R[i] = MemA[address,4]; address = address + 4;
2891
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002892 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002893 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2894 if (!success)
2895 return false;
2896
2897 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2898 return false;
2899
2900 offset += addr_byte_size;
2901 }
2902 }
2903
2904 // if registers<15> == ’1’ then
2905 // LoadWritePC(MemA[address,4]);
2906 if (BitIsSet (registers, 15))
2907 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002908 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002909 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2910 if (!success)
2911 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002912 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002913 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002914 return false;
2915 }
2916
2917 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2918 if (wback && BitIsClear (registers, n))
2919 {
Caroline Tice85aab332011-02-08 23:56:10 +00002920 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2921 if (!success)
2922 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002923
2924 offset = addr_byte_size * BitCount (registers);
2925 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002926 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002927 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002928 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2929 return false;
2930 }
2931
2932 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2933 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002934 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002935 }
2936 return true;
2937}
Caroline Tice0b29e242011-02-08 23:16:02 +00002938
Johnny Chenef21b592011-02-10 01:52:38 +00002939// Load Register (immediate) calculates an address from a base register value and
2940// an immediate offset, loads a word from memory, and writes to a register.
2941// LDR (immediate, Thumb)
2942bool
2943EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2944{
2945#if 0
2946 // ARM pseudo code...
2947 if (ConditionPassed())
2948 {
2949 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2950 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2951 address = if index then offset_addr else R[n];
2952 data = MemU[address,4];
2953 if wback then R[n] = offset_addr;
2954 if t == 15 then
2955 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2956 elsif UnalignedSupport() || address<1:0> = '00' then
2957 R[t] = data;
2958 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2959 }
2960#endif
2961
2962 bool success = false;
2963 const uint32_t opcode = OpcodeAsUnsigned (&success);
2964 if (!success)
2965 return false;
2966
2967 if (ConditionPassed())
2968 {
2969 uint32_t Rt; // the destination register
2970 uint32_t Rn; // the base register
2971 uint32_t imm32; // the immediate offset used to form the address
2972 addr_t offset_addr; // the offset address
2973 addr_t address; // the calculated address
2974 uint32_t data; // the literal data value from memory load
2975 bool add, index, wback;
2976 switch (encoding) {
2977 case eEncodingT1:
2978 Rt = Bits32(opcode, 5, 3);
2979 Rn = Bits32(opcode, 2, 0);
2980 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2981 // index = TRUE; add = TRUE; wback = FALSE
2982 add = true;
2983 index = true;
2984 wback = false;
2985 break;
2986 default:
2987 return false;
2988 }
2989 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2990 if (!success)
2991 return false;
2992 if (add)
2993 offset_addr = base + imm32;
2994 else
2995 offset_addr = base - imm32;
2996
2997 address = (index ? offset_addr : base);
2998
2999 if (wback)
3000 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003001 EmulateInstruction::Context ctx;
3002 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3003 Register dwarf_reg;
3004 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3005 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3006
Johnny Chenef21b592011-02-10 01:52:38 +00003007 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3008 return false;
3009 }
3010
3011 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003012 EmulateInstruction::Context context;
3013 context.type = EmulateInstruction::eContextImmediate;
3014 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003015
3016 // Read memory from the address.
3017 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
3018 if (!success)
3019 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003020
3021 if (Rt == 15)
3022 {
3023 if (Bits32(address, 1, 0) == 0)
3024 {
Johnny Chen668b4512011-02-15 21:08:58 +00003025 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003026 return false;
3027 }
3028 else
3029 return false;
3030 }
3031 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3032 {
3033 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3034 return false;
3035 }
3036 else
3037 return false;
3038 }
3039 return true;
3040}
3041
Caroline Ticeaf556562011-02-15 18:42:15 +00003042// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3043// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3044// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003045bool
3046EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3047{
3048#if 0
3049 if ConditionPassed() then
3050 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3051 address = R[n];
3052
3053 for i = 0 to 14
3054 if registers<i> == ’1’ then
3055 if i == n && wback && i != LowestSetBit(registers) then
3056 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3057 else
3058 MemA[address,4] = R[i];
3059 address = address + 4;
3060
3061 if registers<15> == ’1’ then // Only possible for encoding A1
3062 MemA[address,4] = PCStoreValue();
3063 if wback then R[n] = R[n] + 4*BitCount(registers);
3064#endif
3065
3066 bool success = false;
3067 const uint32_t opcode = OpcodeAsUnsigned (&success);
3068 if (!success)
3069 return false;
3070
3071 if (ConditionPassed ())
3072 {
3073 uint32_t n;
3074 uint32_t registers = 0;
3075 bool wback;
3076 const uint32_t addr_byte_size = GetAddressByteSize();
3077
3078 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3079 switch (encoding)
3080 {
3081 case eEncodingT1:
3082 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3083 n = Bits32 (opcode, 10, 8);
3084 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003085 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003086 wback = true;
3087
3088 // if BitCount(registers) < 1 then UNPREDICTABLE;
3089 if (BitCount (registers) < 1)
3090 return false;
3091
3092 break;
3093
3094 case eEncodingT2:
3095 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3096 n = Bits32 (opcode, 19, 16);
3097 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003098 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003099 wback = BitIsSet (opcode, 21);
3100
3101 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3102 if ((n == 15) || (BitCount (registers) < 2))
3103 return false;
3104
3105 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3106 if (wback && BitIsSet (registers, n))
3107 return false;
3108
3109 break;
3110
3111 case eEncodingA1:
3112 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3113 n = Bits32 (opcode, 19, 16);
3114 registers = Bits32 (opcode, 15, 0);
3115 wback = BitIsSet (opcode, 21);
3116
3117 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3118 if ((n == 15) || (BitCount (registers) < 1))
3119 return false;
3120
3121 break;
3122
3123 default:
3124 return false;
3125 }
3126
3127 // address = R[n];
3128 int32_t offset = 0;
3129 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3130 if (!success)
3131 return false;
3132
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003133 EmulateInstruction::Context context;
3134 context.type = EmulateInstruction::eContextRegisterStore;
3135 Register base_reg;
3136 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003137
3138 // for i = 0 to 14
3139 for (int i = 0; i < 14; ++i)
3140 {
3141 int lowest_set_bit = 14;
3142 // if registers<i> == ’1’ then
3143 if (BitIsSet (registers, i))
3144 {
3145 if (i < lowest_set_bit)
3146 lowest_set_bit = i;
3147 // if i == n && wback && i != LowestSetBit(registers) then
3148 if ((i == n) && wback && (i != lowest_set_bit))
3149 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3150 WriteBits32UnknownToMemory (address + offset);
3151 else
3152 {
3153 // MemA[address,4] = R[i];
3154 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3155 if (!success)
3156 return false;
3157
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003158 Register data_reg;
3159 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3160 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003161 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3162 return false;
3163 }
3164
3165 // address = address + 4;
3166 offset += addr_byte_size;
3167 }
3168 }
3169
3170 // if registers<15> == ’1’ then // Only possible for encoding A1
3171 // MemA[address,4] = PCStoreValue();
3172 if (BitIsSet (registers, 15))
3173 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003174 Register pc_reg;
3175 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3176 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003177 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3178 if (!success)
3179 return false;
3180
3181 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3182 return false;
3183 }
3184
3185 // if wback then R[n] = R[n] + 4*BitCount(registers);
3186 if (wback)
3187 {
3188 offset = addr_byte_size * BitCount (registers);
3189 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003190 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003191 addr_t data = address + offset;
3192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3193 return false;
3194 }
3195 }
3196 return true;
3197}
3198
Caroline Ticeaf556562011-02-15 18:42:15 +00003199// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3200// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3201// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003202bool
3203EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3204{
3205#if 0
3206 if ConditionPassed() then
3207 EncodingSpecificOperations();
3208 address = R[n] - 4*BitCount(registers) + 4;
3209
3210 for i = 0 to 14
3211 if registers<i> == ’1’ then
3212 if i == n && wback && i != LowestSetBit(registers) then
3213 MemA[address,4] = bits(32) UNKNOWN;
3214 else
3215 MemA[address,4] = R[i];
3216 address = address + 4;
3217
3218 if registers<15> == ’1’ then
3219 MemA[address,4] = PCStoreValue();
3220
3221 if wback then R[n] = R[n] - 4*BitCount(registers);
3222#endif
3223
3224 bool success = false;
3225 const uint32_t opcode = OpcodeAsUnsigned (&success);
3226 if (!success)
3227 return false;
3228
3229 if (ConditionPassed ())
3230 {
3231 uint32_t n;
3232 uint32_t registers = 0;
3233 bool wback;
3234 const uint32_t addr_byte_size = GetAddressByteSize();
3235
3236 // EncodingSpecificOperations();
3237 switch (encoding)
3238 {
3239 case eEncodingA1:
3240 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3241 n = Bits32 (opcode, 19, 16);
3242 registers = Bits32 (opcode, 15, 0);
3243 wback = BitIsSet (opcode, 21);
3244
3245 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3246 if ((n == 15) || (BitCount (registers) < 1))
3247 return false;
3248 break;
3249 default:
3250 return false;
3251 }
3252
3253 // address = R[n] - 4*BitCount(registers) + 4;
3254 int32_t offset = 0;
3255 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3256 if (!success)
3257 return false;
3258
3259 address = address - (addr_byte_size * BitCount (registers)) + 4;
3260
3261 EmulateInstruction::Context context;
3262 context.type = EmulateInstruction::eContextRegisterStore;
3263 Register base_reg;
3264 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3265
3266 // for i = 0 to 14
3267 for (int i = 0; i < 14; ++i)
3268 {
3269 int lowest_bit_set = 14;
3270 // if registers<i> == ’1’ then
3271 if (BitIsSet (registers, i))
3272 {
3273 if (i < lowest_bit_set)
3274 lowest_bit_set = i;
3275 //if i == n && wback && i != LowestSetBit(registers) then
3276 if ((i == n) && wback && (i != lowest_bit_set))
3277 // MemA[address,4] = bits(32) UNKNOWN;
3278 WriteBits32UnknownToMemory (address + offset);
3279 else
3280 {
3281 // MemA[address,4] = R[i];
3282 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3283 if (!success)
3284 return false;
3285
3286 Register data_reg;
3287 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3288 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3289 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3290 return false;
3291 }
3292
3293 // address = address + 4;
3294 offset += addr_byte_size;
3295 }
3296 }
3297
3298 // if registers<15> == ’1’ then
3299 // MemA[address,4] = PCStoreValue();
3300 if (BitIsSet (registers, 15))
3301 {
3302 Register pc_reg;
3303 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3304 context.SetRegisterPlusOffset (pc_reg, 8);
3305 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3306 if (!success)
3307 return false;
3308
3309 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3310 return false;
3311 }
3312
3313 // if wback then R[n] = R[n] - 4*BitCount(registers);
3314 if (wback)
3315 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003316 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003317 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3318 context.SetImmediateSigned (offset);
3319 addr_t data = address + offset;
3320 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3321 return false;
3322 }
3323 }
3324 return true;
3325}
3326
Caroline Ticeaf556562011-02-15 18:42:15 +00003327// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3328// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3329// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003330bool
3331EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3332{
3333#if 0
3334 if ConditionPassed() then
3335 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3336 address = R[n] - 4*BitCount(registers);
3337
3338 for i = 0 to 14
3339 if registers<i> == ’1’ then
3340 if i == n && wback && i != LowestSetBit(registers) then
3341 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3342 else
3343 MemA[address,4] = R[i];
3344 address = address + 4;
3345
3346 if registers<15> == ’1’ then // Only possible for encoding A1
3347 MemA[address,4] = PCStoreValue();
3348
3349 if wback then R[n] = R[n] - 4*BitCount(registers);
3350#endif
3351
3352
3353 bool success = false;
3354 const uint32_t opcode = OpcodeAsUnsigned (&success);
3355 if (!success)
3356 return false;
3357
3358 if (ConditionPassed ())
3359 {
3360 uint32_t n;
3361 uint32_t registers = 0;
3362 bool wback;
3363 const uint32_t addr_byte_size = GetAddressByteSize();
3364
3365 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3366 switch (encoding)
3367 {
3368 case eEncodingT1:
3369 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3370 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3371 {
3372 // See PUSH
3373 }
3374 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3375 n = Bits32 (opcode, 19, 16);
3376 registers = Bits32 (opcode, 15, 0);
3377 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3378 wback = BitIsSet (opcode, 21);
3379 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3380 if ((n == 15) || BitCount (registers) < 2)
3381 return false;
3382 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3383 if (wback && BitIsSet (registers, n))
3384 return false;
3385 break;
3386
3387 case eEncodingA1:
3388 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3389 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3390 {
3391 // See Push
3392 }
3393 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3394 n = Bits32 (opcode, 19, 16);
3395 registers = Bits32 (opcode, 15, 0);
3396 wback = BitIsSet (opcode, 21);
3397 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3398 if ((n == 15) || BitCount (registers) < 1)
3399 return false;
3400 break;
3401
3402 default:
3403 return false;
3404 }
3405
3406 // address = R[n] - 4*BitCount(registers);
3407
3408 int32_t offset = 0;
3409 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3410 if (!success)
3411 return false;
3412
3413 address = address - (addr_byte_size * BitCount (registers));
3414
3415 EmulateInstruction::Context context;
3416 context.type = EmulateInstruction::eContextRegisterStore;
3417 Register base_reg;
3418 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3419
3420 // for i = 0 to 14
3421 for (int i = 0; i < 14; ++i)
3422 {
3423 uint32_t lowest_set_bit = 14;
3424 // if registers<i> == ’1’ then
3425 if (BitIsSet (registers, i))
3426 {
3427 if (i < lowest_set_bit)
3428 lowest_set_bit = i;
3429 // if i == n && wback && i != LowestSetBit(registers) then
3430 if ((i == n) && wback && (i != lowest_set_bit))
3431 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3432 WriteBits32UnknownToMemory (address + offset);
3433 else
3434 {
3435 // MemA[address,4] = R[i];
3436 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3437 if (!success)
3438 return false;
3439
3440 Register data_reg;
3441 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3442 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3443 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3444 return false;
3445 }
3446
3447 // address = address + 4;
3448 offset += addr_byte_size;
3449 }
3450 }
3451
3452 // if registers<15> == ’1’ then // Only possible for encoding A1
3453 // MemA[address,4] = PCStoreValue();
3454 if (BitIsSet (registers, 15))
3455 {
3456 Register pc_reg;
3457 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3458 context.SetRegisterPlusOffset (pc_reg, 8);
3459 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3460 if (!success)
3461 return false;
3462
3463 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3464 return false;
3465 }
3466
3467 // if wback then R[n] = R[n] - 4*BitCount(registers);
3468 if (wback)
3469 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003470 offset = (addr_byte_size * BitCount (registers)) * -1;
3471 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3472 context.SetImmediateSigned (offset);
3473 addr_t data = address + offset;
3474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3475 return false;
3476 }
3477 }
3478 return true;
3479}
3480
3481// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3482// from a base register. The consecutive memory locations start just above this address, and the address of the last
3483// of those locations can optionally be written back to the base register.
3484bool
3485EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3486{
3487#if 0
3488 if ConditionPassed() then
3489 EncodingSpecificOperations();
3490 address = R[n] + 4;
3491
3492 for i = 0 to 14
3493 if registers<i> == ’1’ then
3494 if i == n && wback && i != LowestSetBit(registers) then
3495 MemA[address,4] = bits(32) UNKNOWN;
3496 else
3497 MemA[address,4] = R[i];
3498 address = address + 4;
3499
3500 if registers<15> == ’1’ then
3501 MemA[address,4] = PCStoreValue();
3502
3503 if wback then R[n] = R[n] + 4*BitCount(registers);
3504#endif
3505
3506 bool success = false;
3507 const uint32_t opcode = OpcodeAsUnsigned (&success);
3508 if (!success)
3509 return false;
3510
3511 if (ConditionPassed())
3512 {
3513 uint32_t n;
3514 uint32_t registers = 0;
3515 bool wback;
3516 const uint32_t addr_byte_size = GetAddressByteSize();
3517
3518 // EncodingSpecificOperations();
3519 switch (encoding)
3520 {
3521 case eEncodingA1:
3522 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3523 n = Bits32 (opcode, 19, 16);
3524 registers = Bits32 (opcode, 15, 0);
3525 wback = BitIsSet (opcode, 21);
3526
3527 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3528 if ((n == 15) && (BitCount (registers) < 1))
3529 return false;
3530 break;
3531 default:
3532 return false;
3533 }
3534 // address = R[n] + 4;
3535
3536 int32_t offset = 0;
3537 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3538 if (!success)
3539 return false;
3540
3541 address = address + addr_byte_size;
3542
3543 EmulateInstruction::Context context;
3544 context.type = EmulateInstruction::eContextRegisterStore;
3545 Register base_reg;
3546 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3547
3548 uint32_t lowest_set_bit = 14;
3549 // for i = 0 to 14
3550 for (int i = 0; i < 14; ++i)
3551 {
3552 // if registers<i> == ’1’ then
3553 if (BitIsSet (registers, i))
3554 {
3555 if (i < lowest_set_bit)
3556 lowest_set_bit = i;
3557 // if i == n && wback && i != LowestSetBit(registers) then
3558 if ((i == n) && wback && (i != lowest_set_bit))
3559 // MemA[address,4] = bits(32) UNKNOWN;
3560 WriteBits32UnknownToMemory (address + offset);
3561 // else
3562 else
3563 {
3564 // MemA[address,4] = R[i];
3565 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3566 if (!success)
3567 return false;
3568
3569 Register data_reg;
3570 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3571 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3572 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
3573 return false;
3574 }
3575
3576 // address = address + 4;
3577 offset += addr_byte_size;
3578 }
3579 }
3580
3581 // if registers<15> == ’1’ then
3582 // MemA[address,4] = PCStoreValue();
3583 if (BitIsSet (registers, 15))
3584 {
3585 Register pc_reg;
3586 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3587 context.SetRegisterPlusOffset (pc_reg, 8);
3588 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3589 if (!success)
3590 return false;
3591
3592 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
3593 return false;
3594 }
3595
3596 // if wback then R[n] = R[n] + 4*BitCount(registers);
3597 if (wback)
3598 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003599 offset = addr_byte_size * BitCount (registers);
3600 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3601 context.SetImmediateSigned (offset);
3602 addr_t data = address + offset;
3603 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3604 return false;
3605 }
3606 }
3607 return true;
3608}
Caroline Tice7fac8572011-02-15 22:53:54 +00003609
3610// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3611// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3612bool
3613EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3614{
3615#if 0
3616 if ConditionPassed() then
3617 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3618 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3619 address = if index then offset_addr else R[n];
3620 if UnalignedSupport() || address<1:0> == ’00’ then
3621 MemU[address,4] = R[t];
3622 else // Can only occur before ARMv7
3623 MemU[address,4] = bits(32) UNKNOWN;
3624 if wback then R[n] = offset_addr;
3625#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003626
Caroline Tice7fac8572011-02-15 22:53:54 +00003627 bool success = false;
3628 const uint32_t opcode = OpcodeAsUnsigned (&success);
3629 if (!success)
3630 return false;
3631
3632 if (ConditionPassed())
3633 {
3634 const uint32_t addr_byte_size = GetAddressByteSize();
3635
3636 uint32_t t;
3637 uint32_t n;
3638 uint32_t imm32;
3639 bool index;
3640 bool add;
3641 bool wback;
3642 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3643 switch (encoding)
3644 {
3645 case eEncodingT1:
3646 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3647 t = Bits32 (opcode, 2, 0);
3648 n = Bits32 (opcode, 5, 3);
3649 imm32 = Bits32 (opcode, 10, 6) << 2;
3650
3651 // index = TRUE; add = TRUE; wback = FALSE;
3652 index = true;
3653 add = false;
3654 wback = false;
3655 break;
3656
3657 case eEncodingT2:
3658 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3659 t = Bits32 (opcode, 10, 8);
3660 n = 13;
3661 imm32 = Bits32 (opcode, 7, 0) << 2;
3662
3663 // index = TRUE; add = TRUE; wback = FALSE;
3664 index = true;
3665 add = true;
3666 wback = false;
3667 break;
3668
3669 case eEncodingT3:
3670 // if Rn == ’1111’ then UNDEFINED;
3671 if (Bits32 (opcode, 19, 16) == 15)
3672 return false;
3673
3674 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3675 t = Bits32 (opcode, 15, 12);
3676 n = Bits32 (opcode, 19, 16);
3677 imm32 = Bits32 (opcode, 11, 0);
3678
3679 // index = TRUE; add = TRUE; wback = FALSE;
3680 index = true;
3681 add = true;
3682 wback = false;
3683
3684 // if t == 15 then UNPREDICTABLE;
3685 if (t == 15)
3686 return false;
3687 break;
3688
3689 case eEncodingT4:
3690 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3691 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3692 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3693 if ((Bits32 (opcode, 19, 16) == 15)
3694 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3695 return false;
3696
3697 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3698 t = Bits32 (opcode, 15, 12);
3699 n = Bits32 (opcode, 19, 16);
3700 imm32 = Bits32 (opcode, 7, 0);
3701
3702 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3703 index = BitIsSet (opcode, 10);
3704 add = BitIsSet (opcode, 9);
3705 wback = BitIsSet (opcode, 8);
3706
3707 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3708 if ((t == 15) || (wback && (n == t)))
3709 return false;
3710 break;
3711
3712 default:
3713 return false;
3714 }
3715
3716 addr_t offset_addr;
3717 addr_t address;
3718
3719 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3720 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3721 if (!success)
3722 return false;
3723
3724 if (add)
3725 offset_addr = base_address + imm32;
3726 else
3727 offset_addr = base_address - imm32;
3728
3729 // address = if index then offset_addr else R[n];
3730 if (index)
3731 address = offset_addr;
3732 else
3733 address = base_address;
3734
3735 EmulateInstruction::Context context;
3736 context.type = eContextRegisterStore;
3737 Register base_reg;
3738 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3739
3740 // if UnalignedSupport() || address<1:0> == ’00’ then
3741 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3742 {
3743 // MemU[address,4] = R[t];
3744 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3745 if (!success)
3746 return false;
3747
3748 Register data_reg;
3749 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3750 int32_t offset = address - base_address;
3751 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3752 if (!WriteMemoryUnsigned (context, address, data, addr_byte_size))
3753 return false;
3754 }
3755 else
3756 {
3757 // MemU[address,4] = bits(32) UNKNOWN;
3758 WriteBits32UnknownToMemory (address);
3759 }
3760
3761 // if wback then R[n] = offset_addr;
3762 if (wback)
3763 {
3764 context.type = eContextRegisterLoad;
3765 context.SetAddress (offset_addr);
3766 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3767 return false;
3768 }
3769 }
3770 return true;
3771}
Caroline Ticeaf556562011-02-15 18:42:15 +00003772
Caroline Tice3fd63e92011-02-16 00:33:43 +00003773// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3774// word from a register to memory. The offset register value can optionally be shifted.
3775bool
3776EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3777{
3778#if 0
3779 if ConditionPassed() then
3780 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3781 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3782 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3783 address = if index then offset_addr else R[n];
3784 if t == 15 then // Only possible for encoding A1
3785 data = PCStoreValue();
3786 else
3787 data = R[t];
3788 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3789 MemU[address,4] = data;
3790 else // Can only occur before ARMv7
3791 MemU[address,4] = bits(32) UNKNOWN;
3792 if wback then R[n] = offset_addr;
3793#endif
3794
3795 bool success = false;
3796 const uint32_t opcode = OpcodeAsUnsigned (&success);
3797 if (!success)
3798 return false;
3799
3800 if (ConditionPassed())
3801 {
3802 const uint32_t addr_byte_size = GetAddressByteSize();
3803
3804 uint32_t t;
3805 uint32_t n;
3806 uint32_t m;
3807 ARM_ShifterType shift_t;
3808 uint32_t shift_n;
3809 bool index;
3810 bool add;
3811 bool wback;
3812
3813 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3814 switch (encoding)
3815 {
3816 case eEncodingT1:
3817 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3818 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3819 t = Bits32 (opcode, 2, 0);
3820 n = Bits32 (opcode, 5, 3);
3821 m = Bits32 (opcode, 8, 6);
3822
3823 // index = TRUE; add = TRUE; wback = FALSE;
3824 index = true;
3825 add = true;
3826 wback = false;
3827
3828 // (shift_t, shift_n) = (SRType_LSL, 0);
3829 shift_t = SRType_LSL;
3830 shift_n = 0;
3831 break;
3832
3833 case eEncodingT2:
3834 // if Rn == ’1111’ then UNDEFINED;
3835 if (Bits32 (opcode, 19, 16) == 15)
3836 return false;
3837
3838 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3839 t = Bits32 (opcode, 15, 12);
3840 n = Bits32 (opcode, 19, 16);
3841 m = Bits32 (opcode, 3, 0);
3842
3843 // index = TRUE; add = TRUE; wback = FALSE;
3844 index = true;
3845 add = true;
3846 wback = false;
3847
3848 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3849 shift_t = SRType_LSL;
3850 shift_n = Bits32 (opcode, 5, 4);
3851
3852 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3853 if ((t == 15) || (BadReg (m)))
3854 return false;
3855 break;
3856
3857 case eEncodingA1:
3858 {
3859 // if P == ’0’ && W == ’1’ then SEE STRT;
3860 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3861 t = Bits32 (opcode, 15, 12);
3862 n = Bits32 (opcode, 19, 16);
3863 m = Bits32 (opcode, 3, 0);
3864
3865 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3866 index = BitIsSet (opcode, 24);
3867 add = BitIsSet (opcode, 23);
3868 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3869
3870 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3871 uint32_t typ = Bits32 (opcode, 6, 5);
3872 uint32_t imm5 = Bits32 (opcode, 11, 7);
3873 shift_n = DecodeImmShift(typ, imm5, shift_t);
3874
3875 // if m == 15 then UNPREDICTABLE;
3876 if (m == 15)
3877 return false;
3878
3879 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3880 if (wback && ((n == 15) || (n == t)))
3881 return false;
3882
3883 break;
3884 }
3885 default:
3886 return false;
3887 }
3888
3889 addr_t offset_addr;
3890 addr_t address;
3891 int32_t offset = 0;
3892
3893 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3894 if (!success)
3895 return false;
3896
3897 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3898 if (!success)
3899 return false;
3900
3901 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
3902 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
3903
3904 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3905 if (add)
3906 offset_addr = base_address + offset;
3907 else
3908 offset_addr = base_address - offset;
3909
3910 // address = if index then offset_addr else R[n];
3911 if (index)
3912 address = offset_addr;
3913 else
3914 address = base_address;
3915
3916 uint32_t data;
3917 // if t == 15 then // Only possible for encoding A1
3918 if (t == 15)
3919 // data = PCStoreValue();
3920 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3921 else
3922 // data = R[t];
3923 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3924
3925 if (!success)
3926 return false;
3927
3928 EmulateInstruction::Context context;
3929 context.type = eContextRegisterStore;
3930
3931 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3932 if (UnalignedSupport ()
3933 || (BitIsClear (address, 1) && BitIsClear (address, 0))
3934 || CurrentInstrSet() == eModeARM)
3935 {
3936 // MemU[address,4] = data;
3937
3938 Register base_reg;
3939 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3940
3941 Register data_reg;
3942 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3943
3944 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
3945 if (!WriteMemoryUnsigned (context, address, data, addr_byte_size))
3946 return false;
3947
3948 }
3949 else
3950 // MemU[address,4] = bits(32) UNKNOWN;
3951 WriteBits32UnknownToMemory (address);
3952
3953 // if wback then R[n] = offset_addr;
3954 if (wback)
3955 {
3956 context.type = eContextRegisterLoad;
3957 context.SetAddress (offset_addr);
3958 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3959 return false;
3960 }
3961
3962 }
3963 return true;
3964}
Caroline Tice73a29de2011-02-16 20:22:22 +00003965
3966bool
3967EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
3968{
3969#if 0
3970 if ConditionPassed() then
3971 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3972 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3973 address = if index then offset_addr else R[n];
3974 MemU[address,1] = R[t]<7:0>;
3975 if wback then R[n] = offset_addr;
3976#endif
3977
3978
3979 bool success = false;
3980 const uint32_t opcode = OpcodeAsUnsigned (&success);
3981 if (!success)
3982 return false;
3983
3984 if (ConditionPassed ())
3985 {
3986 uint32_t t;
3987 uint32_t n;
3988 uint32_t imm32;
3989 bool index;
3990 bool add;
3991 bool wback;
3992 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3993 switch (encoding)
3994 {
3995 case eEncodingT1:
3996 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
3997 t = Bits32 (opcode, 2, 0);
3998 n = Bits32 (opcode, 5, 3);
3999 imm32 = Bits32 (opcode, 10, 6);
4000
4001 // index = TRUE; add = TRUE; wback = FALSE;
4002 index = true;
4003 add = true;
4004 wback = false;
4005 break;
4006
4007 case eEncodingT2:
4008 // if Rn == ’1111’ then UNDEFINED;
4009 if (Bits32 (opcode, 19, 16) == 15)
4010 return false;
4011
4012 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4013 t = Bits32 (opcode, 15, 12);
4014 n = Bits32 (opcode, 19, 16);
4015 imm32 = Bits32 (opcode, 11, 0);
4016
4017 // index = TRUE; add = TRUE; wback = FALSE;
4018 index = true;
4019 add = true;
4020 wback = false;
4021
4022 // if BadReg(t) then UNPREDICTABLE;
4023 if (BadReg (t))
4024 return false;
4025 break;
4026
4027 case eEncodingT3:
4028 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4029 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4030 if (Bits32 (opcode, 19, 16) == 15)
4031 return false;
4032
4033 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4034 t = Bits32 (opcode, 15, 12);
4035 n = Bits32 (opcode, 19, 16);
4036 imm32 = Bits32 (opcode, 7, 0);
4037
4038 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4039 index = BitIsSet (opcode, 10);
4040 add = BitIsSet (opcode, 9);
4041 wback = BitIsSet (opcode, 8);
4042
4043 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4044 if ((BadReg (t)) || (wback && (n == t)))
4045 return false;
4046 break;
4047
4048 default:
4049 return false;
4050 }
4051
4052 addr_t offset_addr;
4053 addr_t address;
4054 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4055 if (!success)
4056 return false;
4057
4058 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4059 if (add)
4060 offset_addr = base_address + imm32;
4061 else
4062 offset_addr = base_address - imm32;
4063
4064 // address = if index then offset_addr else R[n];
4065 if (index)
4066 address = offset_addr;
4067 else
4068 address = base_address;
4069
4070 // MemU[address,1] = R[t]<7:0>; NOTE: "MemU' means UNALIGNED memory access
4071 Register base_reg;
4072 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4073
4074 Register data_reg;
4075 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4076
4077 EmulateInstruction::Context context;
4078 context.type = eContextRegisterStore;
4079 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4080
4081 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4082 if (!success)
4083 return false;
4084
4085 data = Bits32 (data, 7, 0);
4086
4087 if (!WriteMemoryUnsigned (context, address, data, 1))
4088 return false;
4089
4090 // if wback then R[n] = offset_addr;
4091 if (wback)
4092 {
4093 context.type = eContextRegisterLoad;
4094 context.SetAddress (offset_addr);
4095 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4096 return false;
4097 }
4098
4099 }
4100
4101 return true;
4102}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004103
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004104EmulateInstructionARM::ARMOpcode*
4105EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004106{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004107 static ARMOpcode
4108 g_arm_opcodes[] =
4109 {
4110 //----------------------------------------------------------------------
4111 // Prologue instructions
4112 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004113
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004114 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004115 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
4116 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004117
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004118 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004119 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
4120 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004121 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00004122 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
4123 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
4124 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004125
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004126 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004127 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004128
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004129 // push one register
4130 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004131 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004132
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004133 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004134 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4135 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004136
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004137 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004138 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004139 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004140
Johnny Chenc28a76d2011-02-01 18:51:48 +00004141 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
4142 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004143 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004144 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4145
4146 //----------------------------------------------------------------------
4147 // Supervisor Call (previously Software Interrupt)
4148 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004149 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4150
4151 //----------------------------------------------------------------------
4152 // Branch instructions
4153 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004154 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004155 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4156 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4157 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4158 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004159 // for example, "bx lr"
4160 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004161
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004162 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004163 // Data-processing instructions
4164 //----------------------------------------------------------------------
4165 // move bitwise not
4166 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004167 // asr (immediate)
4168 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004169 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004170 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004171 // lsl (immediate)
4172 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4173 // lsl (register)
4174 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4175 // lsr (immediate)
4176 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4177 // lsr (register)
4178 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004179 // rrx is a special case encoding of ror (immediate)
4180 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4181 // ror (immediate)
4182 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4183 // ror (register)
4184 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004185
4186 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004187 // Load instructions
4188 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004189 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004190 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004191 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004192 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4193
4194 //----------------------------------------------------------------------
4195 // Store instructions
4196 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004197 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004198 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004199 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004200 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4201 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004202
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004203
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004204 };
4205 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4206
4207 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4208 {
4209 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4210 return &g_arm_opcodes[i];
4211 }
4212 return NULL;
4213}
Greg Clayton64c84432011-01-21 22:02:52 +00004214
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004215
4216EmulateInstructionARM::ARMOpcode*
4217EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004218{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004219
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004220 static ARMOpcode
4221 g_thumb_opcodes[] =
4222 {
4223 //----------------------------------------------------------------------
4224 // Prologue instructions
4225 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004226
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004227 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004228 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004229 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
4230 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004231
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004232 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004233 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004234 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00004235 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004236 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
4237 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004238
Johnny Chenc9de9102011-02-11 19:12:30 +00004239 // PC-relative load into register (see also EmulateAddSPRm)
4240 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004241
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004242 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004243 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
4244 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004245 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
4246 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004247
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004248 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004249 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4250 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004251
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004252 //----------------------------------------------------------------------
4253 // Epilogue instructions
4254 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004255
Johnny Chenc28a76d2011-02-01 18:51:48 +00004256 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
4257 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004258 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
4259 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
4260 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4261 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004262
4263 //----------------------------------------------------------------------
4264 // Supervisor Call (previously Software Interrupt)
4265 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004266 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4267
4268 //----------------------------------------------------------------------
4269 // If Then makes up to four following instructions conditional.
4270 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004271 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4272
4273 //----------------------------------------------------------------------
4274 // Branch instructions
4275 //----------------------------------------------------------------------
4276 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4277 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4278 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004279 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004280 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004281 // J1 == J2 == 1
4282 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4283 // J1 == J2 == 1
4284 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4285 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004286 // for example, "bx lr"
4287 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004288 // compare and branch
4289 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004290
4291 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004292 // Data-processing instructions
4293 //----------------------------------------------------------------------
4294 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
4295 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004296 // move from high register to high register
4297 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
4298 // move from low register to low register
4299 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004300 // move immediate
4301 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
4302 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004303 // move bitwise not
4304 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004305 // compare a register with immediate
4306 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004307 // compare Rn with Rm (Rn and Rm both from r0-r7)
4308 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
4309 // compare Rn with Rm (Rn and Rm not both from r0-r7)
4310 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004311 // asr (immediate)
4312 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004313 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004314 // asr (register)
4315 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4316 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004317 // lsl (immediate)
4318 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4319 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4320 // lsl (register)
4321 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4322 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4323 // lsr (immediate)
4324 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4325 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4326 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004327 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004328 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004329 // rrx is a special case encoding of ror (immediate)
4330 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4331 // ror (immediate)
4332 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4333 // ror (register)
4334 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4335 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004336
4337 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004338 // Load instructions
4339 //----------------------------------------------------------------------
4340 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004341 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004342 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004343 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4344 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004345 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4346
4347 //----------------------------------------------------------------------
4348 // Store instructions
4349 //----------------------------------------------------------------------
4350 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004351 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004352 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4353 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4354 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4355 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004356 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4357 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004358 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4359 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4360 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4361 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004362 };
4363
4364 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4365 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4366 {
4367 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4368 return &g_thumb_opcodes[i];
4369 }
4370 return NULL;
4371}
Greg Clayton64c84432011-01-21 22:02:52 +00004372
Greg Clayton31e2a382011-01-30 20:03:56 +00004373bool
Greg Clayton395fc332011-02-15 21:59:32 +00004374EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004375{
4376 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004377 const char *arch_cstr = arch.AsCString ();
4378 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004379 {
Greg Clayton395fc332011-02-15 21:59:32 +00004380 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4381 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4382 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4383 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4384 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4385 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4386 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4387 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4388 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4389 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004390 }
4391 return m_arm_isa != 0;
4392}
4393
4394
Greg Clayton64c84432011-01-21 22:02:52 +00004395bool
4396EmulateInstructionARM::ReadInstruction ()
4397{
4398 bool success = false;
4399 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4400 if (success)
4401 {
4402 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4403 if (success)
4404 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004405 Context read_inst_context;
4406 read_inst_context.type = eContextReadOpcode;
4407 read_inst_context.SetNoArgs ();
4408
Greg Clayton64c84432011-01-21 22:02:52 +00004409 if (m_inst_cpsr & MASK_CPSR_T)
4410 {
4411 m_inst_mode = eModeThumb;
4412 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
4413
4414 if (success)
4415 {
4416 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4417 {
4418 m_inst.opcode_type = eOpcode16;
4419 m_inst.opcode.inst16 = thumb_opcode;
4420 }
4421 else
4422 {
4423 m_inst.opcode_type = eOpcode32;
4424 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
4425 }
4426 }
4427 }
4428 else
4429 {
4430 m_inst_mode = eModeARM;
4431 m_inst.opcode_type = eOpcode32;
4432 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
4433 }
4434 }
4435 }
4436 if (!success)
4437 {
4438 m_inst_mode = eModeInvalid;
4439 m_inst_pc = LLDB_INVALID_ADDRESS;
4440 }
4441 return success;
4442}
4443
Johnny Chenee9b1f72011-02-09 01:00:31 +00004444uint32_t
4445EmulateInstructionARM::ArchVersion ()
4446{
4447 return m_arm_isa;
4448}
4449
Greg Clayton64c84432011-01-21 22:02:52 +00004450bool
4451EmulateInstructionARM::ConditionPassed ()
4452{
4453 if (m_inst_cpsr == 0)
4454 return false;
4455
4456 const uint32_t cond = CurrentCond ();
4457
4458 if (cond == UINT32_MAX)
4459 return false;
4460
4461 bool result = false;
4462 switch (UnsignedBits(cond, 3, 1))
4463 {
4464 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4465 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4466 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4467 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4468 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4469 case 5:
4470 {
4471 bool n = (m_inst_cpsr & MASK_CPSR_N);
4472 bool v = (m_inst_cpsr & MASK_CPSR_V);
4473 result = n == v;
4474 }
4475 break;
4476 case 6:
4477 {
4478 bool n = (m_inst_cpsr & MASK_CPSR_N);
4479 bool v = (m_inst_cpsr & MASK_CPSR_V);
4480 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4481 }
4482 break;
4483 case 7:
4484 result = true;
4485 break;
4486 }
4487
4488 if (cond & 1)
4489 result = !result;
4490 return result;
4491}
4492
Johnny Chen9ee056b2011-02-08 00:06:35 +00004493uint32_t
4494EmulateInstructionARM::CurrentCond ()
4495{
4496 switch (m_inst_mode)
4497 {
4498 default:
4499 case eModeInvalid:
4500 break;
4501
4502 case eModeARM:
4503 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4504
4505 case eModeThumb:
4506 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4507 // 'cond' field of the encoding.
4508 if (m_inst.opcode_type == eOpcode16 &&
4509 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4510 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4511 {
4512 return Bits32(m_inst.opcode.inst16, 11, 7);
4513 }
4514 else if (m_inst.opcode_type == eOpcode32 &&
4515 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4516 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4517 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4518 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4519 {
4520 return Bits32(m_inst.opcode.inst32, 25, 22);
4521 }
4522
4523 return m_it_session.GetCond();
4524 }
4525 return UINT32_MAX; // Return invalid value
4526}
4527
Johnny Chen9ee056b2011-02-08 00:06:35 +00004528bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004529EmulateInstructionARM::InITBlock()
4530{
4531 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4532}
4533
4534bool
4535EmulateInstructionARM::LastInITBlock()
4536{
4537 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4538}
4539
4540bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004541EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4542{
4543 addr_t target;
4544
Johnny Chenee9b1f72011-02-09 01:00:31 +00004545 // Check the current instruction set.
4546 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004547 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004548 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004549 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004550
Johnny Chen9ee056b2011-02-08 00:06:35 +00004551 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004552 return false;
4553
4554 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004555}
4556
4557// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4558bool
Johnny Chen668b4512011-02-15 21:08:58 +00004559EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004560{
4561 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004562 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4563 // we want to record it and issue a WriteRegister callback so the clients
4564 // can track the mode changes accordingly.
4565 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004566
4567 if (BitIsSet(addr, 0))
4568 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004569 if (CurrentInstrSet() != eModeThumb)
4570 {
4571 SelectInstrSet(eModeThumb);
4572 cpsr_changed = true;
4573 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004574 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004575 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004576 }
4577 else if (BitIsClear(addr, 1))
4578 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004579 if (CurrentInstrSet() != eModeARM)
4580 {
4581 SelectInstrSet(eModeARM);
4582 cpsr_changed = true;
4583 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004584 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004585 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004586 }
4587 else
4588 return false; // address<1:0> == '10' => UNPREDICTABLE
4589
Johnny Chen0f309db2011-02-09 19:11:32 +00004590 if (cpsr_changed)
4591 {
Johnny Chen558133b2011-02-09 23:59:17 +00004592 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004593 return false;
4594 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004595 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004596 return false;
4597
4598 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004599}
Greg Clayton64c84432011-01-21 22:02:52 +00004600
Johnny Chenee9b1f72011-02-09 01:00:31 +00004601// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4602bool
Johnny Chen668b4512011-02-15 21:08:58 +00004603EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004604{
4605 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004606 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004607 else
4608 return BranchWritePC((const Context)context, addr);
4609}
4610
Johnny Chen26863dc2011-02-09 23:43:29 +00004611// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4612bool
Johnny Chen668b4512011-02-15 21:08:58 +00004613EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004614{
4615 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004616 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004617 else
4618 return BranchWritePC((const Context)context, addr);
4619}
4620
Johnny Chenee9b1f72011-02-09 01:00:31 +00004621EmulateInstructionARM::Mode
4622EmulateInstructionARM::CurrentInstrSet ()
4623{
4624 return m_inst_mode;
4625}
4626
4627// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004628// ReadInstruction() is performed. This function has a side effect of updating
4629// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004630bool
4631EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4632{
Johnny Chen558133b2011-02-09 23:59:17 +00004633 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004634 switch (arm_or_thumb)
4635 {
4636 default:
4637 return false;
4638 eModeARM:
4639 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004640 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004641 break;
4642 eModeThumb:
4643 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004644 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004645 break;
4646 }
4647 return true;
4648}
4649
Johnny Chenef21b592011-02-10 01:52:38 +00004650// This function returns TRUE if the processor currently provides support for
4651// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4652// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4653bool
4654EmulateInstructionARM::UnalignedSupport()
4655{
4656 return (ArchVersion() >= ARMv7);
4657}
4658
Johnny Chenbf6ad172011-02-11 01:29:53 +00004659// The main addition and subtraction instructions can produce status information
4660// about both unsigned carry and signed overflow conditions. This status
4661// information can be used to synthesize multi-word additions and subtractions.
4662EmulateInstructionARM::AddWithCarryResult
4663EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4664{
4665 uint32_t result;
4666 uint8_t carry_out;
4667 uint8_t overflow;
4668
4669 uint64_t unsigned_sum = x + y + carry_in;
4670 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4671
4672 result = UnsignedBits(unsigned_sum, 31, 0);
4673 carry_out = (result == unsigned_sum ? 0 : 1);
4674 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4675
4676 AddWithCarryResult res = { result, carry_out, overflow };
4677 return res;
4678}
4679
Johnny Chenca67d1c2011-02-17 01:35:27 +00004680// Write the result to the ARM core register Rd, and optionally update the
4681// condition flags based on the result.
4682//
4683// This helper method tries to encapsulate the following pseudocode from the
4684// ARM Architecture Reference Manual:
4685//
4686// if d == 15 then // Can only occur for encoding A1
4687// ALUWritePC(result); // setflags is always FALSE here
4688// else
4689// R[d] = result;
4690// if setflags then
4691// APSR.N = result<31>;
4692// APSR.Z = IsZeroBit(result);
4693// APSR.C = carry;
4694// // APSR.V unchanged
4695//
4696// In the above case, the API client does not pass in the overflow arg, which
4697// defaults to ~0u.
4698bool
4699EmulateInstructionARM::WriteCoreRegisterWithFlags (Context &context,
4700 const uint32_t result,
4701 const uint32_t Rd,
4702 bool setflags,
4703 const uint32_t carry,
4704 const uint32_t overflow)
4705{
4706 if (Rd == 15)
4707 {
4708 if (!ALUWritePC (context, result))
4709 return false;
4710 }
4711 else
4712 {
4713 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
4714 return false;
4715 if (setflags)
4716 {
4717 m_new_inst_cpsr = m_inst_cpsr;
4718 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
4719 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
4720 if (carry != ~0u)
4721 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
4722 if (overflow != ~0u)
4723 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
4724 if (m_new_inst_cpsr != m_inst_cpsr)
4725 {
4726 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
4727 return false;
4728 }
4729 }
4730 }
4731 return true;
4732}
4733
Greg Clayton64c84432011-01-21 22:02:52 +00004734bool
4735EmulateInstructionARM::EvaluateInstruction ()
4736{
Johnny Chenc315f862011-02-05 00:46:10 +00004737 // Advance the ITSTATE bits to their values for the next instruction.
4738 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4739 m_it_session.ITAdvance();
4740
Greg Clayton64c84432011-01-21 22:02:52 +00004741 return false;
4742}