blob: 9b1a16f121f646a9891b02bb190fe425452f5243 [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 Chen0e00af22011-02-10 19:40:42 +000026//----------------------------------------------------------------------
27//
28// ITSession implementation
29//
30//----------------------------------------------------------------------
31
Johnny Chen93070472011-02-04 23:02:47 +000032// A8.6.50
33// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
34static unsigned short CountITSize(unsigned ITMask) {
35 // First count the trailing zeros of the IT mask.
36 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
37 if (TZ > 3)
38 {
39 printf("Encoding error: IT Mask '0000'\n");
40 return 0;
41 }
42 return (4 - TZ);
43}
44
45// Init ITState. Note that at least one bit is always 1 in mask.
46bool ITSession::InitIT(unsigned short bits7_0)
47{
48 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
49 if (ITCounter == 0)
50 return false;
51
52 // A8.6.50 IT
53 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
54 if (FirstCond == 0xF)
55 {
56 printf("Encoding error: IT FirstCond '1111'\n");
57 return false;
58 }
59 if (FirstCond == 0xE && ITCounter != 1)
60 {
61 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
62 return false;
63 }
64
65 ITState = bits7_0;
66 return true;
67}
68
69// Update ITState if necessary.
70void ITSession::ITAdvance()
71{
72 assert(ITCounter);
73 --ITCounter;
74 if (ITCounter == 0)
75 ITState = 0;
76 else
77 {
78 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
79 SetBits32(ITState, 4, 0, NewITState4_0);
80 }
81}
82
83// Return true if we're inside an IT Block.
84bool ITSession::InITBlock()
85{
86 return ITCounter != 0;
87}
88
Johnny Chenc315f862011-02-05 00:46:10 +000089// Return true if we're the last instruction inside an IT Block.
90bool ITSession::LastInITBlock()
91{
92 return ITCounter == 1;
93}
94
Johnny Chen93070472011-02-04 23:02:47 +000095// Get condition bits for the current thumb instruction.
96uint32_t ITSession::GetCond()
97{
Johnny Chenc315f862011-02-05 00:46:10 +000098 if (InITBlock())
99 return Bits32(ITState, 7, 4);
100 else
101 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000102}
103
Greg Clayton64c84432011-01-21 22:02:52 +0000104// ARM constants used during decoding
105#define REG_RD 0
106#define LDM_REGLIST 1
107#define PC_REG 15
108#define PC_REGLIST_BIT 0x8000
109
Johnny Chen251af6a2011-01-21 22:47:25 +0000110#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000111#define ARMv4T (1u << 1)
112#define ARMv5T (1u << 2)
113#define ARMv5TE (1u << 3)
114#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000115#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000116#define ARMv6K (1u << 6)
117#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000119#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMvAll (0xffffffffu)
121
Johnny Chen9b8d7832011-02-02 01:13:56 +0000122#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
123#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
124#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000125
Johnny Chen0e00af22011-02-10 19:40:42 +0000126//----------------------------------------------------------------------
127//
128// EmulateInstructionARM implementation
129//
130//----------------------------------------------------------------------
131
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000132void
133EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000134{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000135}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000136
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000137void
138EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000139{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140}
141
Caroline Ticefa172202011-02-11 22:49:54 +0000142// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
143bool
144EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
145{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000146 EmulateInstruction::Context context;
147 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
148 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000149
150 uint32_t random_data = rand ();
151 const uint32_t addr_byte_size = GetAddressByteSize();
152
Caroline Ticecc96eb52011-02-17 19:20:40 +0000153 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000154 return false;
155
156 return true;
157}
158
Caroline Tice713c2662011-02-11 17:59:55 +0000159// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
160bool
161EmulateInstructionARM::WriteBits32Unknown (int n)
162{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000163 EmulateInstruction::Context context;
164 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
165 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000166
Johnny Chen62ff6f52011-02-11 18:11:22 +0000167 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000168 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
169
170 if (!success)
171 return false;
172
173 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
174 return false;
175
176 return true;
177}
178
Johnny Chen08c25e82011-01-31 18:02:28 +0000179// Push Multiple Registers stores multiple registers to the stack, storing to
180// consecutive memory locations ending just below the address in SP, and updates
181// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000182bool
183EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000184{
185#if 0
186 // ARM pseudo code...
187 if (ConditionPassed())
188 {
189 EncodingSpecificOperations();
190 NullCheckIfThumbEE(13);
191 address = SP - 4*BitCount(registers);
192
193 for (i = 0 to 14)
194 {
195 if (registers<i> == ’1’)
196 {
197 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
198 MemA[address,4] = bits(32) UNKNOWN;
199 else
200 MemA[address,4] = R[i];
201 address = address + 4;
202 }
203 }
204
205 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
206 MemA[address,4] = PCStoreValue();
207
208 SP = SP - 4*BitCount(registers);
209 }
210#endif
211
212 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000213 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000214 if (!success)
215 return false;
216
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000217 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000218 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000219 const uint32_t addr_byte_size = GetAddressByteSize();
220 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000221 if (!success)
222 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000223 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000224 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000225 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000226 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000227 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000228 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000229 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000230 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000231 // if BitCount(registers) < 1 then UNPREDICTABLE;
232 if (BitCount(registers) < 1)
233 return false;
234 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000235 case eEncodingT2:
236 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000237 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000238 // if BitCount(registers) < 2 then UNPREDICTABLE;
239 if (BitCount(registers) < 2)
240 return false;
241 break;
242 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000245 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000246 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000247 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000249 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000250 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000251 // Instead of return false, let's handle the following case as well,
252 // which amounts to pushing one reg onto the full descending stacks.
253 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000254 break;
255 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000257 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000258 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000259 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000260 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000261 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000262 default:
263 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000264 }
Johnny Chence1ca772011-01-25 01:13:00 +0000265 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000266 addr_t addr = sp - sp_offset;
267 uint32_t i;
268
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000269 EmulateInstruction::Context context;
270 context.type = EmulateInstruction::eContextPushRegisterOnStack;
271 Register dwarf_reg;
272 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000273 for (i=0; i<15; ++i)
274 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000275 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000276 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000277 dwarf_reg.num = dwarf_r0 + i;
278 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
279 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000280 if (!success)
281 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000282 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000283 return false;
284 addr += addr_byte_size;
285 }
286 }
287
Johnny Chen7c1bf922011-02-08 23:49:37 +0000288 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000289 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000290 dwarf_reg.num = dwarf_pc;
291 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000292 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000293 if (!success)
294 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000295 if (!MemAWrite (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000296 return false;
297 }
298
299 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000300 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000301
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000302 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000303 return false;
304 }
305 return true;
306}
307
Johnny Chenef85e912011-01-31 23:07:40 +0000308// Pop Multiple Registers loads multiple registers from the stack, loading from
309// consecutive memory locations staring at the address in SP, and updates
310// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000311bool
312EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000313{
314#if 0
315 // ARM pseudo code...
316 if (ConditionPassed())
317 {
318 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
319 address = SP;
320 for i = 0 to 14
321 if registers<i> == ‘1’ then
322 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
323 if registers<15> == ‘1’ then
324 if UnalignedAllowed then
325 LoadWritePC(MemU[address,4]);
326 else
327 LoadWritePC(MemA[address,4]);
328 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
329 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
330 }
331#endif
332
333 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000334 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000335 if (!success)
336 return false;
337
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000338 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000339 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000340 const uint32_t addr_byte_size = GetAddressByteSize();
341 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000342 if (!success)
343 return false;
344 uint32_t registers = 0;
345 uint32_t Rt; // the destination register
346 switch (encoding) {
347 case eEncodingT1:
348 registers = Bits32(opcode, 7, 0);
349 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000350 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000351 registers |= (1u << 15);
352 // if BitCount(registers) < 1 then UNPREDICTABLE;
353 if (BitCount(registers) < 1)
354 return false;
355 break;
356 case eEncodingT2:
357 // Ignore bit 13.
358 registers = Bits32(opcode, 15, 0) & ~0x2000;
359 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000360 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000361 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000362 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
363 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
364 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000365 break;
366 case eEncodingT3:
367 Rt = Bits32(opcode, 15, 12);
368 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000369 if (Rt == 13)
370 return false;
371 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000372 return false;
373 registers = (1u << Rt);
374 break;
375 case eEncodingA1:
376 registers = Bits32(opcode, 15, 0);
377 // Instead of return false, let's handle the following case as well,
378 // which amounts to popping one reg from the full descending stacks.
379 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
380
381 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000382 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000383 return false;
384 break;
385 case eEncodingA2:
386 Rt = Bits32(opcode, 15, 12);
387 // if t == 13 then UNPREDICTABLE;
388 if (Rt == dwarf_sp)
389 return false;
390 registers = (1u << Rt);
391 break;
392 default:
393 return false;
394 }
395 addr_t sp_offset = addr_byte_size * BitCount (registers);
396 addr_t addr = sp;
397 uint32_t i, data;
398
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000399 EmulateInstruction::Context context;
400 context.type = EmulateInstruction::eContextPopRegisterOffStack;
401 Register dwarf_reg;
402 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000403 for (i=0; i<15; ++i)
404 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000405 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000406 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000407 dwarf_reg.num = dwarf_r0 + i;
408 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000409 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000410 if (!success)
411 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000412 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000413 return false;
414 addr += addr_byte_size;
415 }
416 }
417
Johnny Chen7c1bf922011-02-08 23:49:37 +0000418 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000419 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 dwarf_reg.num = dwarf_pc;
421 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000422 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000423 if (!success)
424 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000425 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000426 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 return false;
428 addr += addr_byte_size;
429 }
430
431 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000432 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000433
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000434 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 }
437 return true;
438}
439
Johnny Chen5b442b72011-01-27 19:34:30 +0000440// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000441// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442bool
443EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000444{
445#if 0
446 // ARM pseudo code...
447 if (ConditionPassed())
448 {
449 EncodingSpecificOperations();
450 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
451 if d == 15 then
452 ALUWritePC(result); // setflags is always FALSE here
453 else
454 R[d] = result;
455 if setflags then
456 APSR.N = result<31>;
457 APSR.Z = IsZeroBit(result);
458 APSR.C = carry;
459 APSR.V = overflow;
460 }
461#endif
462
463 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000464 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000465 if (!success)
466 return false;
467
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000470 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000471 if (!success)
472 return false;
473 uint32_t Rd; // the destination register
474 uint32_t imm32;
475 switch (encoding) {
476 case eEncodingT1:
477 Rd = 7;
478 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
479 break;
480 case eEncodingA1:
481 Rd = Bits32(opcode, 15, 12);
482 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
483 break;
484 default:
485 return false;
486 }
487 addr_t sp_offset = imm32;
488 addr_t addr = sp + sp_offset; // a pointer to the stack area
489
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000490 EmulateInstruction::Context context;
491 context.type = EmulateInstruction::eContextRegisterPlusOffset;
492 Register sp_reg;
493 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
494 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000495
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000497 return false;
498 }
499 return true;
500}
501
Johnny Chen2ccad832011-01-28 19:57:25 +0000502// Set r7 or ip to the current stack pointer.
503// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504bool
505EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000506{
507#if 0
508 // ARM pseudo code...
509 if (ConditionPassed())
510 {
511 EncodingSpecificOperations();
512 result = R[m];
513 if d == 15 then
514 ALUWritePC(result); // setflags is always FALSE here
515 else
516 R[d] = result;
517 if setflags then
518 APSR.N = result<31>;
519 APSR.Z = IsZeroBit(result);
520 // APSR.C unchanged
521 // APSR.V unchanged
522 }
523#endif
524
525 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000526 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000527 //if (!success)
528 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000529
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000531 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000532 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000533 if (!success)
534 return false;
535 uint32_t Rd; // the destination register
536 switch (encoding) {
537 case eEncodingT1:
538 Rd = 7;
539 break;
540 case eEncodingA1:
541 Rd = 12;
542 break;
543 default:
544 return false;
545 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000546
547 EmulateInstruction::Context context;
548 context.type = EmulateInstruction::eContextRegisterPlusOffset;
549 Register sp_reg;
550 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
551 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000552
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000554 return false;
555 }
556 return true;
557}
558
Johnny Chen1c13b622011-01-29 00:11:15 +0000559// Move from high register (r8-r15) to low register (r0-r7).
560// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561bool
562EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000563{
Johnny Chen338bf542011-02-10 19:29:03 +0000564 return EmulateMovRdRm (encoding);
565}
566
567// Move from register to register.
568// MOV (register)
569bool
570EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
571{
Johnny Chen1c13b622011-01-29 00:11:15 +0000572#if 0
573 // ARM pseudo code...
574 if (ConditionPassed())
575 {
576 EncodingSpecificOperations();
577 result = R[m];
578 if d == 15 then
579 ALUWritePC(result); // setflags is always FALSE here
580 else
581 R[d] = result;
582 if setflags then
583 APSR.N = result<31>;
584 APSR.Z = IsZeroBit(result);
585 // APSR.C unchanged
586 // APSR.V unchanged
587 }
588#endif
589
590 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000591 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000592 if (!success)
593 return false;
594
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000595 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 {
597 uint32_t Rm; // the source register
598 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000599 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 switch (encoding) {
601 case eEncodingT1:
602 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000603 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000604 setflags = false;
605 break;
606 case eEncodingT2:
607 Rm = Bits32(opcode, 5, 3);
608 Rd = Bits32(opcode, 2, 1);
609 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000610 break;
611 default:
612 return false;
613 }
Johnny Chenca67d1c2011-02-17 01:35:27 +0000614 uint32_t result = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000615 if (!success)
616 return false;
617
618 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000619 EmulateInstruction::Context context;
620 context.type = EmulateInstruction::eContextRegisterPlusOffset;
621 Register dwarf_reg;
622 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
623 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000624
625 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags))
626 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000627 }
628 return true;
629}
630
Johnny Chen357c30f2011-02-14 22:04:25 +0000631// Move (immediate) writes an immediate value to the destination register. It
632// can optionally update the condition flags based on the value.
633// MOV (immediate)
634bool
635EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
636{
637#if 0
638 // ARM pseudo code...
639 if (ConditionPassed())
640 {
641 EncodingSpecificOperations();
642 result = imm32;
643 if d == 15 then // Can only occur for ARM encoding
644 ALUWritePC(result); // setflags is always FALSE here
645 else
646 R[d] = result;
647 if setflags then
648 APSR.N = result<31>;
649 APSR.Z = IsZeroBit(result);
650 APSR.C = carry;
651 // APSR.V unchanged
652 }
653#endif
654 bool success = false;
655 const uint32_t opcode = OpcodeAsUnsigned (&success);
656 if (!success)
657 return false;
658
659 if (ConditionPassed())
660 {
661 uint32_t Rd; // the destination register
662 uint32_t imm12; // some intermediate result
663 uint32_t imm32; // the immediate value to be written to Rd
664 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
665 bool setflags;
666 switch (encoding) {
667 case eEncodingT1:
668 Rd = Bits32(opcode, 11, 8);
669 setflags = !InITBlock();
670 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
671 carry = Bit32(m_inst_cpsr, CPSR_C);
672 break;
673 case eEncodingT2:
674 Rd = Bits32(opcode, 15, 12);
675 setflags = BitIsSet(opcode, 20);
676 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
677 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000678 if (BadReg(Rd))
679 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000680 break;
681 default:
682 return false;
683 }
684 uint32_t result = imm32;
685
686 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000687 EmulateInstruction::Context context;
688 context.type = EmulateInstruction::eContextImmediate;
689 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000690
691 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
692 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000693 }
694 return true;
695}
696
Johnny Chen28070c32011-02-12 01:27:26 +0000697// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
698// the destination register. It can optionally update the condition flags based
699// on the value.
700// MVN (immediate)
701bool
702EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
703{
704#if 0
705 // ARM pseudo code...
706 if (ConditionPassed())
707 {
708 EncodingSpecificOperations();
709 result = NOT(imm32);
710 if d == 15 then // Can only occur for ARM encoding
711 ALUWritePC(result); // setflags is always FALSE here
712 else
713 R[d] = result;
714 if setflags then
715 APSR.N = result<31>;
716 APSR.Z = IsZeroBit(result);
717 APSR.C = carry;
718 // APSR.V unchanged
719 }
720#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000721 bool success = false;
722 const uint32_t opcode = OpcodeAsUnsigned (&success);
723 if (!success)
724 return false;
725
726 if (ConditionPassed())
727 {
728 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000729 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
730 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
731 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000732 bool setflags;
733 switch (encoding) {
734 case eEncodingT1:
735 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000736 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000737 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000738 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
739 break;
740 case eEncodingA1:
741 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000742 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000743 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000744 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
745 break;
746 default:
747 return false;
748 }
749 uint32_t result = ~imm32;
750
751 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000752 EmulateInstruction::Context context;
753 context.type = EmulateInstruction::eContextImmediate;
754 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000755
756 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
757 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000758 }
759 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000760}
761
Johnny Chen788e0552011-01-27 22:52:23 +0000762// PC relative immediate load into register, possibly followed by ADD (SP plus register).
763// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000764bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000765EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000766{
767#if 0
768 // ARM pseudo code...
769 if (ConditionPassed())
770 {
771 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
772 base = Align(PC,4);
773 address = if add then (base + imm32) else (base - imm32);
774 data = MemU[address,4];
775 if t == 15 then
776 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
777 elsif UnalignedSupport() || address<1:0> = ‘00’ then
778 R[t] = data;
779 else // Can only apply before ARMv7
780 if CurrentInstrSet() == InstrSet_ARM then
781 R[t] = ROR(data, 8*UInt(address<1:0>));
782 else
783 R[t] = bits(32) UNKNOWN;
784 }
785#endif
786
787 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000788 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000789 if (!success)
790 return false;
791
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000792 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000793 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000794 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000795 if (!success)
796 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000797
798 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000799 EmulateInstruction::Context context;
800 context.type = EmulateInstruction::eContextRegisterPlusOffset;
801 Register pc_reg;
802 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
803 context.SetRegisterPlusOffset (pc_reg, 0);
804
Johnny Chenc9de9102011-02-11 19:12:30 +0000805 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000806 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000807 bool add; // +imm32 or -imm32?
808 addr_t base; // the base address
809 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000810 uint32_t data; // the literal data value from the PC relative load
811 switch (encoding) {
812 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000813 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000814 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000815 add = true;
816 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000817 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000818 break;
819 case eEncodingT2:
820 Rt = Bits32(opcode, 15, 12);
821 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
822 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000823 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000824 return false;
825 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000826 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000827 break;
828 default:
829 return false;
830 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000831
832 if (add)
833 address = base + imm32;
834 else
835 address = base - imm32;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000836 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000837 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000838 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000839
840 if (Rt == 15)
841 {
842 if (Bits32(address, 1, 0) == 0)
843 {
844 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000845 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000846 return false;
847 }
848 else
849 return false;
850 }
851 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
852 {
853 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
854 return false;
855 }
856 else // We don't handle ARM for now.
857 return false;
858
859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000860 return false;
861 }
862 return true;
863}
864
Johnny Chen5b442b72011-01-27 19:34:30 +0000865// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000866// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000867bool
868EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000869{
870#if 0
871 // ARM pseudo code...
872 if (ConditionPassed())
873 {
874 EncodingSpecificOperations();
875 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
876 if d == 15 then // Can only occur for ARM encoding
877 ALUWritePC(result); // setflags is always FALSE here
878 else
879 R[d] = result;
880 if setflags then
881 APSR.N = result<31>;
882 APSR.Z = IsZeroBit(result);
883 APSR.C = carry;
884 APSR.V = overflow;
885 }
886#endif
887
888 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000889 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000890 if (!success)
891 return false;
892
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000893 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000894 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000895 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000896 if (!success)
897 return false;
898 uint32_t imm32; // the immediate operand
899 switch (encoding) {
900 case eEncodingT2:
901 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
902 break;
903 default:
904 return false;
905 }
906 addr_t sp_offset = imm32;
907 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
908
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000909 EmulateInstruction::Context context;
910 context.type = EmulateInstruction::eContextAdjustStackPointer;
911 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000912
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000913 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000914 return false;
915 }
916 return true;
917}
918
919// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000920// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000921bool
922EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000923{
924#if 0
925 // ARM pseudo code...
926 if (ConditionPassed())
927 {
928 EncodingSpecificOperations();
929 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
930 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
931 if d == 15 then
932 ALUWritePC(result); // setflags is always FALSE here
933 else
934 R[d] = result;
935 if setflags then
936 APSR.N = result<31>;
937 APSR.Z = IsZeroBit(result);
938 APSR.C = carry;
939 APSR.V = overflow;
940 }
941#endif
942
943 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000944 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000945 if (!success)
946 return false;
947
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000948 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000949 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000950 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000951 if (!success)
952 return false;
953 uint32_t Rm; // the second operand
954 switch (encoding) {
955 case eEncodingT2:
956 Rm = Bits32(opcode, 6, 3);
957 break;
958 default:
959 return false;
960 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000961 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000962 if (!success)
963 return false;
964
965 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
966
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000967 EmulateInstruction::Context context;
968 context.type = EmulateInstruction::eContextAdjustStackPointer;
969 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000970
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000971 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000972 return false;
973 }
974 return true;
975}
976
Johnny Chen9b8d7832011-02-02 01:13:56 +0000977// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
978// at a PC-relative address, and changes instruction set from ARM to Thumb, or
979// from Thumb to ARM.
980// BLX (immediate)
981bool
982EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
983{
984#if 0
985 // ARM pseudo code...
986 if (ConditionPassed())
987 {
988 EncodingSpecificOperations();
989 if CurrentInstrSet() == InstrSet_ARM then
990 LR = PC - 4;
991 else
992 LR = PC<31:1> : '1';
993 if targetInstrSet == InstrSet_ARM then
994 targetAddress = Align(PC,4) + imm32;
995 else
996 targetAddress = PC + imm32;
997 SelectInstrSet(targetInstrSet);
998 BranchWritePC(targetAddress);
999 }
1000#endif
1001
1002 bool success = false;
1003 const uint32_t opcode = OpcodeAsUnsigned (&success);
1004 if (!success)
1005 return false;
1006
1007 if (ConditionPassed())
1008 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001009 EmulateInstruction::Context context;
1010 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001011 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001012 if (!success)
1013 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001014 addr_t lr; // next instruction address
1015 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001016 int32_t imm32; // PC-relative offset
1017 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001018 case eEncodingT1:
1019 {
1020 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001021 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001022 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001023 uint32_t J1 = Bit32(opcode, 13);
1024 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001025 uint32_t imm11 = Bits32(opcode, 10, 0);
1026 uint32_t I1 = !(J1 ^ S);
1027 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001028 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001029 imm32 = llvm::SignExtend32<25>(imm25);
1030 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001031 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001032 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001033 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001034 break;
1035 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001036 case eEncodingT2:
1037 {
1038 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001039 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001040 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001041 uint32_t J1 = Bit32(opcode, 13);
1042 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001043 uint32_t imm10L = Bits32(opcode, 10, 1);
1044 uint32_t I1 = !(J1 ^ S);
1045 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001046 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001047 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001048 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001049 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001050 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001051 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001052 break;
1053 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001054 case eEncodingA1:
1055 lr = pc + 4; // return address
1056 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001057 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001058 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001059 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001060 case eEncodingA2:
1061 lr = pc + 4; // return address
1062 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1063 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001064 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001065 break;
1066 default:
1067 return false;
1068 }
1069 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1070 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001071 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001072 return false;
1073 }
1074 return true;
1075}
1076
1077// Branch with Link and Exchange (register) calls a subroutine at an address and
1078// instruction set specified by a register.
1079// BLX (register)
1080bool
1081EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1082{
1083#if 0
1084 // ARM pseudo code...
1085 if (ConditionPassed())
1086 {
1087 EncodingSpecificOperations();
1088 target = R[m];
1089 if CurrentInstrSet() == InstrSet_ARM then
1090 next_instr_addr = PC - 4;
1091 LR = next_instr_addr;
1092 else
1093 next_instr_addr = PC - 2;
1094 LR = next_instr_addr<31:1> : ‘1’;
1095 BXWritePC(target);
1096 }
1097#endif
1098
1099 bool success = false;
1100 const uint32_t opcode = OpcodeAsUnsigned (&success);
1101 if (!success)
1102 return false;
1103
1104 if (ConditionPassed())
1105 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001106 EmulateInstruction::Context context;
1107 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001108 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1109 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001110 if (!success)
1111 return false;
1112 uint32_t Rm; // the register with the target address
1113 switch (encoding) {
1114 case eEncodingT1:
1115 lr = (pc + 2) | 1u; // return address
1116 Rm = Bits32(opcode, 6, 3);
1117 // if m == 15 then UNPREDICTABLE;
1118 if (Rm == 15)
1119 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001120 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001121 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001122 break;
1123 case eEncodingA1:
1124 lr = pc + 4; // return address
1125 Rm = Bits32(opcode, 3, 0);
1126 // if m == 15 then UNPREDICTABLE;
1127 if (Rm == 15)
1128 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001129 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001130 default:
1131 return false;
1132 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001133 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1134 if (!success)
1135 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001136 Register dwarf_reg;
1137 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1138 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001139 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1140 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001141 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001142 return false;
1143 }
1144 return true;
1145}
1146
Johnny Chenab3b3512011-02-12 00:10:51 +00001147// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1148// BX
1149bool
1150EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1151{
1152#if 0
1153 // ARM pseudo code...
1154 if (ConditionPassed())
1155 {
1156 EncodingSpecificOperations();
1157 BXWritePC(R[m]);
1158 }
1159#endif
1160
1161 bool success = false;
1162 const uint32_t opcode = OpcodeAsUnsigned (&success);
1163 if (!success)
1164 return false;
1165
1166 if (ConditionPassed())
1167 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001168 EmulateInstruction::Context context;
1169 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001170 uint32_t Rm; // the register with the target address
1171 switch (encoding) {
1172 case eEncodingT1:
1173 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001174 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001175 return false;
1176 break;
1177 case eEncodingA1:
1178 Rm = Bits32(opcode, 3, 0);
1179 break;
1180 default:
1181 return false;
1182 }
1183 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1184 if (!success)
1185 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001186
1187 Register dwarf_reg;
1188 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001189 context.SetRegister (dwarf_reg);
1190 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001191 return false;
1192 }
1193 return true;
1194}
1195
Johnny Chen0d0148e2011-01-28 02:26:08 +00001196// Set r7 to point to some ip offset.
1197// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001198bool
1199EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001200{
1201#if 0
1202 // ARM pseudo code...
1203 if (ConditionPassed())
1204 {
1205 EncodingSpecificOperations();
1206 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1207 if d == 15 then // Can only occur for ARM encoding
1208 ALUWritePC(result); // setflags is always FALSE here
1209 else
1210 R[d] = result;
1211 if setflags then
1212 APSR.N = result<31>;
1213 APSR.Z = IsZeroBit(result);
1214 APSR.C = carry;
1215 APSR.V = overflow;
1216 }
1217#endif
1218
1219 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001221 if (!success)
1222 return false;
1223
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001224 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001225 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001226 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001227 if (!success)
1228 return false;
1229 uint32_t imm32;
1230 switch (encoding) {
1231 case eEncodingA1:
1232 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1233 break;
1234 default:
1235 return false;
1236 }
1237 addr_t ip_offset = imm32;
1238 addr_t addr = ip - ip_offset; // the adjusted ip value
1239
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001240 EmulateInstruction::Context context;
1241 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1242 Register dwarf_reg;
1243 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1244 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001245
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001246 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001247 return false;
1248 }
1249 return true;
1250}
1251
1252// Set ip to point to some stack offset.
1253// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001254bool
1255EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001256{
1257#if 0
1258 // ARM pseudo code...
1259 if (ConditionPassed())
1260 {
1261 EncodingSpecificOperations();
1262 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1263 if d == 15 then // Can only occur for ARM encoding
1264 ALUWritePC(result); // setflags is always FALSE here
1265 else
1266 R[d] = result;
1267 if setflags then
1268 APSR.N = result<31>;
1269 APSR.Z = IsZeroBit(result);
1270 APSR.C = carry;
1271 APSR.V = overflow;
1272 }
1273#endif
1274
1275 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001276 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001277 if (!success)
1278 return false;
1279
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001280 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001281 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001282 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001283 if (!success)
1284 return false;
1285 uint32_t imm32;
1286 switch (encoding) {
1287 case eEncodingA1:
1288 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1289 break;
1290 default:
1291 return false;
1292 }
1293 addr_t sp_offset = imm32;
1294 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1295
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001296 EmulateInstruction::Context context;
1297 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1298 Register dwarf_reg;
1299 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1300 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001301
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001302 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001303 return false;
1304 }
1305 return true;
1306}
1307
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001308// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001309bool
1310EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001311{
1312#if 0
1313 // ARM pseudo code...
1314 if (ConditionPassed())
1315 {
1316 EncodingSpecificOperations();
1317 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1318 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001319 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001320 else
1321 R[d] = result;
1322 if setflags then
1323 APSR.N = result<31>;
1324 APSR.Z = IsZeroBit(result);
1325 APSR.C = carry;
1326 APSR.V = overflow;
1327 }
1328#endif
1329
1330 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001331 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001332 if (!success)
1333 return false;
1334
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001335 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001336 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001337 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001338 if (!success)
1339 return false;
1340 uint32_t imm32;
1341 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001342 case eEncodingT1:
1343 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001344 case eEncodingT2:
1345 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1346 break;
1347 case eEncodingT3:
1348 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1349 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001350 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001351 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001352 break;
1353 default:
1354 return false;
1355 }
1356 addr_t sp_offset = imm32;
1357 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1358
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001359 EmulateInstruction::Context context;
1360 context.type = EmulateInstruction::eContextAdjustStackPointer;
1361 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001362
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001363 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001364 return false;
1365 }
1366 return true;
1367}
1368
Johnny Chen08c25e82011-01-31 18:02:28 +00001369// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001370bool
1371EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001372{
1373#if 0
1374 // ARM pseudo code...
1375 if (ConditionPassed())
1376 {
1377 EncodingSpecificOperations();
1378 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1379 address = if index then offset_addr else R[n];
1380 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1381 if wback then R[n] = offset_addr;
1382 }
1383#endif
1384
1385 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001386 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001387 if (!success)
1388 return false;
1389
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001390 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001391 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001392 const uint32_t addr_byte_size = GetAddressByteSize();
1393 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001394 if (!success)
1395 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001396 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001397 uint32_t imm12;
1398 switch (encoding) {
1399 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001400 Rt = Bits32(opcode, 15, 12);
1401 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001402 break;
1403 default:
1404 return false;
1405 }
1406 addr_t sp_offset = imm12;
1407 addr_t addr = sp - sp_offset;
1408
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001409 EmulateInstruction::Context context;
1410 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1411 Register dwarf_reg;
1412 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001413 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001415 dwarf_reg.num = dwarf_r0 + Rt;
1416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1417 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001418 if (!success)
1419 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001420 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001421 return false;
1422 }
1423 else
1424 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001425 dwarf_reg.num = dwarf_pc;
1426 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001427 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001428 if (!success)
1429 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001430 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001431 return false;
1432 }
1433
1434 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001435 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001436
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001437 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001438 return false;
1439 }
1440 return true;
1441}
1442
Johnny Chen08c25e82011-01-31 18:02:28 +00001443// Vector Push stores multiple extension registers to the stack.
1444// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001445bool
1446EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001447{
1448#if 0
1449 // ARM pseudo code...
1450 if (ConditionPassed())
1451 {
1452 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1453 address = SP - imm32;
1454 SP = SP - imm32;
1455 if single_regs then
1456 for r = 0 to regs-1
1457 MemA[address,4] = S[d+r]; address = address+4;
1458 else
1459 for r = 0 to regs-1
1460 // Store as two word-aligned words in the correct order for current endianness.
1461 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1462 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1463 address = address+8;
1464 }
1465#endif
1466
1467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001469 if (!success)
1470 return false;
1471
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001472 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001474 const uint32_t addr_byte_size = GetAddressByteSize();
1475 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001476 if (!success)
1477 return false;
1478 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001479 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001480 uint32_t imm32; // stack offset
1481 uint32_t regs; // number of registers
1482 switch (encoding) {
1483 case eEncodingT1:
1484 case eEncodingA1:
1485 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001486 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001487 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1488 // If UInt(imm8) is odd, see "FSTMX".
1489 regs = Bits32(opcode, 7, 0) / 2;
1490 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1491 if (regs == 0 || regs > 16 || (d + regs) > 32)
1492 return false;
1493 break;
1494 case eEncodingT2:
1495 case eEncodingA2:
1496 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001497 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001498 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1499 regs = Bits32(opcode, 7, 0);
1500 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1501 if (regs == 0 || regs > 16 || (d + regs) > 32)
1502 return false;
1503 break;
1504 default:
1505 return false;
1506 }
1507 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1508 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1509 addr_t sp_offset = imm32;
1510 addr_t addr = sp - sp_offset;
1511 uint32_t i;
1512
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001513 EmulateInstruction::Context context;
1514 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1515 Register dwarf_reg;
1516 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001517 for (i=d; i<regs; ++i)
1518 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001519 dwarf_reg.num = start_reg + i;
1520 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001521 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001522 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001523 if (!success)
1524 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001525 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001526 return false;
1527 addr += reg_byte_size;
1528 }
1529
1530 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001531 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001532
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001533 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001534 return false;
1535 }
1536 return true;
1537}
1538
Johnny Chen587a0a42011-02-01 18:35:28 +00001539// Vector Pop loads multiple extension registers from the stack.
1540// It also updates SP to point just above the loaded data.
1541bool
1542EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1543{
1544#if 0
1545 // ARM pseudo code...
1546 if (ConditionPassed())
1547 {
1548 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1549 address = SP;
1550 SP = SP + imm32;
1551 if single_regs then
1552 for r = 0 to regs-1
1553 S[d+r] = MemA[address,4]; address = address+4;
1554 else
1555 for r = 0 to regs-1
1556 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1557 // Combine the word-aligned words in the correct order for current endianness.
1558 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1559 }
1560#endif
1561
1562 bool success = false;
1563 const uint32_t opcode = OpcodeAsUnsigned (&success);
1564 if (!success)
1565 return false;
1566
1567 if (ConditionPassed())
1568 {
1569 const uint32_t addr_byte_size = GetAddressByteSize();
1570 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1571 if (!success)
1572 return false;
1573 bool single_regs;
1574 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1575 uint32_t imm32; // stack offset
1576 uint32_t regs; // number of registers
1577 switch (encoding) {
1578 case eEncodingT1:
1579 case eEncodingA1:
1580 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001581 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001582 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1583 // If UInt(imm8) is odd, see "FLDMX".
1584 regs = Bits32(opcode, 7, 0) / 2;
1585 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1586 if (regs == 0 || regs > 16 || (d + regs) > 32)
1587 return false;
1588 break;
1589 case eEncodingT2:
1590 case eEncodingA2:
1591 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001592 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001593 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1594 regs = Bits32(opcode, 7, 0);
1595 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1596 if (regs == 0 || regs > 16 || (d + regs) > 32)
1597 return false;
1598 break;
1599 default:
1600 return false;
1601 }
1602 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1603 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1604 addr_t sp_offset = imm32;
1605 addr_t addr = sp;
1606 uint32_t i;
1607 uint64_t data; // uint64_t to accomodate 64-bit registers.
1608
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001609 EmulateInstruction::Context context;
1610 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1611 Register dwarf_reg;
1612 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001613 for (i=d; i<regs; ++i)
1614 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001615 dwarf_reg.num = start_reg + i;
1616 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001617 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001618 if (!success)
1619 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001620 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001621 return false;
1622 addr += reg_byte_size;
1623 }
1624
1625 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001626 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001627
1628 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1629 return false;
1630 }
1631 return true;
1632}
1633
Johnny Chenb77be412011-02-04 00:40:18 +00001634// SVC (previously SWI)
1635bool
1636EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1637{
1638#if 0
1639 // ARM pseudo code...
1640 if (ConditionPassed())
1641 {
1642 EncodingSpecificOperations();
1643 CallSupervisor();
1644 }
1645#endif
1646
1647 bool success = false;
1648 const uint32_t opcode = OpcodeAsUnsigned (&success);
1649 if (!success)
1650 return false;
1651
1652 if (ConditionPassed())
1653 {
1654 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1655 addr_t lr; // next instruction address
1656 if (!success)
1657 return false;
1658 uint32_t imm32; // the immediate constant
1659 uint32_t mode; // ARM or Thumb mode
1660 switch (encoding) {
1661 case eEncodingT1:
1662 lr = (pc + 2) | 1u; // return address
1663 imm32 = Bits32(opcode, 7, 0);
1664 mode = eModeThumb;
1665 break;
1666 case eEncodingA1:
1667 lr = pc + 4; // return address
1668 imm32 = Bits32(opcode, 23, 0);
1669 mode = eModeARM;
1670 break;
1671 default:
1672 return false;
1673 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001674
1675 EmulateInstruction::Context context;
1676 context.type = EmulateInstruction::eContextSupervisorCall;
1677 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001678 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1679 return false;
1680 }
1681 return true;
1682}
1683
Johnny Chenc315f862011-02-05 00:46:10 +00001684// If Then makes up to four following instructions (the IT block) conditional.
1685bool
1686EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1687{
1688#if 0
1689 // ARM pseudo code...
1690 EncodingSpecificOperations();
1691 ITSTATE.IT<7:0> = firstcond:mask;
1692#endif
1693
1694 bool success = false;
1695 const uint32_t opcode = OpcodeAsUnsigned (&success);
1696 if (!success)
1697 return false;
1698
1699 m_it_session.InitIT(Bits32(opcode, 7, 0));
1700 return true;
1701}
1702
Johnny Chen3b620b32011-02-07 20:11:47 +00001703// Branch causes a branch to a target address.
1704bool
1705EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1706{
1707#if 0
1708 // ARM pseudo code...
1709 if (ConditionPassed())
1710 {
1711 EncodingSpecificOperations();
1712 BranchWritePC(PC + imm32);
1713 }
1714#endif
1715
1716 bool success = false;
1717 const uint32_t opcode = OpcodeAsUnsigned (&success);
1718 if (!success)
1719 return false;
1720
Johnny Chen9ee056b2011-02-08 00:06:35 +00001721 if (ConditionPassed())
1722 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001723 EmulateInstruction::Context context;
1724 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001725 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001726 if (!success)
1727 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001728 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001729 int32_t imm32; // PC-relative offset
1730 switch (encoding) {
1731 case eEncodingT1:
1732 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1733 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1734 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001735 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001736 break;
1737 case eEncodingT2:
1738 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
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 eEncodingT3:
1743 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1744 {
Johnny Chenbd599902011-02-10 21:39:01 +00001745 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001746 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001747 uint32_t J1 = Bit32(opcode, 13);
1748 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001749 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001750 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001751 imm32 = llvm::SignExtend32<21>(imm21);
1752 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001753 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001754 break;
1755 }
1756 case eEncodingT4:
1757 {
Johnny Chenbd599902011-02-10 21:39:01 +00001758 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001759 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001760 uint32_t J1 = Bit32(opcode, 13);
1761 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001762 uint32_t imm11 = Bits32(opcode, 10, 0);
1763 uint32_t I1 = !(J1 ^ S);
1764 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001765 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001766 imm32 = llvm::SignExtend32<25>(imm25);
1767 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001768 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001769 break;
1770 }
1771 case eEncodingA1:
1772 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1773 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001774 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001775 break;
1776 default:
1777 return false;
1778 }
1779 if (!BranchWritePC(context, target))
1780 return false;
1781 }
1782 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001783}
1784
Johnny Chen53ebab72011-02-08 23:21:57 +00001785// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1786// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1787// CBNZ, CBZ
1788bool
1789EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1790{
1791#if 0
1792 // ARM pseudo code...
1793 EncodingSpecificOperations();
1794 if nonzero ^ IsZero(R[n]) then
1795 BranchWritePC(PC + imm32);
1796#endif
1797
1798 bool success = false;
1799 const uint32_t opcode = OpcodeAsUnsigned (&success);
1800 if (!success)
1801 return false;
1802
1803 // Read the register value from the operand register Rn.
1804 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1805 if (!success)
1806 return false;
1807
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001808 EmulateInstruction::Context context;
1809 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001810 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1811 if (!success)
1812 return false;
1813
1814 addr_t target; // target address
1815 uint32_t imm32; // PC-relative offset to branch forward
1816 bool nonzero;
1817 switch (encoding) {
1818 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001819 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001820 nonzero = BitIsSet(opcode, 11);
1821 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001822 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001823 break;
1824 default:
1825 return false;
1826 }
1827 if (nonzero ^ (reg_val == 0))
1828 if (!BranchWritePC(context, target))
1829 return false;
1830
1831 return true;
1832}
1833
Johnny Chen26863dc2011-02-09 23:43:29 +00001834// ADD <Rdn>, <Rm>
1835// where <Rdn> the destination register is also the first operand register
1836// and <Rm> is the second operand register.
1837bool
1838EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1839{
1840#if 0
1841 // ARM pseudo code...
1842 if ConditionPassed() then
1843 EncodingSpecificOperations();
1844 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1845 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1846 if d == 15 then
1847 ALUWritePC(result); // setflags is always FALSE here
1848 else
1849 R[d] = result;
1850 if setflags then
1851 APSR.N = result<31>;
1852 APSR.Z = IsZeroBit(result);
1853 APSR.C = carry;
1854 APSR.V = overflow;
1855#endif
1856
1857 bool success = false;
1858 const uint32_t opcode = OpcodeAsUnsigned (&success);
1859 if (!success)
1860 return false;
1861
1862 if (ConditionPassed())
1863 {
1864 uint32_t Rd, Rn, Rm;
Johnny Chenca67d1c2011-02-17 01:35:27 +00001865 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00001866 switch (encoding)
1867 {
1868 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00001869 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001870 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00001871 setflags = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001872 if (Rn == 15 && Rm == 15)
1873 return false;
1874 break;
1875 default:
1876 return false;
1877 }
1878
1879 int32_t result, val1, val2;
1880 // Read the first operand.
1881 if (Rn == 15)
1882 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1883 else
1884 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1885 if (!success)
1886 return false;
1887
1888 // Read the second operand.
1889 if (Rm == 15)
1890 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1891 else
1892 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1893 if (!success)
1894 return false;
1895
Johnny Chenca67d1c2011-02-17 01:35:27 +00001896 // TODO: Handle the case where Rm needs to be shifted properly.
1897 AddWithCarryResult res = AddWithCarry(val1, val2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001898 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001899
1900 EmulateInstruction::Context context;
1901 context.type = EmulateInstruction::eContextImmediate;
1902 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001903
1904 if (!WriteCoreRegisterWithFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1905 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001906 }
1907 return true;
1908}
1909
Johnny Chene4a4d302011-02-11 21:53:58 +00001910// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001911bool
1912EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1913{
1914#if 0
1915 // ARM pseudo code...
1916 if ConditionPassed() then
1917 EncodingSpecificOperations();
1918 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1919 APSR.N = result<31>;
1920 APSR.Z = IsZeroBit(result);
1921 APSR.C = carry;
1922 APSR.V = overflow;
1923#endif
1924
1925 bool success = false;
1926 const uint32_t opcode = OpcodeAsUnsigned (&success);
1927 if (!success)
1928 return false;
1929
1930 uint32_t Rn; // the first operand
1931 uint32_t imm32; // the immediate value to be compared with
1932 switch (encoding) {
1933 case eEncodingT1:
1934 Rn = Bits32(opcode, 10, 8);
1935 imm32 = Bits32(opcode, 7, 0);
1936 break;
1937 default:
1938 return false;
1939 }
1940 // Read the register value from the operand register Rn.
1941 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1942 if (!success)
1943 return false;
1944
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001945 EmulateInstruction::Context context;
1946 context.type = EmulateInstruction::eContextImmediate;
1947 context.SetNoArgs ();
1948
Johnny Chend4dc4442011-02-11 02:02:56 +00001949 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1950 m_new_inst_cpsr = m_inst_cpsr;
1951 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1952 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1953 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1954 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1955 if (m_new_inst_cpsr != m_inst_cpsr)
1956 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001957 EmulateInstruction::Context context;
1958 context.type = EmulateInstruction::eContextImmediate;
1959 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00001960 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1961 return false;
1962 }
1963 return true;
1964}
1965
Johnny Chene4a4d302011-02-11 21:53:58 +00001966// CMP (register)
1967bool
1968EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1969{
1970#if 0
1971 // ARM pseudo code...
1972 if ConditionPassed() then
1973 EncodingSpecificOperations();
1974 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1975 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1976 APSR.N = result<31>;
1977 APSR.Z = IsZeroBit(result);
1978 APSR.C = carry;
1979 APSR.V = overflow;
1980#endif
1981
1982 bool success = false;
1983 const uint32_t opcode = OpcodeAsUnsigned (&success);
1984 if (!success)
1985 return false;
1986
1987 uint32_t Rn; // the first operand
1988 uint32_t Rm; // the second operand
1989 switch (encoding) {
1990 case eEncodingT1:
1991 Rn = Bits32(opcode, 2, 0);
1992 Rm = Bits32(opcode, 5, 3);
1993 break;
1994 case eEncodingT2:
1995 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1996 Rm = Bits32(opcode, 6, 3);
1997 if (Rn < 8 && Rm < 8)
1998 return false;
1999 if (Rn == 15 || Rm == 15)
2000 return false;
2001 break;
2002 default:
2003 return false;
2004 }
2005 // Read the register value from register Rn.
2006 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2007 if (!success)
2008 return false;
2009 // Read the register value from register Rm.
2010 // The register value is not being shifted since we don't handle ARM for now.
2011 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2012 if (!success)
2013 return false;
2014
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002015 EmulateInstruction::Context context;
2016 context.type = EmulateInstruction::eContextImmediate;
2017 context.SetNoArgs();
2018
Johnny Chene4a4d302011-02-11 21:53:58 +00002019 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2020 m_new_inst_cpsr = m_inst_cpsr;
2021 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2022 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2023 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2024 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2025 if (m_new_inst_cpsr != m_inst_cpsr)
2026 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002027 EmulateInstruction::Context context;
2028 context.type = EmulateInstruction::eContextImmediate;
2029 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002030 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2031 return false;
2032 }
2033 return true;
2034}
2035
Johnny Chen82f16aa2011-02-15 20:10:55 +00002036// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2037// shifting in copies of its sign bit, and writes the result to the destination register. It can
2038// optionally update the condition flags based on the result.
2039bool
2040EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2041{
2042#if 0
2043 // ARM pseudo code...
2044 if ConditionPassed() then
2045 EncodingSpecificOperations();
2046 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2047 if d == 15 then // Can only occur for ARM encoding
2048 ALUWritePC(result); // setflags is always FALSE here
2049 else
2050 R[d] = result;
2051 if setflags then
2052 APSR.N = result<31>;
2053 APSR.Z = IsZeroBit(result);
2054 APSR.C = carry;
2055 // APSR.V unchanged
2056#endif
2057
Johnny Chen41a0a152011-02-16 01:27:54 +00002058 return EmulateShiftImm(encoding, SRType_ASR);
2059}
2060
2061// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2062// shifting in copies of its sign bit, and writes the result to the destination register.
2063// The variable number of bits is read from the bottom byte of a register. It can optionally update
2064// the condition flags based on the result.
2065bool
2066EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2067{
2068#if 0
2069 // ARM pseudo code...
2070 if ConditionPassed() then
2071 EncodingSpecificOperations();
2072 shift_n = UInt(R[m]<7:0>);
2073 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2074 R[d] = result;
2075 if setflags then
2076 APSR.N = result<31>;
2077 APSR.Z = IsZeroBit(result);
2078 APSR.C = carry;
2079 // APSR.V unchanged
2080#endif
2081
2082 return EmulateShiftReg(encoding, SRType_ASR);
2083}
2084
2085// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2086// shifting in zeros, and writes the result to the destination register. It can optionally
2087// update the condition flags based on the result.
2088bool
2089EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2090{
2091#if 0
2092 // ARM pseudo code...
2093 if ConditionPassed() then
2094 EncodingSpecificOperations();
2095 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2096 if d == 15 then // Can only occur for ARM encoding
2097 ALUWritePC(result); // setflags is always FALSE here
2098 else
2099 R[d] = result;
2100 if setflags then
2101 APSR.N = result<31>;
2102 APSR.Z = IsZeroBit(result);
2103 APSR.C = carry;
2104 // APSR.V unchanged
2105#endif
2106
2107 return EmulateShiftImm(encoding, SRType_LSL);
2108}
2109
2110// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2111// shifting in zeros, and writes the result to the destination register. The variable number
2112// of bits is read from the bottom byte of a register. It can optionally update the condition
2113// flags based on the result.
2114bool
2115EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2116{
2117#if 0
2118 // ARM pseudo code...
2119 if ConditionPassed() then
2120 EncodingSpecificOperations();
2121 shift_n = UInt(R[m]<7:0>);
2122 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2123 R[d] = result;
2124 if setflags then
2125 APSR.N = result<31>;
2126 APSR.Z = IsZeroBit(result);
2127 APSR.C = carry;
2128 // APSR.V unchanged
2129#endif
2130
2131 return EmulateShiftReg(encoding, SRType_LSL);
2132}
2133
2134// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2135// shifting in zeros, and writes the result to the destination register. It can optionally
2136// update the condition flags based on the result.
2137bool
2138EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2139{
2140#if 0
2141 // ARM pseudo code...
2142 if ConditionPassed() then
2143 EncodingSpecificOperations();
2144 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2145 if d == 15 then // Can only occur for ARM encoding
2146 ALUWritePC(result); // setflags is always FALSE here
2147 else
2148 R[d] = result;
2149 if setflags then
2150 APSR.N = result<31>;
2151 APSR.Z = IsZeroBit(result);
2152 APSR.C = carry;
2153 // APSR.V unchanged
2154#endif
2155
2156 return EmulateShiftImm(encoding, SRType_LSR);
2157}
2158
2159// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2160// shifting in zeros, and writes the result to the destination register. The variable number
2161// of bits is read from the bottom byte of a register. It can optionally update the condition
2162// flags based on the result.
2163bool
2164EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2165{
2166#if 0
2167 // ARM pseudo code...
2168 if ConditionPassed() then
2169 EncodingSpecificOperations();
2170 shift_n = UInt(R[m]<7:0>);
2171 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2172 R[d] = result;
2173 if setflags then
2174 APSR.N = result<31>;
2175 APSR.Z = IsZeroBit(result);
2176 APSR.C = carry;
2177 // APSR.V unchanged
2178#endif
2179
2180 return EmulateShiftReg(encoding, SRType_LSR);
2181}
2182
Johnny Cheneeab4852011-02-16 22:14:44 +00002183// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2184// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2185// It can optionally update the condition flags based on the result.
2186bool
2187EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2188{
2189#if 0
2190 // ARM pseudo code...
2191 if ConditionPassed() then
2192 EncodingSpecificOperations();
2193 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2194 if d == 15 then // Can only occur for ARM encoding
2195 ALUWritePC(result); // setflags is always FALSE here
2196 else
2197 R[d] = result;
2198 if setflags then
2199 APSR.N = result<31>;
2200 APSR.Z = IsZeroBit(result);
2201 APSR.C = carry;
2202 // APSR.V unchanged
2203#endif
2204
2205 return EmulateShiftImm(encoding, SRType_ROR);
2206}
2207
2208// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2209// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2210// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2211// flags based on the result.
2212bool
2213EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2214{
2215#if 0
2216 // ARM pseudo code...
2217 if ConditionPassed() then
2218 EncodingSpecificOperations();
2219 shift_n = UInt(R[m]<7:0>);
2220 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2221 R[d] = result;
2222 if setflags then
2223 APSR.N = result<31>;
2224 APSR.Z = IsZeroBit(result);
2225 APSR.C = carry;
2226 // APSR.V unchanged
2227#endif
2228
2229 return EmulateShiftReg(encoding, SRType_ROR);
2230}
2231
2232// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2233// with the carry flag shifted into bit [31].
2234//
2235// RRX can optionally update the condition flags based on the result.
2236// In that case, bit [0] is shifted into the carry flag.
2237bool
2238EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2239{
2240#if 0
2241 // ARM pseudo code...
2242 if ConditionPassed() then
2243 EncodingSpecificOperations();
2244 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2245 if d == 15 then // Can only occur for ARM encoding
2246 ALUWritePC(result); // setflags is always FALSE here
2247 else
2248 R[d] = result;
2249 if setflags then
2250 APSR.N = result<31>;
2251 APSR.Z = IsZeroBit(result);
2252 APSR.C = carry;
2253 // APSR.V unchanged
2254#endif
2255
2256 return EmulateShiftImm(encoding, SRType_RRX);
2257}
2258
Johnny Chen41a0a152011-02-16 01:27:54 +00002259bool
2260EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2261{
2262 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2263
Johnny Chen82f16aa2011-02-15 20:10:55 +00002264 bool success = false;
2265 const uint32_t opcode = OpcodeAsUnsigned (&success);
2266 if (!success)
2267 return false;
2268
2269 if (ConditionPassed())
2270 {
Johnny Chene7f89532011-02-15 23:22:46 +00002271 uint32_t Rd; // the destination register
2272 uint32_t Rm; // the first operand register
2273 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002274 uint32_t carry; // the carry bit after the shift operation
2275 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002276
2277 // Special case handling!
2278 // A8.6.139 ROR (immediate) -- Encoding T1
2279 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2280 {
2281 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2282 // have the same decoding of bit fields as the other Thumb2 shift operations.
2283 encoding = eEncodingT2;
2284 }
2285
Johnny Chen82f16aa2011-02-15 20:10:55 +00002286 switch (encoding) {
2287 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002288 // Due to the above special case handling!
2289 assert(shift_type != SRType_ROR);
2290
Johnny Chen82f16aa2011-02-15 20:10:55 +00002291 Rd = Bits32(opcode, 2, 0);
2292 Rm = Bits32(opcode, 5, 3);
2293 setflags = !InITBlock();
2294 imm5 = Bits32(opcode, 10, 6);
2295 break;
2296 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002297 // A8.6.141 RRX
2298 assert(shift_type != SRType_RRX);
2299
Johnny Chen82f16aa2011-02-15 20:10:55 +00002300 Rd = Bits32(opcode, 11, 8);
2301 Rm = Bits32(opcode, 3, 0);
2302 setflags = BitIsSet(opcode, 20);
2303 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2304 if (BadReg(Rd) || BadReg(Rm))
2305 return false;
2306 break;
2307 case eEncodingA1:
2308 Rd = Bits32(opcode, 15, 12);
2309 Rm = Bits32(opcode, 3, 0);
2310 setflags = BitIsSet(opcode, 20);
2311 imm5 = Bits32(opcode, 11, 7);
2312 break;
2313 default:
2314 return false;
2315 }
2316
Johnny Cheneeab4852011-02-16 22:14:44 +00002317 // A8.6.139 ROR (immediate)
2318 if (shift_type == SRType_ROR && imm5 == 0)
2319 shift_type = SRType_RRX;
2320
Johnny Chen82f16aa2011-02-15 20:10:55 +00002321 // Get the first operand.
2322 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2323 if (!success)
2324 return false;
2325
Johnny Cheneeab4852011-02-16 22:14:44 +00002326 // Decode the shift amount if not RRX.
2327 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002328
Johnny Chen41a0a152011-02-16 01:27:54 +00002329 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002330
2331 // The context specifies that an immediate is to be moved into Rd.
2332 EmulateInstruction::Context context;
2333 context.type = EmulateInstruction::eContextImmediate;
2334 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002335
Johnny Chenca67d1c2011-02-17 01:35:27 +00002336 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
2337 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002338 }
2339 return true;
2340}
2341
Johnny Chene7f89532011-02-15 23:22:46 +00002342bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002343EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002344{
Johnny Chen41a0a152011-02-16 01:27:54 +00002345 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002346
2347 bool success = false;
2348 const uint32_t opcode = OpcodeAsUnsigned (&success);
2349 if (!success)
2350 return false;
2351
2352 if (ConditionPassed())
2353 {
2354 uint32_t Rd; // the destination register
2355 uint32_t Rn; // the first operand register
2356 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2357 uint32_t carry; // the carry bit after the shift operation
2358 bool setflags;
2359 switch (encoding) {
2360 case eEncodingT1:
2361 Rd = Bits32(opcode, 2, 0);
2362 Rn = Rd;
2363 Rm = Bits32(opcode, 5, 3);
2364 setflags = !InITBlock();
2365 break;
2366 case eEncodingT2:
2367 Rd = Bits32(opcode, 11, 8);
2368 Rn = Bits32(opcode, 19, 16);
2369 Rm = Bits32(opcode, 3, 0);
2370 setflags = BitIsSet(opcode, 20);
2371 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2372 return false;
2373 break;
2374 case eEncodingA1:
2375 Rd = Bits32(opcode, 15, 12);
2376 Rn = Bits32(opcode, 3, 0);
2377 Rm = Bits32(opcode, 11, 8);
2378 setflags = BitIsSet(opcode, 20);
2379 if (Rd == 15 || Rn == 15 || Rm == 15)
2380 return false;
2381 break;
2382 default:
2383 return false;
2384 }
2385
2386 // Get the first operand.
2387 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2388 if (!success)
2389 return false;
2390 // Get the Rm register content.
2391 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2392 if (!success)
2393 return false;
2394
2395 // Get the shift amount.
2396 uint32_t amt = Bits32(val, 7, 0);
2397
Johnny Chen41a0a152011-02-16 01:27:54 +00002398 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002399
2400 // The context specifies that an immediate is to be moved into Rd.
2401 EmulateInstruction::Context context;
2402 context.type = EmulateInstruction::eContextImmediate;
2403 context.SetNoArgs ();
2404
Johnny Chenca67d1c2011-02-17 01:35:27 +00002405 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002406 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002407 }
2408 return true;
2409}
2410
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002411// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002412// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002413// can be written back to the base register.
2414bool
2415EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2416{
2417#if 0
2418 // ARM pseudo code...
2419 if ConditionPassed()
2420 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2421 address = R[n];
2422
2423 for i = 0 to 14
2424 if registers<i> == '1' then
2425 R[i] = MemA[address, 4]; address = address + 4;
2426 if registers<15> == '1' then
2427 LoadWritePC (MemA[address, 4]);
2428
2429 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2430 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2431
2432#endif
2433
2434 bool success = false;
2435 const uint32_t opcode = OpcodeAsUnsigned (&success);
2436 if (!success)
2437 return false;
2438
2439 if (ConditionPassed())
2440 {
2441 uint32_t n;
2442 uint32_t registers = 0;
2443 bool wback;
2444 const uint32_t addr_byte_size = GetAddressByteSize();
2445 switch (encoding)
2446 {
2447 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002448 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002449 n = Bits32 (opcode, 10, 8);
2450 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002451 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002452 wback = BitIsClear (registers, n);
2453 // if BitCount(registers) < 1 then UNPREDICTABLE;
2454 if (BitCount(registers) < 1)
2455 return false;
2456 break;
2457 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002458 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2459 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002460 n = Bits32 (opcode, 19, 16);
2461 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002462 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002463 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002464
2465 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002466 if ((n == 15)
2467 || (BitCount (registers) < 2)
2468 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2469 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002470
2471 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002472 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002473 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002474
2475 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002476 if (wback
2477 && BitIsSet (registers, n))
2478 return false;
2479 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002480
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002481 case eEncodingA1:
2482 n = Bits32 (opcode, 19, 16);
2483 registers = Bits32 (opcode, 15, 0);
2484 wback = BitIsSet (opcode, 21);
2485 if ((n == 15)
2486 || (BitCount (registers) < 1))
2487 return false;
2488 break;
2489 default:
2490 return false;
2491 }
2492
2493 int32_t offset = 0;
2494 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2495 if (!success)
2496 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002497
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002498 EmulateInstruction::Context context;
2499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2500 Register dwarf_reg;
2501 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2502 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002503
2504 for (int i = 0; i < 14; ++i)
2505 {
2506 if (BitIsSet (registers, i))
2507 {
Caroline Tice85aab332011-02-08 23:56:10 +00002508 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002509 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002510 if (wback && (n == 13)) // Pop Instruction
2511 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2512
2513 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002514 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002515 if (!success)
2516 return false;
2517
2518 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2519 return false;
2520
2521 offset += addr_byte_size;
2522 }
2523 }
2524
2525 if (BitIsSet (registers, 15))
2526 {
2527 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002528 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002529 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002530 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002531 if (!success)
2532 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002533 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002534 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002535 return false;
2536 }
2537
2538 if (wback && BitIsClear (registers, n))
2539 {
Caroline Ticefa172202011-02-11 22:49:54 +00002540 // R[n] = R[n] + 4 * BitCount (registers)
2541 int32_t offset = addr_byte_size * BitCount (registers);
2542 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002543 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002544
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002545 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2546 return false;
2547 }
2548 if (wback && BitIsSet (registers, n))
2549 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002550 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002551 }
2552 return true;
2553}
Caroline Tice713c2662011-02-11 17:59:55 +00002554
2555// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2556// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2557// can optionally be written back tot he base registers.
2558bool
2559EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2560{
2561#if 0
2562 // ARM pseudo code...
2563 if ConditionPassed() then
2564 EncodingSpecificOperations();
2565 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002566
Caroline Tice713c2662011-02-11 17:59:55 +00002567 for i = 0 to 14
2568 if registers<i> == ’1’ then
2569 R[i] = MemA[address,4]; address = address + 4;
2570
2571 if registers<15> == ’1’ then
2572 LoadWritePC(MemA[address,4]);
2573
2574 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2575 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2576#endif
2577
2578 bool success = false;
2579 const uint32_t opcode = OpcodeAsUnsigned (&success);
2580 if (!success)
2581 return false;
2582
2583 if (ConditionPassed())
2584 {
2585 uint32_t n;
2586 uint32_t registers = 0;
2587 bool wback;
2588 const uint32_t addr_byte_size = GetAddressByteSize();
2589
2590 // EncodingSpecificOperations();
2591 switch (encoding)
2592 {
2593 case eEncodingA1:
2594 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2595 n = Bits32 (opcode, 19, 16);
2596 registers = Bits32 (opcode, 15, 0);
2597 wback = BitIsSet (opcode, 21);
2598
2599 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2600 if ((n == 15) || (BitCount (registers) < 1))
2601 return false;
2602
2603 break;
2604
2605 default:
2606 return false;
2607 }
2608 // address = R[n] - 4*BitCount(registers) + 4;
2609
2610 int32_t offset = 0;
2611 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2612
2613 if (!success)
2614 return false;
2615
2616 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2617
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002618 EmulateInstruction::Context context;
2619 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2620 Register dwarf_reg;
2621 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2622 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002623
2624 // for i = 0 to 14
2625 for (int i = 0; i < 14; ++i)
2626 {
2627 // if registers<i> == ’1’ then
2628 if (BitIsSet (registers, i))
2629 {
2630 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002631 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002632 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002633 if (!success)
2634 return false;
2635 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2636 return false;
2637 offset += addr_byte_size;
2638 }
2639 }
2640
2641 // if registers<15> == ’1’ then
2642 // LoadWritePC(MemA[address,4]);
2643 if (BitIsSet (registers, 15))
2644 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002645 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002646 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002647 if (!success)
2648 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002649 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002650 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002651 return false;
2652 }
2653
2654 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2655 if (wback && BitIsClear (registers, n))
2656 {
Caroline Tice713c2662011-02-11 17:59:55 +00002657 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2658 if (!success)
2659 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002660
2661 offset = (addr_byte_size * BitCount (registers)) * -1;
2662 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002663 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002664 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002665 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2666 return false;
2667 }
2668
2669 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2670 if (wback && BitIsSet (registers, n))
2671 return WriteBits32Unknown (n);
2672 }
2673 return true;
2674}
2675
2676// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2677// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2678// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002679bool
2680EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2681{
2682#if 0
2683 // ARM pseudo code...
2684 if ConditionPassed() then
2685 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2686 address = R[n] - 4*BitCount(registers);
2687
2688 for i = 0 to 14
2689 if registers<i> == ’1’ then
2690 R[i] = MemA[address,4]; address = address + 4;
2691 if registers<15> == ’1’ then
2692 LoadWritePC(MemA[address,4]);
2693
2694 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2695 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2696#endif
2697
2698 bool success = false;
2699 const uint32_t opcode = OpcodeAsUnsigned (&success);
2700 if (!success)
2701 return false;
2702
2703 if (ConditionPassed())
2704 {
2705 uint32_t n;
2706 uint32_t registers = 0;
2707 bool wback;
2708 const uint32_t addr_byte_size = GetAddressByteSize();
2709 switch (encoding)
2710 {
2711 case eEncodingT1:
2712 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2713 n = Bits32 (opcode, 19, 16);
2714 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002715 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002716 wback = BitIsSet (opcode, 21);
2717
2718 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2719 if ((n == 15)
2720 || (BitCount (registers) < 2)
2721 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2722 return false;
2723
2724 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002725 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002726 return false;
2727
2728 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2729 if (wback && BitIsSet (registers, n))
2730 return false;
2731
2732 break;
2733
2734 case eEncodingA1:
2735 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2736 n = Bits32 (opcode, 19, 16);
2737 registers = Bits32 (opcode, 15, 0);
2738 wback = BitIsSet (opcode, 21);
2739
2740 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2741 if ((n == 15) || (BitCount (registers) < 1))
2742 return false;
2743
2744 break;
2745
2746 default:
2747 return false;
2748 }
2749
Caroline Tice713c2662011-02-11 17:59:55 +00002750 // address = R[n] - 4*BitCount(registers);
2751
Caroline Tice0b29e242011-02-08 23:16:02 +00002752 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002753 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2754
2755 if (!success)
2756 return false;
2757
2758 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002759 EmulateInstruction::Context context;
2760 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2761 Register dwarf_reg;
2762 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2763 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002764
2765 for (int i = 0; i < 14; ++i)
2766 {
2767 if (BitIsSet (registers, i))
2768 {
2769 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002770 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002771 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002772 if (!success)
2773 return false;
2774
2775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2776 return false;
2777
2778 offset += addr_byte_size;
2779 }
2780 }
2781
2782 // if registers<15> == ’1’ then
2783 // LoadWritePC(MemA[address,4]);
2784 if (BitIsSet (registers, 15))
2785 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002786 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002787 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002788 if (!success)
2789 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002790 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002791 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002792 return false;
2793 }
2794
2795 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2796 if (wback && BitIsClear (registers, n))
2797 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002798 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2799 if (!success)
2800 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002801
2802 offset = (addr_byte_size * BitCount (registers)) * -1;
2803 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002804 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002805 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2807 return false;
2808 }
2809
2810 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2811 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002812 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002813 }
2814 return true;
2815}
Caroline Tice85aab332011-02-08 23:56:10 +00002816
Caroline Tice713c2662011-02-11 17:59:55 +00002817// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2818// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2819// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002820bool
2821EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2822{
2823#if 0
2824 if ConditionPassed() then
2825 EncodingSpecificOperations();
2826 address = R[n] + 4;
2827
2828 for i = 0 to 14
2829 if registers<i> == ’1’ then
2830 R[i] = MemA[address,4]; address = address + 4;
2831 if registers<15> == ’1’ then
2832 LoadWritePC(MemA[address,4]);
2833
2834 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2835 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2836#endif
2837
2838 bool success = false;
2839 const uint32_t opcode = OpcodeAsUnsigned (&success);
2840 if (!success)
2841 return false;
2842
2843 if (ConditionPassed())
2844 {
2845 uint32_t n;
2846 uint32_t registers = 0;
2847 bool wback;
2848 const uint32_t addr_byte_size = GetAddressByteSize();
2849 switch (encoding)
2850 {
2851 case eEncodingA1:
2852 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2853 n = Bits32 (opcode, 19, 16);
2854 registers = Bits32 (opcode, 15, 0);
2855 wback = BitIsSet (opcode, 21);
2856
2857 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2858 if ((n == 15) || (BitCount (registers) < 1))
2859 return false;
2860
2861 break;
2862 default:
2863 return false;
2864 }
2865 // address = R[n] + 4;
2866
2867 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002868 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2869
2870 if (!success)
2871 return false;
2872
2873 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002874
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002875 EmulateInstruction::Context context;
2876 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2877 Register dwarf_reg;
2878 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2879 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002880
2881 for (int i = 0; i < 14; ++i)
2882 {
2883 if (BitIsSet (registers, i))
2884 {
2885 // R[i] = MemA[address,4]; address = address + 4;
2886
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002887 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002888 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002889 if (!success)
2890 return false;
2891
2892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2893 return false;
2894
2895 offset += addr_byte_size;
2896 }
2897 }
2898
2899 // if registers<15> == ’1’ then
2900 // LoadWritePC(MemA[address,4]);
2901 if (BitIsSet (registers, 15))
2902 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002903 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002904 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002905 if (!success)
2906 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002907 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002908 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002909 return false;
2910 }
2911
2912 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2913 if (wback && BitIsClear (registers, n))
2914 {
Caroline Tice85aab332011-02-08 23:56:10 +00002915 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2916 if (!success)
2917 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002918
2919 offset = addr_byte_size * BitCount (registers);
2920 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002921 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002922 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2924 return false;
2925 }
2926
2927 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2928 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002929 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002930 }
2931 return true;
2932}
Caroline Tice0b29e242011-02-08 23:16:02 +00002933
Johnny Chenef21b592011-02-10 01:52:38 +00002934// Load Register (immediate) calculates an address from a base register value and
2935// an immediate offset, loads a word from memory, and writes to a register.
2936// LDR (immediate, Thumb)
2937bool
2938EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2939{
2940#if 0
2941 // ARM pseudo code...
2942 if (ConditionPassed())
2943 {
2944 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2945 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2946 address = if index then offset_addr else R[n];
2947 data = MemU[address,4];
2948 if wback then R[n] = offset_addr;
2949 if t == 15 then
2950 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2951 elsif UnalignedSupport() || address<1:0> = '00' then
2952 R[t] = data;
2953 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2954 }
2955#endif
2956
2957 bool success = false;
2958 const uint32_t opcode = OpcodeAsUnsigned (&success);
2959 if (!success)
2960 return false;
2961
2962 if (ConditionPassed())
2963 {
2964 uint32_t Rt; // the destination register
2965 uint32_t Rn; // the base register
2966 uint32_t imm32; // the immediate offset used to form the address
2967 addr_t offset_addr; // the offset address
2968 addr_t address; // the calculated address
2969 uint32_t data; // the literal data value from memory load
2970 bool add, index, wback;
2971 switch (encoding) {
2972 case eEncodingT1:
2973 Rt = Bits32(opcode, 5, 3);
2974 Rn = Bits32(opcode, 2, 0);
2975 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2976 // index = TRUE; add = TRUE; wback = FALSE
2977 add = true;
2978 index = true;
2979 wback = false;
2980 break;
2981 default:
2982 return false;
2983 }
2984 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2985 if (!success)
2986 return false;
2987 if (add)
2988 offset_addr = base + imm32;
2989 else
2990 offset_addr = base - imm32;
2991
2992 address = (index ? offset_addr : base);
2993
2994 if (wback)
2995 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002996 EmulateInstruction::Context ctx;
2997 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
2998 Register dwarf_reg;
2999 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3000 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3001
Johnny Chenef21b592011-02-10 01:52:38 +00003002 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3003 return false;
3004 }
3005
3006 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003007 EmulateInstruction::Context context;
3008 context.type = EmulateInstruction::eContextImmediate;
3009 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003010
3011 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003012 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003013 if (!success)
3014 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003015
3016 if (Rt == 15)
3017 {
3018 if (Bits32(address, 1, 0) == 0)
3019 {
Johnny Chen668b4512011-02-15 21:08:58 +00003020 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003021 return false;
3022 }
3023 else
3024 return false;
3025 }
3026 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3027 {
3028 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3029 return false;
3030 }
3031 else
3032 return false;
3033 }
3034 return true;
3035}
3036
Caroline Ticeaf556562011-02-15 18:42:15 +00003037// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3038// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3039// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003040bool
3041EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3042{
3043#if 0
3044 if ConditionPassed() then
3045 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3046 address = R[n];
3047
3048 for i = 0 to 14
3049 if registers<i> == ’1’ then
3050 if i == n && wback && i != LowestSetBit(registers) then
3051 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3052 else
3053 MemA[address,4] = R[i];
3054 address = address + 4;
3055
3056 if registers<15> == ’1’ then // Only possible for encoding A1
3057 MemA[address,4] = PCStoreValue();
3058 if wback then R[n] = R[n] + 4*BitCount(registers);
3059#endif
3060
3061 bool success = false;
3062 const uint32_t opcode = OpcodeAsUnsigned (&success);
3063 if (!success)
3064 return false;
3065
3066 if (ConditionPassed ())
3067 {
3068 uint32_t n;
3069 uint32_t registers = 0;
3070 bool wback;
3071 const uint32_t addr_byte_size = GetAddressByteSize();
3072
3073 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3074 switch (encoding)
3075 {
3076 case eEncodingT1:
3077 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3078 n = Bits32 (opcode, 10, 8);
3079 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003080 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003081 wback = true;
3082
3083 // if BitCount(registers) < 1 then UNPREDICTABLE;
3084 if (BitCount (registers) < 1)
3085 return false;
3086
3087 break;
3088
3089 case eEncodingT2:
3090 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3091 n = Bits32 (opcode, 19, 16);
3092 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003093 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003094 wback = BitIsSet (opcode, 21);
3095
3096 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3097 if ((n == 15) || (BitCount (registers) < 2))
3098 return false;
3099
3100 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3101 if (wback && BitIsSet (registers, n))
3102 return false;
3103
3104 break;
3105
3106 case eEncodingA1:
3107 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3108 n = Bits32 (opcode, 19, 16);
3109 registers = Bits32 (opcode, 15, 0);
3110 wback = BitIsSet (opcode, 21);
3111
3112 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3113 if ((n == 15) || (BitCount (registers) < 1))
3114 return false;
3115
3116 break;
3117
3118 default:
3119 return false;
3120 }
3121
3122 // address = R[n];
3123 int32_t offset = 0;
3124 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3125 if (!success)
3126 return false;
3127
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003128 EmulateInstruction::Context context;
3129 context.type = EmulateInstruction::eContextRegisterStore;
3130 Register base_reg;
3131 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003132
3133 // for i = 0 to 14
3134 for (int i = 0; i < 14; ++i)
3135 {
3136 int lowest_set_bit = 14;
3137 // if registers<i> == ’1’ then
3138 if (BitIsSet (registers, i))
3139 {
3140 if (i < lowest_set_bit)
3141 lowest_set_bit = i;
3142 // if i == n && wback && i != LowestSetBit(registers) then
3143 if ((i == n) && wback && (i != lowest_set_bit))
3144 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3145 WriteBits32UnknownToMemory (address + offset);
3146 else
3147 {
3148 // MemA[address,4] = R[i];
3149 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3150 if (!success)
3151 return false;
3152
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003153 Register data_reg;
3154 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3155 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003156 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003157 return false;
3158 }
3159
3160 // address = address + 4;
3161 offset += addr_byte_size;
3162 }
3163 }
3164
3165 // if registers<15> == ’1’ then // Only possible for encoding A1
3166 // MemA[address,4] = PCStoreValue();
3167 if (BitIsSet (registers, 15))
3168 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003169 Register pc_reg;
3170 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3171 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003172 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3173 if (!success)
3174 return false;
3175
Caroline Ticecc96eb52011-02-17 19:20:40 +00003176 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003177 return false;
3178 }
3179
3180 // if wback then R[n] = R[n] + 4*BitCount(registers);
3181 if (wback)
3182 {
3183 offset = addr_byte_size * BitCount (registers);
3184 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003185 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003186 addr_t data = address + offset;
3187 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3188 return false;
3189 }
3190 }
3191 return true;
3192}
3193
Caroline Ticeaf556562011-02-15 18:42:15 +00003194// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3195// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3196// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003197bool
3198EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3199{
3200#if 0
3201 if ConditionPassed() then
3202 EncodingSpecificOperations();
3203 address = R[n] - 4*BitCount(registers) + 4;
3204
3205 for i = 0 to 14
3206 if registers<i> == ’1’ then
3207 if i == n && wback && i != LowestSetBit(registers) then
3208 MemA[address,4] = bits(32) UNKNOWN;
3209 else
3210 MemA[address,4] = R[i];
3211 address = address + 4;
3212
3213 if registers<15> == ’1’ then
3214 MemA[address,4] = PCStoreValue();
3215
3216 if wback then R[n] = R[n] - 4*BitCount(registers);
3217#endif
3218
3219 bool success = false;
3220 const uint32_t opcode = OpcodeAsUnsigned (&success);
3221 if (!success)
3222 return false;
3223
3224 if (ConditionPassed ())
3225 {
3226 uint32_t n;
3227 uint32_t registers = 0;
3228 bool wback;
3229 const uint32_t addr_byte_size = GetAddressByteSize();
3230
3231 // EncodingSpecificOperations();
3232 switch (encoding)
3233 {
3234 case eEncodingA1:
3235 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3236 n = Bits32 (opcode, 19, 16);
3237 registers = Bits32 (opcode, 15, 0);
3238 wback = BitIsSet (opcode, 21);
3239
3240 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3241 if ((n == 15) || (BitCount (registers) < 1))
3242 return false;
3243 break;
3244 default:
3245 return false;
3246 }
3247
3248 // address = R[n] - 4*BitCount(registers) + 4;
3249 int32_t offset = 0;
3250 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3251 if (!success)
3252 return false;
3253
3254 address = address - (addr_byte_size * BitCount (registers)) + 4;
3255
3256 EmulateInstruction::Context context;
3257 context.type = EmulateInstruction::eContextRegisterStore;
3258 Register base_reg;
3259 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3260
3261 // for i = 0 to 14
3262 for (int i = 0; i < 14; ++i)
3263 {
3264 int lowest_bit_set = 14;
3265 // if registers<i> == ’1’ then
3266 if (BitIsSet (registers, i))
3267 {
3268 if (i < lowest_bit_set)
3269 lowest_bit_set = i;
3270 //if i == n && wback && i != LowestSetBit(registers) then
3271 if ((i == n) && wback && (i != lowest_bit_set))
3272 // MemA[address,4] = bits(32) UNKNOWN;
3273 WriteBits32UnknownToMemory (address + offset);
3274 else
3275 {
3276 // MemA[address,4] = R[i];
3277 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3278 if (!success)
3279 return false;
3280
3281 Register data_reg;
3282 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3283 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003284 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003285 return false;
3286 }
3287
3288 // address = address + 4;
3289 offset += addr_byte_size;
3290 }
3291 }
3292
3293 // if registers<15> == ’1’ then
3294 // MemA[address,4] = PCStoreValue();
3295 if (BitIsSet (registers, 15))
3296 {
3297 Register pc_reg;
3298 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3299 context.SetRegisterPlusOffset (pc_reg, 8);
3300 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3301 if (!success)
3302 return false;
3303
Caroline Ticecc96eb52011-02-17 19:20:40 +00003304 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003305 return false;
3306 }
3307
3308 // if wback then R[n] = R[n] - 4*BitCount(registers);
3309 if (wback)
3310 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003311 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003312 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3313 context.SetImmediateSigned (offset);
3314 addr_t data = address + offset;
3315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3316 return false;
3317 }
3318 }
3319 return true;
3320}
3321
Caroline Ticeaf556562011-02-15 18:42:15 +00003322// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3323// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3324// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003325bool
3326EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3327{
3328#if 0
3329 if ConditionPassed() then
3330 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3331 address = R[n] - 4*BitCount(registers);
3332
3333 for i = 0 to 14
3334 if registers<i> == ’1’ then
3335 if i == n && wback && i != LowestSetBit(registers) then
3336 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3337 else
3338 MemA[address,4] = R[i];
3339 address = address + 4;
3340
3341 if registers<15> == ’1’ then // Only possible for encoding A1
3342 MemA[address,4] = PCStoreValue();
3343
3344 if wback then R[n] = R[n] - 4*BitCount(registers);
3345#endif
3346
3347
3348 bool success = false;
3349 const uint32_t opcode = OpcodeAsUnsigned (&success);
3350 if (!success)
3351 return false;
3352
3353 if (ConditionPassed ())
3354 {
3355 uint32_t n;
3356 uint32_t registers = 0;
3357 bool wback;
3358 const uint32_t addr_byte_size = GetAddressByteSize();
3359
3360 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3361 switch (encoding)
3362 {
3363 case eEncodingT1:
3364 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3365 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3366 {
3367 // See PUSH
3368 }
3369 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3370 n = Bits32 (opcode, 19, 16);
3371 registers = Bits32 (opcode, 15, 0);
3372 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3373 wback = BitIsSet (opcode, 21);
3374 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3375 if ((n == 15) || BitCount (registers) < 2)
3376 return false;
3377 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3378 if (wback && BitIsSet (registers, n))
3379 return false;
3380 break;
3381
3382 case eEncodingA1:
3383 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3384 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3385 {
3386 // See Push
3387 }
3388 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3389 n = Bits32 (opcode, 19, 16);
3390 registers = Bits32 (opcode, 15, 0);
3391 wback = BitIsSet (opcode, 21);
3392 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3393 if ((n == 15) || BitCount (registers) < 1)
3394 return false;
3395 break;
3396
3397 default:
3398 return false;
3399 }
3400
3401 // address = R[n] - 4*BitCount(registers);
3402
3403 int32_t offset = 0;
3404 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3405 if (!success)
3406 return false;
3407
3408 address = address - (addr_byte_size * BitCount (registers));
3409
3410 EmulateInstruction::Context context;
3411 context.type = EmulateInstruction::eContextRegisterStore;
3412 Register base_reg;
3413 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3414
3415 // for i = 0 to 14
3416 for (int i = 0; i < 14; ++i)
3417 {
3418 uint32_t lowest_set_bit = 14;
3419 // if registers<i> == ’1’ then
3420 if (BitIsSet (registers, i))
3421 {
3422 if (i < lowest_set_bit)
3423 lowest_set_bit = i;
3424 // if i == n && wback && i != LowestSetBit(registers) then
3425 if ((i == n) && wback && (i != lowest_set_bit))
3426 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3427 WriteBits32UnknownToMemory (address + offset);
3428 else
3429 {
3430 // MemA[address,4] = R[i];
3431 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3432 if (!success)
3433 return false;
3434
3435 Register data_reg;
3436 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3437 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003438 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003439 return false;
3440 }
3441
3442 // address = address + 4;
3443 offset += addr_byte_size;
3444 }
3445 }
3446
3447 // if registers<15> == ’1’ then // Only possible for encoding A1
3448 // MemA[address,4] = PCStoreValue();
3449 if (BitIsSet (registers, 15))
3450 {
3451 Register pc_reg;
3452 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3453 context.SetRegisterPlusOffset (pc_reg, 8);
3454 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3455 if (!success)
3456 return false;
3457
Caroline Ticecc96eb52011-02-17 19:20:40 +00003458 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003459 return false;
3460 }
3461
3462 // if wback then R[n] = R[n] - 4*BitCount(registers);
3463 if (wback)
3464 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003465 offset = (addr_byte_size * BitCount (registers)) * -1;
3466 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3467 context.SetImmediateSigned (offset);
3468 addr_t data = address + offset;
3469 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3470 return false;
3471 }
3472 }
3473 return true;
3474}
3475
3476// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3477// from a base register. The consecutive memory locations start just above this address, and the address of the last
3478// of those locations can optionally be written back to the base register.
3479bool
3480EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3481{
3482#if 0
3483 if ConditionPassed() then
3484 EncodingSpecificOperations();
3485 address = R[n] + 4;
3486
3487 for i = 0 to 14
3488 if registers<i> == ’1’ then
3489 if i == n && wback && i != LowestSetBit(registers) then
3490 MemA[address,4] = bits(32) UNKNOWN;
3491 else
3492 MemA[address,4] = R[i];
3493 address = address + 4;
3494
3495 if registers<15> == ’1’ then
3496 MemA[address,4] = PCStoreValue();
3497
3498 if wback then R[n] = R[n] + 4*BitCount(registers);
3499#endif
3500
3501 bool success = false;
3502 const uint32_t opcode = OpcodeAsUnsigned (&success);
3503 if (!success)
3504 return false;
3505
3506 if (ConditionPassed())
3507 {
3508 uint32_t n;
3509 uint32_t registers = 0;
3510 bool wback;
3511 const uint32_t addr_byte_size = GetAddressByteSize();
3512
3513 // EncodingSpecificOperations();
3514 switch (encoding)
3515 {
3516 case eEncodingA1:
3517 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3518 n = Bits32 (opcode, 19, 16);
3519 registers = Bits32 (opcode, 15, 0);
3520 wback = BitIsSet (opcode, 21);
3521
3522 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3523 if ((n == 15) && (BitCount (registers) < 1))
3524 return false;
3525 break;
3526 default:
3527 return false;
3528 }
3529 // address = R[n] + 4;
3530
3531 int32_t offset = 0;
3532 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3533 if (!success)
3534 return false;
3535
3536 address = address + addr_byte_size;
3537
3538 EmulateInstruction::Context context;
3539 context.type = EmulateInstruction::eContextRegisterStore;
3540 Register base_reg;
3541 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3542
3543 uint32_t lowest_set_bit = 14;
3544 // for i = 0 to 14
3545 for (int i = 0; i < 14; ++i)
3546 {
3547 // if registers<i> == ’1’ then
3548 if (BitIsSet (registers, i))
3549 {
3550 if (i < lowest_set_bit)
3551 lowest_set_bit = i;
3552 // if i == n && wback && i != LowestSetBit(registers) then
3553 if ((i == n) && wback && (i != lowest_set_bit))
3554 // MemA[address,4] = bits(32) UNKNOWN;
3555 WriteBits32UnknownToMemory (address + offset);
3556 // else
3557 else
3558 {
3559 // MemA[address,4] = R[i];
3560 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3561 if (!success)
3562 return false;
3563
3564 Register data_reg;
3565 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3566 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003567 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003568 return false;
3569 }
3570
3571 // address = address + 4;
3572 offset += addr_byte_size;
3573 }
3574 }
3575
3576 // if registers<15> == ’1’ then
3577 // MemA[address,4] = PCStoreValue();
3578 if (BitIsSet (registers, 15))
3579 {
3580 Register pc_reg;
3581 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3582 context.SetRegisterPlusOffset (pc_reg, 8);
3583 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3584 if (!success)
3585 return false;
3586
Caroline Ticecc96eb52011-02-17 19:20:40 +00003587 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003588 return false;
3589 }
3590
3591 // if wback then R[n] = R[n] + 4*BitCount(registers);
3592 if (wback)
3593 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003594 offset = addr_byte_size * BitCount (registers);
3595 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3596 context.SetImmediateSigned (offset);
3597 addr_t data = address + offset;
3598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3599 return false;
3600 }
3601 }
3602 return true;
3603}
Caroline Tice7fac8572011-02-15 22:53:54 +00003604
3605// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3606// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3607bool
3608EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3609{
3610#if 0
3611 if ConditionPassed() then
3612 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3613 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3614 address = if index then offset_addr else R[n];
3615 if UnalignedSupport() || address<1:0> == ’00’ then
3616 MemU[address,4] = R[t];
3617 else // Can only occur before ARMv7
3618 MemU[address,4] = bits(32) UNKNOWN;
3619 if wback then R[n] = offset_addr;
3620#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003621
Caroline Tice7fac8572011-02-15 22:53:54 +00003622 bool success = false;
3623 const uint32_t opcode = OpcodeAsUnsigned (&success);
3624 if (!success)
3625 return false;
3626
3627 if (ConditionPassed())
3628 {
3629 const uint32_t addr_byte_size = GetAddressByteSize();
3630
3631 uint32_t t;
3632 uint32_t n;
3633 uint32_t imm32;
3634 bool index;
3635 bool add;
3636 bool wback;
3637 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3638 switch (encoding)
3639 {
3640 case eEncodingT1:
3641 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3642 t = Bits32 (opcode, 2, 0);
3643 n = Bits32 (opcode, 5, 3);
3644 imm32 = Bits32 (opcode, 10, 6) << 2;
3645
3646 // index = TRUE; add = TRUE; wback = FALSE;
3647 index = true;
3648 add = false;
3649 wback = false;
3650 break;
3651
3652 case eEncodingT2:
3653 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3654 t = Bits32 (opcode, 10, 8);
3655 n = 13;
3656 imm32 = Bits32 (opcode, 7, 0) << 2;
3657
3658 // index = TRUE; add = TRUE; wback = FALSE;
3659 index = true;
3660 add = true;
3661 wback = false;
3662 break;
3663
3664 case eEncodingT3:
3665 // if Rn == ’1111’ then UNDEFINED;
3666 if (Bits32 (opcode, 19, 16) == 15)
3667 return false;
3668
3669 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3670 t = Bits32 (opcode, 15, 12);
3671 n = Bits32 (opcode, 19, 16);
3672 imm32 = Bits32 (opcode, 11, 0);
3673
3674 // index = TRUE; add = TRUE; wback = FALSE;
3675 index = true;
3676 add = true;
3677 wback = false;
3678
3679 // if t == 15 then UNPREDICTABLE;
3680 if (t == 15)
3681 return false;
3682 break;
3683
3684 case eEncodingT4:
3685 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3686 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3687 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3688 if ((Bits32 (opcode, 19, 16) == 15)
3689 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3690 return false;
3691
3692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3693 t = Bits32 (opcode, 15, 12);
3694 n = Bits32 (opcode, 19, 16);
3695 imm32 = Bits32 (opcode, 7, 0);
3696
3697 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3698 index = BitIsSet (opcode, 10);
3699 add = BitIsSet (opcode, 9);
3700 wback = BitIsSet (opcode, 8);
3701
3702 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3703 if ((t == 15) || (wback && (n == t)))
3704 return false;
3705 break;
3706
3707 default:
3708 return false;
3709 }
3710
3711 addr_t offset_addr;
3712 addr_t address;
3713
3714 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3715 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3716 if (!success)
3717 return false;
3718
3719 if (add)
3720 offset_addr = base_address + imm32;
3721 else
3722 offset_addr = base_address - imm32;
3723
3724 // address = if index then offset_addr else R[n];
3725 if (index)
3726 address = offset_addr;
3727 else
3728 address = base_address;
3729
3730 EmulateInstruction::Context context;
3731 context.type = eContextRegisterStore;
3732 Register base_reg;
3733 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3734
3735 // if UnalignedSupport() || address<1:0> == ’00’ then
3736 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3737 {
3738 // MemU[address,4] = R[t];
3739 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3740 if (!success)
3741 return false;
3742
3743 Register data_reg;
3744 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3745 int32_t offset = address - base_address;
3746 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003747 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003748 return false;
3749 }
3750 else
3751 {
3752 // MemU[address,4] = bits(32) UNKNOWN;
3753 WriteBits32UnknownToMemory (address);
3754 }
3755
3756 // if wback then R[n] = offset_addr;
3757 if (wback)
3758 {
3759 context.type = eContextRegisterLoad;
3760 context.SetAddress (offset_addr);
3761 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3762 return false;
3763 }
3764 }
3765 return true;
3766}
Caroline Ticeaf556562011-02-15 18:42:15 +00003767
Caroline Tice3fd63e92011-02-16 00:33:43 +00003768// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3769// word from a register to memory. The offset register value can optionally be shifted.
3770bool
3771EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3772{
3773#if 0
3774 if ConditionPassed() then
3775 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3776 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3777 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3778 address = if index then offset_addr else R[n];
3779 if t == 15 then // Only possible for encoding A1
3780 data = PCStoreValue();
3781 else
3782 data = R[t];
3783 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3784 MemU[address,4] = data;
3785 else // Can only occur before ARMv7
3786 MemU[address,4] = bits(32) UNKNOWN;
3787 if wback then R[n] = offset_addr;
3788#endif
3789
3790 bool success = false;
3791 const uint32_t opcode = OpcodeAsUnsigned (&success);
3792 if (!success)
3793 return false;
3794
3795 if (ConditionPassed())
3796 {
3797 const uint32_t addr_byte_size = GetAddressByteSize();
3798
3799 uint32_t t;
3800 uint32_t n;
3801 uint32_t m;
3802 ARM_ShifterType shift_t;
3803 uint32_t shift_n;
3804 bool index;
3805 bool add;
3806 bool wback;
3807
3808 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3809 switch (encoding)
3810 {
3811 case eEncodingT1:
3812 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3813 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3814 t = Bits32 (opcode, 2, 0);
3815 n = Bits32 (opcode, 5, 3);
3816 m = Bits32 (opcode, 8, 6);
3817
3818 // index = TRUE; add = TRUE; wback = FALSE;
3819 index = true;
3820 add = true;
3821 wback = false;
3822
3823 // (shift_t, shift_n) = (SRType_LSL, 0);
3824 shift_t = SRType_LSL;
3825 shift_n = 0;
3826 break;
3827
3828 case eEncodingT2:
3829 // if Rn == ’1111’ then UNDEFINED;
3830 if (Bits32 (opcode, 19, 16) == 15)
3831 return false;
3832
3833 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3834 t = Bits32 (opcode, 15, 12);
3835 n = Bits32 (opcode, 19, 16);
3836 m = Bits32 (opcode, 3, 0);
3837
3838 // index = TRUE; add = TRUE; wback = FALSE;
3839 index = true;
3840 add = true;
3841 wback = false;
3842
3843 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3844 shift_t = SRType_LSL;
3845 shift_n = Bits32 (opcode, 5, 4);
3846
3847 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3848 if ((t == 15) || (BadReg (m)))
3849 return false;
3850 break;
3851
3852 case eEncodingA1:
3853 {
3854 // if P == ’0’ && W == ’1’ then SEE STRT;
3855 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3856 t = Bits32 (opcode, 15, 12);
3857 n = Bits32 (opcode, 19, 16);
3858 m = Bits32 (opcode, 3, 0);
3859
3860 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3861 index = BitIsSet (opcode, 24);
3862 add = BitIsSet (opcode, 23);
3863 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3864
3865 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3866 uint32_t typ = Bits32 (opcode, 6, 5);
3867 uint32_t imm5 = Bits32 (opcode, 11, 7);
3868 shift_n = DecodeImmShift(typ, imm5, shift_t);
3869
3870 // if m == 15 then UNPREDICTABLE;
3871 if (m == 15)
3872 return false;
3873
3874 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3875 if (wback && ((n == 15) || (n == t)))
3876 return false;
3877
3878 break;
3879 }
3880 default:
3881 return false;
3882 }
3883
3884 addr_t offset_addr;
3885 addr_t address;
3886 int32_t offset = 0;
3887
3888 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3889 if (!success)
3890 return false;
3891
3892 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3893 if (!success)
3894 return false;
3895
3896 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
3897 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
3898
3899 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3900 if (add)
3901 offset_addr = base_address + offset;
3902 else
3903 offset_addr = base_address - offset;
3904
3905 // address = if index then offset_addr else R[n];
3906 if (index)
3907 address = offset_addr;
3908 else
3909 address = base_address;
3910
3911 uint32_t data;
3912 // if t == 15 then // Only possible for encoding A1
3913 if (t == 15)
3914 // data = PCStoreValue();
3915 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3916 else
3917 // data = R[t];
3918 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3919
3920 if (!success)
3921 return false;
3922
3923 EmulateInstruction::Context context;
3924 context.type = eContextRegisterStore;
3925
3926 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3927 if (UnalignedSupport ()
3928 || (BitIsClear (address, 1) && BitIsClear (address, 0))
3929 || CurrentInstrSet() == eModeARM)
3930 {
3931 // MemU[address,4] = data;
3932
3933 Register base_reg;
3934 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3935
3936 Register data_reg;
3937 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3938
3939 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003940 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00003941 return false;
3942
3943 }
3944 else
3945 // MemU[address,4] = bits(32) UNKNOWN;
3946 WriteBits32UnknownToMemory (address);
3947
3948 // if wback then R[n] = offset_addr;
3949 if (wback)
3950 {
3951 context.type = eContextRegisterLoad;
3952 context.SetAddress (offset_addr);
3953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3954 return false;
3955 }
3956
3957 }
3958 return true;
3959}
Caroline Tice73a29de2011-02-16 20:22:22 +00003960
3961bool
3962EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
3963{
3964#if 0
3965 if ConditionPassed() then
3966 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3967 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3968 address = if index then offset_addr else R[n];
3969 MemU[address,1] = R[t]<7:0>;
3970 if wback then R[n] = offset_addr;
3971#endif
3972
3973
3974 bool success = false;
3975 const uint32_t opcode = OpcodeAsUnsigned (&success);
3976 if (!success)
3977 return false;
3978
3979 if (ConditionPassed ())
3980 {
3981 uint32_t t;
3982 uint32_t n;
3983 uint32_t imm32;
3984 bool index;
3985 bool add;
3986 bool wback;
3987 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3988 switch (encoding)
3989 {
3990 case eEncodingT1:
3991 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
3992 t = Bits32 (opcode, 2, 0);
3993 n = Bits32 (opcode, 5, 3);
3994 imm32 = Bits32 (opcode, 10, 6);
3995
3996 // index = TRUE; add = TRUE; wback = FALSE;
3997 index = true;
3998 add = true;
3999 wback = false;
4000 break;
4001
4002 case eEncodingT2:
4003 // if Rn == ’1111’ then UNDEFINED;
4004 if (Bits32 (opcode, 19, 16) == 15)
4005 return false;
4006
4007 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4008 t = Bits32 (opcode, 15, 12);
4009 n = Bits32 (opcode, 19, 16);
4010 imm32 = Bits32 (opcode, 11, 0);
4011
4012 // index = TRUE; add = TRUE; wback = FALSE;
4013 index = true;
4014 add = true;
4015 wback = false;
4016
4017 // if BadReg(t) then UNPREDICTABLE;
4018 if (BadReg (t))
4019 return false;
4020 break;
4021
4022 case eEncodingT3:
4023 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4024 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4025 if (Bits32 (opcode, 19, 16) == 15)
4026 return false;
4027
4028 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4029 t = Bits32 (opcode, 15, 12);
4030 n = Bits32 (opcode, 19, 16);
4031 imm32 = Bits32 (opcode, 7, 0);
4032
4033 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4034 index = BitIsSet (opcode, 10);
4035 add = BitIsSet (opcode, 9);
4036 wback = BitIsSet (opcode, 8);
4037
4038 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4039 if ((BadReg (t)) || (wback && (n == t)))
4040 return false;
4041 break;
4042
4043 default:
4044 return false;
4045 }
4046
4047 addr_t offset_addr;
4048 addr_t address;
4049 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4050 if (!success)
4051 return false;
4052
4053 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4054 if (add)
4055 offset_addr = base_address + imm32;
4056 else
4057 offset_addr = base_address - imm32;
4058
4059 // address = if index then offset_addr else R[n];
4060 if (index)
4061 address = offset_addr;
4062 else
4063 address = base_address;
4064
Caroline Ticecc96eb52011-02-17 19:20:40 +00004065 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004066 Register base_reg;
4067 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4068
4069 Register data_reg;
4070 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4071
4072 EmulateInstruction::Context context;
4073 context.type = eContextRegisterStore;
4074 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4075
4076 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4077 if (!success)
4078 return false;
4079
4080 data = Bits32 (data, 7, 0);
4081
Caroline Ticecc96eb52011-02-17 19:20:40 +00004082 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004083 return false;
4084
4085 // if wback then R[n] = offset_addr;
4086 if (wback)
4087 {
4088 context.type = eContextRegisterLoad;
4089 context.SetAddress (offset_addr);
4090 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4091 return false;
4092 }
4093
4094 }
4095
4096 return true;
4097}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004098
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004099EmulateInstructionARM::ARMOpcode*
4100EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004101{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004102 static ARMOpcode
4103 g_arm_opcodes[] =
4104 {
4105 //----------------------------------------------------------------------
4106 // Prologue instructions
4107 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004108
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004109 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004110 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
4111 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004112
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004113 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004114 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
4115 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004116 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00004117 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
4118 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
4119 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004120
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004121 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004122 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004123
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004124 // push one register
4125 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004126 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004127
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004128 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004129 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4130 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004131
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004132 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004133 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004134 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004135
Johnny Chenc28a76d2011-02-01 18:51:48 +00004136 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
4137 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004138 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004139 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4140
4141 //----------------------------------------------------------------------
4142 // Supervisor Call (previously Software Interrupt)
4143 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004144 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4145
4146 //----------------------------------------------------------------------
4147 // Branch instructions
4148 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004149 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004150 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4151 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4152 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4153 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004154 // for example, "bx lr"
4155 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004156
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004157 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004158 // Data-processing instructions
4159 //----------------------------------------------------------------------
4160 // move bitwise not
4161 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004162 // asr (immediate)
4163 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004164 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004165 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004166 // lsl (immediate)
4167 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4168 // lsl (register)
4169 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4170 // lsr (immediate)
4171 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4172 // lsr (register)
4173 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004174 // rrx is a special case encoding of ror (immediate)
4175 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4176 // ror (immediate)
4177 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4178 // ror (register)
4179 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004180
4181 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004182 // Load instructions
4183 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004184 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004185 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004186 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004187 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4188
4189 //----------------------------------------------------------------------
4190 // Store instructions
4191 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004192 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004193 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004194 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004195 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4196 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004197
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004198
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004199 };
4200 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4201
4202 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4203 {
4204 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4205 return &g_arm_opcodes[i];
4206 }
4207 return NULL;
4208}
Greg Clayton64c84432011-01-21 22:02:52 +00004209
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004210
4211EmulateInstructionARM::ARMOpcode*
4212EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004213{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004214
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004215 static ARMOpcode
4216 g_thumb_opcodes[] =
4217 {
4218 //----------------------------------------------------------------------
4219 // Prologue instructions
4220 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004221
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004222 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004223 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004224 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
4225 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004226
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004227 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004228 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004229 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00004230 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004231 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
4232 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004233
Johnny Chenc9de9102011-02-11 19:12:30 +00004234 // PC-relative load into register (see also EmulateAddSPRm)
4235 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004236
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004237 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004238 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
4239 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004240 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
4241 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004242
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004243 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004244 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4245 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004246
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004247 //----------------------------------------------------------------------
4248 // Epilogue instructions
4249 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004250
Johnny Chenc28a76d2011-02-01 18:51:48 +00004251 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
4252 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004253 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
4254 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
4255 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4256 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004257
4258 //----------------------------------------------------------------------
4259 // Supervisor Call (previously Software Interrupt)
4260 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004261 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4262
4263 //----------------------------------------------------------------------
4264 // If Then makes up to four following instructions conditional.
4265 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004266 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4267
4268 //----------------------------------------------------------------------
4269 // Branch instructions
4270 //----------------------------------------------------------------------
4271 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4272 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4273 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004274 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004275 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004276 // J1 == J2 == 1
4277 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4278 // J1 == J2 == 1
4279 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4280 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004281 // for example, "bx lr"
4282 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004283 // compare and branch
4284 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004285
4286 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004287 // Data-processing instructions
4288 //----------------------------------------------------------------------
4289 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
4290 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004291 // move from high register to high register
4292 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
4293 // move from low register to low register
4294 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004295 // move immediate
4296 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
4297 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004298 // move bitwise not
4299 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004300 // compare a register with immediate
4301 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004302 // compare Rn with Rm (Rn and Rm both from r0-r7)
4303 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
4304 // compare Rn with Rm (Rn and Rm not both from r0-r7)
4305 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004306 // asr (immediate)
4307 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004308 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004309 // asr (register)
4310 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4311 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004312 // lsl (immediate)
4313 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4314 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4315 // lsl (register)
4316 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4317 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4318 // lsr (immediate)
4319 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4320 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4321 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004322 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004323 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004324 // rrx is a special case encoding of ror (immediate)
4325 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4326 // ror (immediate)
4327 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4328 // ror (register)
4329 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4330 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004331
4332 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004333 // Load instructions
4334 //----------------------------------------------------------------------
4335 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004336 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004337 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004338 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4339 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004340 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4341
4342 //----------------------------------------------------------------------
4343 // Store instructions
4344 //----------------------------------------------------------------------
4345 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004346 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004347 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4348 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4349 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4350 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004351 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4352 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004353 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4354 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4355 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4356 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004357 };
4358
4359 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4360 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4361 {
4362 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4363 return &g_thumb_opcodes[i];
4364 }
4365 return NULL;
4366}
Greg Clayton64c84432011-01-21 22:02:52 +00004367
Greg Clayton31e2a382011-01-30 20:03:56 +00004368bool
Greg Clayton395fc332011-02-15 21:59:32 +00004369EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004370{
4371 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004372 const char *arch_cstr = arch.AsCString ();
4373 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004374 {
Greg Clayton395fc332011-02-15 21:59:32 +00004375 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4376 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4377 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4378 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4379 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4380 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4381 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4382 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4383 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4384 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004385 }
4386 return m_arm_isa != 0;
4387}
4388
4389
Greg Clayton64c84432011-01-21 22:02:52 +00004390bool
4391EmulateInstructionARM::ReadInstruction ()
4392{
4393 bool success = false;
4394 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4395 if (success)
4396 {
4397 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4398 if (success)
4399 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004400 Context read_inst_context;
4401 read_inst_context.type = eContextReadOpcode;
4402 read_inst_context.SetNoArgs ();
4403
Greg Clayton64c84432011-01-21 22:02:52 +00004404 if (m_inst_cpsr & MASK_CPSR_T)
4405 {
4406 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004407 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004408
4409 if (success)
4410 {
4411 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4412 {
4413 m_inst.opcode_type = eOpcode16;
4414 m_inst.opcode.inst16 = thumb_opcode;
4415 }
4416 else
4417 {
4418 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004419 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004420 }
4421 }
4422 }
4423 else
4424 {
4425 m_inst_mode = eModeARM;
4426 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004427 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004428 }
4429 }
4430 }
4431 if (!success)
4432 {
4433 m_inst_mode = eModeInvalid;
4434 m_inst_pc = LLDB_INVALID_ADDRESS;
4435 }
4436 return success;
4437}
4438
Johnny Chenee9b1f72011-02-09 01:00:31 +00004439uint32_t
4440EmulateInstructionARM::ArchVersion ()
4441{
4442 return m_arm_isa;
4443}
4444
Greg Clayton64c84432011-01-21 22:02:52 +00004445bool
4446EmulateInstructionARM::ConditionPassed ()
4447{
4448 if (m_inst_cpsr == 0)
4449 return false;
4450
4451 const uint32_t cond = CurrentCond ();
4452
4453 if (cond == UINT32_MAX)
4454 return false;
4455
4456 bool result = false;
4457 switch (UnsignedBits(cond, 3, 1))
4458 {
4459 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4460 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4461 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4462 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4463 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4464 case 5:
4465 {
4466 bool n = (m_inst_cpsr & MASK_CPSR_N);
4467 bool v = (m_inst_cpsr & MASK_CPSR_V);
4468 result = n == v;
4469 }
4470 break;
4471 case 6:
4472 {
4473 bool n = (m_inst_cpsr & MASK_CPSR_N);
4474 bool v = (m_inst_cpsr & MASK_CPSR_V);
4475 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4476 }
4477 break;
4478 case 7:
4479 result = true;
4480 break;
4481 }
4482
4483 if (cond & 1)
4484 result = !result;
4485 return result;
4486}
4487
Johnny Chen9ee056b2011-02-08 00:06:35 +00004488uint32_t
4489EmulateInstructionARM::CurrentCond ()
4490{
4491 switch (m_inst_mode)
4492 {
4493 default:
4494 case eModeInvalid:
4495 break;
4496
4497 case eModeARM:
4498 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4499
4500 case eModeThumb:
4501 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4502 // 'cond' field of the encoding.
4503 if (m_inst.opcode_type == eOpcode16 &&
4504 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4505 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4506 {
4507 return Bits32(m_inst.opcode.inst16, 11, 7);
4508 }
4509 else if (m_inst.opcode_type == eOpcode32 &&
4510 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4511 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4512 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4513 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4514 {
4515 return Bits32(m_inst.opcode.inst32, 25, 22);
4516 }
4517
4518 return m_it_session.GetCond();
4519 }
4520 return UINT32_MAX; // Return invalid value
4521}
4522
Johnny Chen9ee056b2011-02-08 00:06:35 +00004523bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004524EmulateInstructionARM::InITBlock()
4525{
4526 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4527}
4528
4529bool
4530EmulateInstructionARM::LastInITBlock()
4531{
4532 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4533}
4534
4535bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004536EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4537{
4538 addr_t target;
4539
Johnny Chenee9b1f72011-02-09 01:00:31 +00004540 // Check the current instruction set.
4541 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004542 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004543 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004544 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004545
Johnny Chen9ee056b2011-02-08 00:06:35 +00004546 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004547 return false;
4548
4549 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004550}
4551
4552// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4553bool
Johnny Chen668b4512011-02-15 21:08:58 +00004554EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004555{
4556 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004557 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4558 // we want to record it and issue a WriteRegister callback so the clients
4559 // can track the mode changes accordingly.
4560 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004561
4562 if (BitIsSet(addr, 0))
4563 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004564 if (CurrentInstrSet() != eModeThumb)
4565 {
4566 SelectInstrSet(eModeThumb);
4567 cpsr_changed = true;
4568 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004569 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004570 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004571 }
4572 else if (BitIsClear(addr, 1))
4573 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004574 if (CurrentInstrSet() != eModeARM)
4575 {
4576 SelectInstrSet(eModeARM);
4577 cpsr_changed = true;
4578 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004579 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004580 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004581 }
4582 else
4583 return false; // address<1:0> == '10' => UNPREDICTABLE
4584
Johnny Chen0f309db2011-02-09 19:11:32 +00004585 if (cpsr_changed)
4586 {
Johnny Chen558133b2011-02-09 23:59:17 +00004587 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004588 return false;
4589 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004590 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004591 return false;
4592
4593 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004594}
Greg Clayton64c84432011-01-21 22:02:52 +00004595
Johnny Chenee9b1f72011-02-09 01:00:31 +00004596// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4597bool
Johnny Chen668b4512011-02-15 21:08:58 +00004598EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004599{
4600 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004601 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004602 else
4603 return BranchWritePC((const Context)context, addr);
4604}
4605
Johnny Chen26863dc2011-02-09 23:43:29 +00004606// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4607bool
Johnny Chen668b4512011-02-15 21:08:58 +00004608EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004609{
4610 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004611 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004612 else
4613 return BranchWritePC((const Context)context, addr);
4614}
4615
Johnny Chenee9b1f72011-02-09 01:00:31 +00004616EmulateInstructionARM::Mode
4617EmulateInstructionARM::CurrentInstrSet ()
4618{
4619 return m_inst_mode;
4620}
4621
4622// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004623// ReadInstruction() is performed. This function has a side effect of updating
4624// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004625bool
4626EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4627{
Johnny Chen558133b2011-02-09 23:59:17 +00004628 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004629 switch (arm_or_thumb)
4630 {
4631 default:
4632 return false;
4633 eModeARM:
4634 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004635 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004636 break;
4637 eModeThumb:
4638 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004639 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004640 break;
4641 }
4642 return true;
4643}
4644
Johnny Chenef21b592011-02-10 01:52:38 +00004645// This function returns TRUE if the processor currently provides support for
4646// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4647// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4648bool
4649EmulateInstructionARM::UnalignedSupport()
4650{
4651 return (ArchVersion() >= ARMv7);
4652}
4653
Johnny Chenbf6ad172011-02-11 01:29:53 +00004654// The main addition and subtraction instructions can produce status information
4655// about both unsigned carry and signed overflow conditions. This status
4656// information can be used to synthesize multi-word additions and subtractions.
4657EmulateInstructionARM::AddWithCarryResult
4658EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4659{
4660 uint32_t result;
4661 uint8_t carry_out;
4662 uint8_t overflow;
4663
4664 uint64_t unsigned_sum = x + y + carry_in;
4665 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4666
4667 result = UnsignedBits(unsigned_sum, 31, 0);
4668 carry_out = (result == unsigned_sum ? 0 : 1);
4669 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4670
4671 AddWithCarryResult res = { result, carry_out, overflow };
4672 return res;
4673}
4674
Johnny Chenca67d1c2011-02-17 01:35:27 +00004675// Write the result to the ARM core register Rd, and optionally update the
4676// condition flags based on the result.
4677//
4678// This helper method tries to encapsulate the following pseudocode from the
4679// ARM Architecture Reference Manual:
4680//
4681// if d == 15 then // Can only occur for encoding A1
4682// ALUWritePC(result); // setflags is always FALSE here
4683// else
4684// R[d] = result;
4685// if setflags then
4686// APSR.N = result<31>;
4687// APSR.Z = IsZeroBit(result);
4688// APSR.C = carry;
4689// // APSR.V unchanged
4690//
4691// In the above case, the API client does not pass in the overflow arg, which
4692// defaults to ~0u.
4693bool
4694EmulateInstructionARM::WriteCoreRegisterWithFlags (Context &context,
4695 const uint32_t result,
4696 const uint32_t Rd,
4697 bool setflags,
4698 const uint32_t carry,
4699 const uint32_t overflow)
4700{
4701 if (Rd == 15)
4702 {
4703 if (!ALUWritePC (context, result))
4704 return false;
4705 }
4706 else
4707 {
4708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
4709 return false;
4710 if (setflags)
4711 {
4712 m_new_inst_cpsr = m_inst_cpsr;
4713 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
4714 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
4715 if (carry != ~0u)
4716 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
4717 if (overflow != ~0u)
4718 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
4719 if (m_new_inst_cpsr != m_inst_cpsr)
4720 {
4721 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
4722 return false;
4723 }
4724 }
4725 }
4726 return true;
4727}
4728
Greg Clayton64c84432011-01-21 22:02:52 +00004729bool
4730EmulateInstructionARM::EvaluateInstruction ()
4731{
Johnny Chenc315f862011-02-05 00:46:10 +00004732 // Advance the ITSTATE bits to their values for the next instruction.
4733 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4734 m_it_session.ITAdvance();
4735
Greg Clayton64c84432011-01-21 22:02:52 +00004736 return false;
4737}