blob: 36608508662c526a27af63d4fdcc3d758bbaf064 [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 Chen60299ec2011-02-17 19:34:27 +00001834// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1835// A base register provides a pointer to the table, and a second register supplies an index into the table.
1836// The branch length is twice the value of the byte returned from the table.
1837//
1838// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1839// A base register provides a pointer to the table, and a second register supplies an index into the table.
1840// The branch length is twice the value of the halfword returned from the table.
1841// TBB, TBH
1842bool
1843EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1844{
1845#if 0
1846 // ARM pseudo code...
1847 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1848 if is_tbh then
1849 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1850 else
1851 halfwords = UInt(MemU[R[n]+R[m], 1]);
1852 BranchWritePC(PC + 2*halfwords);
1853#endif
1854
1855 bool success = false;
1856 const uint32_t opcode = OpcodeAsUnsigned (&success);
1857 if (!success)
1858 return false;
1859
1860 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1861 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1862 bool is_tbh; // true if table branch halfword
1863 switch (encoding) {
1864 case eEncodingT1:
1865 Rn = Bits32(opcode, 19, 16);
1866 Rm = Bits32(opcode, 3, 0);
1867 is_tbh = BitIsSet(opcode, 4);
1868 if (Rn == 13 || BadReg(Rm))
1869 return false;
1870 if (InITBlock() && !LastInITBlock())
1871 return false;
1872 break;
1873 default:
1874 return false;
1875 }
1876
1877 // Read the address of the table from the operand register Rn.
1878 // The PC can be used, in which case the table immediately follows this instruction.
1879 uint32_t base =
1880 Rn == 15 ? (ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success) + 4)
1881 : ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1882 if (!success)
1883 return false;
1884
1885 // the table index
1886 uint32_t index = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1887 if (!success)
1888 return false;
1889
1890 // the offsetted table address
1891 addr_t addr = base + (is_tbh ? index*2 : index);
1892
1893 // PC-relative offset to branch forward
1894 EmulateInstruction::Context context;
1895 context.type = EmulateInstruction::eContextTableBranchReadMemory;
1896 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success);
1897 if (!success)
1898 return false;
1899
1900 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1901 if (!success)
1902 return false;
1903
1904 // target address
1905 addr_t target = pc + 4 + offset;
1906 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1907 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
1908
1909 if (!BranchWritePC(context, target))
1910 return false;
1911
1912 return true;
1913}
1914
Johnny Chen26863dc2011-02-09 23:43:29 +00001915// ADD <Rdn>, <Rm>
1916// where <Rdn> the destination register is also the first operand register
1917// and <Rm> is the second operand register.
1918bool
1919EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1920{
1921#if 0
1922 // ARM pseudo code...
1923 if ConditionPassed() then
1924 EncodingSpecificOperations();
1925 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1926 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1927 if d == 15 then
1928 ALUWritePC(result); // setflags is always FALSE here
1929 else
1930 R[d] = result;
1931 if setflags then
1932 APSR.N = result<31>;
1933 APSR.Z = IsZeroBit(result);
1934 APSR.C = carry;
1935 APSR.V = overflow;
1936#endif
1937
1938 bool success = false;
1939 const uint32_t opcode = OpcodeAsUnsigned (&success);
1940 if (!success)
1941 return false;
1942
1943 if (ConditionPassed())
1944 {
1945 uint32_t Rd, Rn, Rm;
Johnny Chenca67d1c2011-02-17 01:35:27 +00001946 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00001947 switch (encoding)
1948 {
1949 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00001950 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001951 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00001952 setflags = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001953 if (Rn == 15 && Rm == 15)
1954 return false;
1955 break;
1956 default:
1957 return false;
1958 }
1959
1960 int32_t result, val1, val2;
1961 // Read the first operand.
1962 if (Rn == 15)
1963 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1964 else
1965 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1966 if (!success)
1967 return false;
1968
1969 // Read the second operand.
1970 if (Rm == 15)
1971 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1972 else
1973 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1974 if (!success)
1975 return false;
1976
Johnny Chenca67d1c2011-02-17 01:35:27 +00001977 // TODO: Handle the case where Rm needs to be shifted properly.
1978 AddWithCarryResult res = AddWithCarry(val1, val2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001979 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001980
1981 EmulateInstruction::Context context;
1982 context.type = EmulateInstruction::eContextImmediate;
1983 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001984
1985 if (!WriteCoreRegisterWithFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1986 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001987 }
1988 return true;
1989}
1990
Johnny Chene4a4d302011-02-11 21:53:58 +00001991// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001992bool
1993EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1994{
1995#if 0
1996 // ARM pseudo code...
1997 if ConditionPassed() then
1998 EncodingSpecificOperations();
1999 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2000 APSR.N = result<31>;
2001 APSR.Z = IsZeroBit(result);
2002 APSR.C = carry;
2003 APSR.V = overflow;
2004#endif
2005
2006 bool success = false;
2007 const uint32_t opcode = OpcodeAsUnsigned (&success);
2008 if (!success)
2009 return false;
2010
2011 uint32_t Rn; // the first operand
2012 uint32_t imm32; // the immediate value to be compared with
2013 switch (encoding) {
2014 case eEncodingT1:
2015 Rn = Bits32(opcode, 10, 8);
2016 imm32 = Bits32(opcode, 7, 0);
2017 break;
2018 default:
2019 return false;
2020 }
2021 // Read the register value from the operand register Rn.
2022 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2023 if (!success)
2024 return false;
2025
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002026 EmulateInstruction::Context context;
2027 context.type = EmulateInstruction::eContextImmediate;
2028 context.SetNoArgs ();
2029
Johnny Chend4dc4442011-02-11 02:02:56 +00002030 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2031 m_new_inst_cpsr = m_inst_cpsr;
2032 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2033 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2034 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2035 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2036 if (m_new_inst_cpsr != m_inst_cpsr)
2037 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002038 EmulateInstruction::Context context;
2039 context.type = EmulateInstruction::eContextImmediate;
2040 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002041 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2042 return false;
2043 }
2044 return true;
2045}
2046
Johnny Chene4a4d302011-02-11 21:53:58 +00002047// CMP (register)
2048bool
2049EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2050{
2051#if 0
2052 // ARM pseudo code...
2053 if ConditionPassed() then
2054 EncodingSpecificOperations();
2055 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2056 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2057 APSR.N = result<31>;
2058 APSR.Z = IsZeroBit(result);
2059 APSR.C = carry;
2060 APSR.V = overflow;
2061#endif
2062
2063 bool success = false;
2064 const uint32_t opcode = OpcodeAsUnsigned (&success);
2065 if (!success)
2066 return false;
2067
2068 uint32_t Rn; // the first operand
2069 uint32_t Rm; // the second operand
2070 switch (encoding) {
2071 case eEncodingT1:
2072 Rn = Bits32(opcode, 2, 0);
2073 Rm = Bits32(opcode, 5, 3);
2074 break;
2075 case eEncodingT2:
2076 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2077 Rm = Bits32(opcode, 6, 3);
2078 if (Rn < 8 && Rm < 8)
2079 return false;
2080 if (Rn == 15 || Rm == 15)
2081 return false;
2082 break;
2083 default:
2084 return false;
2085 }
2086 // Read the register value from register Rn.
2087 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2088 if (!success)
2089 return false;
2090 // Read the register value from register Rm.
2091 // The register value is not being shifted since we don't handle ARM for now.
2092 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2093 if (!success)
2094 return false;
2095
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002096 EmulateInstruction::Context context;
2097 context.type = EmulateInstruction::eContextImmediate;
2098 context.SetNoArgs();
2099
Johnny Chene4a4d302011-02-11 21:53:58 +00002100 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2101 m_new_inst_cpsr = m_inst_cpsr;
2102 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2103 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2104 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2105 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2106 if (m_new_inst_cpsr != m_inst_cpsr)
2107 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002108 EmulateInstruction::Context context;
2109 context.type = EmulateInstruction::eContextImmediate;
2110 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002111 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2112 return false;
2113 }
2114 return true;
2115}
2116
Johnny Chen82f16aa2011-02-15 20:10:55 +00002117// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2118// shifting in copies of its sign bit, and writes the result to the destination register. It can
2119// optionally update the condition flags based on the result.
2120bool
2121EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2122{
2123#if 0
2124 // ARM pseudo code...
2125 if ConditionPassed() then
2126 EncodingSpecificOperations();
2127 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2128 if d == 15 then // Can only occur for ARM encoding
2129 ALUWritePC(result); // setflags is always FALSE here
2130 else
2131 R[d] = result;
2132 if setflags then
2133 APSR.N = result<31>;
2134 APSR.Z = IsZeroBit(result);
2135 APSR.C = carry;
2136 // APSR.V unchanged
2137#endif
2138
Johnny Chen41a0a152011-02-16 01:27:54 +00002139 return EmulateShiftImm(encoding, SRType_ASR);
2140}
2141
2142// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2143// shifting in copies of its sign bit, and writes the result to the destination register.
2144// The variable number of bits is read from the bottom byte of a register. It can optionally update
2145// the condition flags based on the result.
2146bool
2147EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2148{
2149#if 0
2150 // ARM pseudo code...
2151 if ConditionPassed() then
2152 EncodingSpecificOperations();
2153 shift_n = UInt(R[m]<7:0>);
2154 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2155 R[d] = result;
2156 if setflags then
2157 APSR.N = result<31>;
2158 APSR.Z = IsZeroBit(result);
2159 APSR.C = carry;
2160 // APSR.V unchanged
2161#endif
2162
2163 return EmulateShiftReg(encoding, SRType_ASR);
2164}
2165
2166// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2167// shifting in zeros, and writes the result to the destination register. It can optionally
2168// update the condition flags based on the result.
2169bool
2170EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2171{
2172#if 0
2173 // ARM pseudo code...
2174 if ConditionPassed() then
2175 EncodingSpecificOperations();
2176 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2177 if d == 15 then // Can only occur for ARM encoding
2178 ALUWritePC(result); // setflags is always FALSE here
2179 else
2180 R[d] = result;
2181 if setflags then
2182 APSR.N = result<31>;
2183 APSR.Z = IsZeroBit(result);
2184 APSR.C = carry;
2185 // APSR.V unchanged
2186#endif
2187
2188 return EmulateShiftImm(encoding, SRType_LSL);
2189}
2190
2191// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2192// shifting in zeros, and writes the result to the destination register. The variable number
2193// of bits is read from the bottom byte of a register. It can optionally update the condition
2194// flags based on the result.
2195bool
2196EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2197{
2198#if 0
2199 // ARM pseudo code...
2200 if ConditionPassed() then
2201 EncodingSpecificOperations();
2202 shift_n = UInt(R[m]<7:0>);
2203 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2204 R[d] = result;
2205 if setflags then
2206 APSR.N = result<31>;
2207 APSR.Z = IsZeroBit(result);
2208 APSR.C = carry;
2209 // APSR.V unchanged
2210#endif
2211
2212 return EmulateShiftReg(encoding, SRType_LSL);
2213}
2214
2215// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2216// shifting in zeros, and writes the result to the destination register. It can optionally
2217// update the condition flags based on the result.
2218bool
2219EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2220{
2221#if 0
2222 // ARM pseudo code...
2223 if ConditionPassed() then
2224 EncodingSpecificOperations();
2225 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2226 if d == 15 then // Can only occur for ARM encoding
2227 ALUWritePC(result); // setflags is always FALSE here
2228 else
2229 R[d] = result;
2230 if setflags then
2231 APSR.N = result<31>;
2232 APSR.Z = IsZeroBit(result);
2233 APSR.C = carry;
2234 // APSR.V unchanged
2235#endif
2236
2237 return EmulateShiftImm(encoding, SRType_LSR);
2238}
2239
2240// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2241// shifting in zeros, and writes the result to the destination register. The variable number
2242// of bits is read from the bottom byte of a register. It can optionally update the condition
2243// flags based on the result.
2244bool
2245EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2246{
2247#if 0
2248 // ARM pseudo code...
2249 if ConditionPassed() then
2250 EncodingSpecificOperations();
2251 shift_n = UInt(R[m]<7:0>);
2252 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2253 R[d] = result;
2254 if setflags then
2255 APSR.N = result<31>;
2256 APSR.Z = IsZeroBit(result);
2257 APSR.C = carry;
2258 // APSR.V unchanged
2259#endif
2260
2261 return EmulateShiftReg(encoding, SRType_LSR);
2262}
2263
Johnny Cheneeab4852011-02-16 22:14:44 +00002264// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2265// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2266// It can optionally update the condition flags based on the result.
2267bool
2268EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2269{
2270#if 0
2271 // ARM pseudo code...
2272 if ConditionPassed() then
2273 EncodingSpecificOperations();
2274 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2275 if d == 15 then // Can only occur for ARM encoding
2276 ALUWritePC(result); // setflags is always FALSE here
2277 else
2278 R[d] = result;
2279 if setflags then
2280 APSR.N = result<31>;
2281 APSR.Z = IsZeroBit(result);
2282 APSR.C = carry;
2283 // APSR.V unchanged
2284#endif
2285
2286 return EmulateShiftImm(encoding, SRType_ROR);
2287}
2288
2289// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2290// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2291// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2292// flags based on the result.
2293bool
2294EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2295{
2296#if 0
2297 // ARM pseudo code...
2298 if ConditionPassed() then
2299 EncodingSpecificOperations();
2300 shift_n = UInt(R[m]<7:0>);
2301 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2302 R[d] = result;
2303 if setflags then
2304 APSR.N = result<31>;
2305 APSR.Z = IsZeroBit(result);
2306 APSR.C = carry;
2307 // APSR.V unchanged
2308#endif
2309
2310 return EmulateShiftReg(encoding, SRType_ROR);
2311}
2312
2313// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2314// with the carry flag shifted into bit [31].
2315//
2316// RRX can optionally update the condition flags based on the result.
2317// In that case, bit [0] is shifted into the carry flag.
2318bool
2319EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2320{
2321#if 0
2322 // ARM pseudo code...
2323 if ConditionPassed() then
2324 EncodingSpecificOperations();
2325 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2326 if d == 15 then // Can only occur for ARM encoding
2327 ALUWritePC(result); // setflags is always FALSE here
2328 else
2329 R[d] = result;
2330 if setflags then
2331 APSR.N = result<31>;
2332 APSR.Z = IsZeroBit(result);
2333 APSR.C = carry;
2334 // APSR.V unchanged
2335#endif
2336
2337 return EmulateShiftImm(encoding, SRType_RRX);
2338}
2339
Johnny Chen41a0a152011-02-16 01:27:54 +00002340bool
2341EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2342{
2343 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2344
Johnny Chen82f16aa2011-02-15 20:10:55 +00002345 bool success = false;
2346 const uint32_t opcode = OpcodeAsUnsigned (&success);
2347 if (!success)
2348 return false;
2349
2350 if (ConditionPassed())
2351 {
Johnny Chene7f89532011-02-15 23:22:46 +00002352 uint32_t Rd; // the destination register
2353 uint32_t Rm; // the first operand register
2354 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002355 uint32_t carry; // the carry bit after the shift operation
2356 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002357
2358 // Special case handling!
2359 // A8.6.139 ROR (immediate) -- Encoding T1
2360 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2361 {
2362 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2363 // have the same decoding of bit fields as the other Thumb2 shift operations.
2364 encoding = eEncodingT2;
2365 }
2366
Johnny Chen82f16aa2011-02-15 20:10:55 +00002367 switch (encoding) {
2368 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002369 // Due to the above special case handling!
2370 assert(shift_type != SRType_ROR);
2371
Johnny Chen82f16aa2011-02-15 20:10:55 +00002372 Rd = Bits32(opcode, 2, 0);
2373 Rm = Bits32(opcode, 5, 3);
2374 setflags = !InITBlock();
2375 imm5 = Bits32(opcode, 10, 6);
2376 break;
2377 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002378 // A8.6.141 RRX
2379 assert(shift_type != SRType_RRX);
2380
Johnny Chen82f16aa2011-02-15 20:10:55 +00002381 Rd = Bits32(opcode, 11, 8);
2382 Rm = Bits32(opcode, 3, 0);
2383 setflags = BitIsSet(opcode, 20);
2384 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2385 if (BadReg(Rd) || BadReg(Rm))
2386 return false;
2387 break;
2388 case eEncodingA1:
2389 Rd = Bits32(opcode, 15, 12);
2390 Rm = Bits32(opcode, 3, 0);
2391 setflags = BitIsSet(opcode, 20);
2392 imm5 = Bits32(opcode, 11, 7);
2393 break;
2394 default:
2395 return false;
2396 }
2397
Johnny Cheneeab4852011-02-16 22:14:44 +00002398 // A8.6.139 ROR (immediate)
2399 if (shift_type == SRType_ROR && imm5 == 0)
2400 shift_type = SRType_RRX;
2401
Johnny Chen82f16aa2011-02-15 20:10:55 +00002402 // Get the first operand.
2403 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2404 if (!success)
2405 return false;
2406
Johnny Cheneeab4852011-02-16 22:14:44 +00002407 // Decode the shift amount if not RRX.
2408 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002409
Johnny Chen41a0a152011-02-16 01:27:54 +00002410 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002411
2412 // The context specifies that an immediate is to be moved into Rd.
2413 EmulateInstruction::Context context;
2414 context.type = EmulateInstruction::eContextImmediate;
2415 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002416
Johnny Chenca67d1c2011-02-17 01:35:27 +00002417 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
2418 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002419 }
2420 return true;
2421}
2422
Johnny Chene7f89532011-02-15 23:22:46 +00002423bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002424EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002425{
Johnny Chen41a0a152011-02-16 01:27:54 +00002426 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002427
2428 bool success = false;
2429 const uint32_t opcode = OpcodeAsUnsigned (&success);
2430 if (!success)
2431 return false;
2432
2433 if (ConditionPassed())
2434 {
2435 uint32_t Rd; // the destination register
2436 uint32_t Rn; // the first operand register
2437 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2438 uint32_t carry; // the carry bit after the shift operation
2439 bool setflags;
2440 switch (encoding) {
2441 case eEncodingT1:
2442 Rd = Bits32(opcode, 2, 0);
2443 Rn = Rd;
2444 Rm = Bits32(opcode, 5, 3);
2445 setflags = !InITBlock();
2446 break;
2447 case eEncodingT2:
2448 Rd = Bits32(opcode, 11, 8);
2449 Rn = Bits32(opcode, 19, 16);
2450 Rm = Bits32(opcode, 3, 0);
2451 setflags = BitIsSet(opcode, 20);
2452 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2453 return false;
2454 break;
2455 case eEncodingA1:
2456 Rd = Bits32(opcode, 15, 12);
2457 Rn = Bits32(opcode, 3, 0);
2458 Rm = Bits32(opcode, 11, 8);
2459 setflags = BitIsSet(opcode, 20);
2460 if (Rd == 15 || Rn == 15 || Rm == 15)
2461 return false;
2462 break;
2463 default:
2464 return false;
2465 }
2466
2467 // Get the first operand.
2468 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2469 if (!success)
2470 return false;
2471 // Get the Rm register content.
2472 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2473 if (!success)
2474 return false;
2475
2476 // Get the shift amount.
2477 uint32_t amt = Bits32(val, 7, 0);
2478
Johnny Chen41a0a152011-02-16 01:27:54 +00002479 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002480
2481 // The context specifies that an immediate is to be moved into Rd.
2482 EmulateInstruction::Context context;
2483 context.type = EmulateInstruction::eContextImmediate;
2484 context.SetNoArgs ();
2485
Johnny Chenca67d1c2011-02-17 01:35:27 +00002486 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002487 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002488 }
2489 return true;
2490}
2491
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002492// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002493// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002494// can be written back to the base register.
2495bool
2496EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2497{
2498#if 0
2499 // ARM pseudo code...
2500 if ConditionPassed()
2501 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2502 address = R[n];
2503
2504 for i = 0 to 14
2505 if registers<i> == '1' then
2506 R[i] = MemA[address, 4]; address = address + 4;
2507 if registers<15> == '1' then
2508 LoadWritePC (MemA[address, 4]);
2509
2510 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2511 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2512
2513#endif
2514
2515 bool success = false;
2516 const uint32_t opcode = OpcodeAsUnsigned (&success);
2517 if (!success)
2518 return false;
2519
2520 if (ConditionPassed())
2521 {
2522 uint32_t n;
2523 uint32_t registers = 0;
2524 bool wback;
2525 const uint32_t addr_byte_size = GetAddressByteSize();
2526 switch (encoding)
2527 {
2528 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002529 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002530 n = Bits32 (opcode, 10, 8);
2531 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002532 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002533 wback = BitIsClear (registers, n);
2534 // if BitCount(registers) < 1 then UNPREDICTABLE;
2535 if (BitCount(registers) < 1)
2536 return false;
2537 break;
2538 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002539 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2540 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002541 n = Bits32 (opcode, 19, 16);
2542 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002543 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002544 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002545
2546 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002547 if ((n == 15)
2548 || (BitCount (registers) < 2)
2549 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2550 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002551
2552 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002553 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002554 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002555
2556 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002557 if (wback
2558 && BitIsSet (registers, n))
2559 return false;
2560 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002561
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002562 case eEncodingA1:
2563 n = Bits32 (opcode, 19, 16);
2564 registers = Bits32 (opcode, 15, 0);
2565 wback = BitIsSet (opcode, 21);
2566 if ((n == 15)
2567 || (BitCount (registers) < 1))
2568 return false;
2569 break;
2570 default:
2571 return false;
2572 }
2573
2574 int32_t offset = 0;
2575 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2576 if (!success)
2577 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002578
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002579 EmulateInstruction::Context context;
2580 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2581 Register dwarf_reg;
2582 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2583 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002584
2585 for (int i = 0; i < 14; ++i)
2586 {
2587 if (BitIsSet (registers, i))
2588 {
Caroline Tice85aab332011-02-08 23:56:10 +00002589 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002590 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002591 if (wback && (n == 13)) // Pop Instruction
2592 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2593
2594 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002595 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002596 if (!success)
2597 return false;
2598
2599 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2600 return false;
2601
2602 offset += addr_byte_size;
2603 }
2604 }
2605
2606 if (BitIsSet (registers, 15))
2607 {
2608 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002609 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002610 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002611 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002612 if (!success)
2613 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002614 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002615 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002616 return false;
2617 }
2618
2619 if (wback && BitIsClear (registers, n))
2620 {
Caroline Ticefa172202011-02-11 22:49:54 +00002621 // R[n] = R[n] + 4 * BitCount (registers)
2622 int32_t offset = addr_byte_size * BitCount (registers);
2623 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002624 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002625
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002626 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2627 return false;
2628 }
2629 if (wback && BitIsSet (registers, n))
2630 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002631 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002632 }
2633 return true;
2634}
Caroline Tice713c2662011-02-11 17:59:55 +00002635
2636// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2637// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2638// can optionally be written back tot he base registers.
2639bool
2640EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2641{
2642#if 0
2643 // ARM pseudo code...
2644 if ConditionPassed() then
2645 EncodingSpecificOperations();
2646 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002647
Caroline Tice713c2662011-02-11 17:59:55 +00002648 for i = 0 to 14
2649 if registers<i> == ’1’ then
2650 R[i] = MemA[address,4]; address = address + 4;
2651
2652 if registers<15> == ’1’ then
2653 LoadWritePC(MemA[address,4]);
2654
2655 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2656 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2657#endif
2658
2659 bool success = false;
2660 const uint32_t opcode = OpcodeAsUnsigned (&success);
2661 if (!success)
2662 return false;
2663
2664 if (ConditionPassed())
2665 {
2666 uint32_t n;
2667 uint32_t registers = 0;
2668 bool wback;
2669 const uint32_t addr_byte_size = GetAddressByteSize();
2670
2671 // EncodingSpecificOperations();
2672 switch (encoding)
2673 {
2674 case eEncodingA1:
2675 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2676 n = Bits32 (opcode, 19, 16);
2677 registers = Bits32 (opcode, 15, 0);
2678 wback = BitIsSet (opcode, 21);
2679
2680 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2681 if ((n == 15) || (BitCount (registers) < 1))
2682 return false;
2683
2684 break;
2685
2686 default:
2687 return false;
2688 }
2689 // address = R[n] - 4*BitCount(registers) + 4;
2690
2691 int32_t offset = 0;
2692 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2693
2694 if (!success)
2695 return false;
2696
2697 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2698
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002699 EmulateInstruction::Context context;
2700 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2701 Register dwarf_reg;
2702 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2703 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002704
2705 // for i = 0 to 14
2706 for (int i = 0; i < 14; ++i)
2707 {
2708 // if registers<i> == ’1’ then
2709 if (BitIsSet (registers, i))
2710 {
2711 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002712 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002713 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002714 if (!success)
2715 return false;
2716 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2717 return false;
2718 offset += addr_byte_size;
2719 }
2720 }
2721
2722 // if registers<15> == ’1’ then
2723 // LoadWritePC(MemA[address,4]);
2724 if (BitIsSet (registers, 15))
2725 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002726 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002727 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002728 if (!success)
2729 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002730 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002731 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002732 return false;
2733 }
2734
2735 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2736 if (wback && BitIsClear (registers, n))
2737 {
Caroline Tice713c2662011-02-11 17:59:55 +00002738 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2739 if (!success)
2740 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002741
2742 offset = (addr_byte_size * BitCount (registers)) * -1;
2743 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002744 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002745 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2747 return false;
2748 }
2749
2750 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2751 if (wback && BitIsSet (registers, n))
2752 return WriteBits32Unknown (n);
2753 }
2754 return true;
2755}
2756
2757// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2758// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2759// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002760bool
2761EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2762{
2763#if 0
2764 // ARM pseudo code...
2765 if ConditionPassed() then
2766 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2767 address = R[n] - 4*BitCount(registers);
2768
2769 for i = 0 to 14
2770 if registers<i> == ’1’ then
2771 R[i] = MemA[address,4]; address = address + 4;
2772 if registers<15> == ’1’ then
2773 LoadWritePC(MemA[address,4]);
2774
2775 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2776 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2777#endif
2778
2779 bool success = false;
2780 const uint32_t opcode = OpcodeAsUnsigned (&success);
2781 if (!success)
2782 return false;
2783
2784 if (ConditionPassed())
2785 {
2786 uint32_t n;
2787 uint32_t registers = 0;
2788 bool wback;
2789 const uint32_t addr_byte_size = GetAddressByteSize();
2790 switch (encoding)
2791 {
2792 case eEncodingT1:
2793 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2794 n = Bits32 (opcode, 19, 16);
2795 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002796 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002797 wback = BitIsSet (opcode, 21);
2798
2799 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2800 if ((n == 15)
2801 || (BitCount (registers) < 2)
2802 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2803 return false;
2804
2805 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002806 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002807 return false;
2808
2809 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2810 if (wback && BitIsSet (registers, n))
2811 return false;
2812
2813 break;
2814
2815 case eEncodingA1:
2816 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2817 n = Bits32 (opcode, 19, 16);
2818 registers = Bits32 (opcode, 15, 0);
2819 wback = BitIsSet (opcode, 21);
2820
2821 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2822 if ((n == 15) || (BitCount (registers) < 1))
2823 return false;
2824
2825 break;
2826
2827 default:
2828 return false;
2829 }
2830
Caroline Tice713c2662011-02-11 17:59:55 +00002831 // address = R[n] - 4*BitCount(registers);
2832
Caroline Tice0b29e242011-02-08 23:16:02 +00002833 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002834 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2835
2836 if (!success)
2837 return false;
2838
2839 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002840 EmulateInstruction::Context context;
2841 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2842 Register dwarf_reg;
2843 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2844 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002845
2846 for (int i = 0; i < 14; ++i)
2847 {
2848 if (BitIsSet (registers, i))
2849 {
2850 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002851 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002852 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002853 if (!success)
2854 return false;
2855
2856 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2857 return false;
2858
2859 offset += addr_byte_size;
2860 }
2861 }
2862
2863 // if registers<15> == ’1’ then
2864 // LoadWritePC(MemA[address,4]);
2865 if (BitIsSet (registers, 15))
2866 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002867 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002868 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002869 if (!success)
2870 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002871 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002872 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002873 return false;
2874 }
2875
2876 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2877 if (wback && BitIsClear (registers, n))
2878 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002879 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2880 if (!success)
2881 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002882
2883 offset = (addr_byte_size * BitCount (registers)) * -1;
2884 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002885 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002886 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002887 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2888 return false;
2889 }
2890
2891 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2892 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002893 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002894 }
2895 return true;
2896}
Caroline Tice85aab332011-02-08 23:56:10 +00002897
Caroline Tice713c2662011-02-11 17:59:55 +00002898// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2899// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2900// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002901bool
2902EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2903{
2904#if 0
2905 if ConditionPassed() then
2906 EncodingSpecificOperations();
2907 address = R[n] + 4;
2908
2909 for i = 0 to 14
2910 if registers<i> == ’1’ then
2911 R[i] = MemA[address,4]; address = address + 4;
2912 if registers<15> == ’1’ then
2913 LoadWritePC(MemA[address,4]);
2914
2915 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2916 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2917#endif
2918
2919 bool success = false;
2920 const uint32_t opcode = OpcodeAsUnsigned (&success);
2921 if (!success)
2922 return false;
2923
2924 if (ConditionPassed())
2925 {
2926 uint32_t n;
2927 uint32_t registers = 0;
2928 bool wback;
2929 const uint32_t addr_byte_size = GetAddressByteSize();
2930 switch (encoding)
2931 {
2932 case eEncodingA1:
2933 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2934 n = Bits32 (opcode, 19, 16);
2935 registers = Bits32 (opcode, 15, 0);
2936 wback = BitIsSet (opcode, 21);
2937
2938 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2939 if ((n == 15) || (BitCount (registers) < 1))
2940 return false;
2941
2942 break;
2943 default:
2944 return false;
2945 }
2946 // address = R[n] + 4;
2947
2948 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002949 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2950
2951 if (!success)
2952 return false;
2953
2954 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002955
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002956 EmulateInstruction::Context context;
2957 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2958 Register dwarf_reg;
2959 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2960 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002961
2962 for (int i = 0; i < 14; ++i)
2963 {
2964 if (BitIsSet (registers, i))
2965 {
2966 // R[i] = MemA[address,4]; address = address + 4;
2967
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002968 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002969 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002970 if (!success)
2971 return false;
2972
2973 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2974 return false;
2975
2976 offset += addr_byte_size;
2977 }
2978 }
2979
2980 // if registers<15> == ’1’ then
2981 // LoadWritePC(MemA[address,4]);
2982 if (BitIsSet (registers, 15))
2983 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002984 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002985 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002986 if (!success)
2987 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002988 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002989 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002990 return false;
2991 }
2992
2993 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2994 if (wback && BitIsClear (registers, n))
2995 {
Caroline Tice85aab332011-02-08 23:56:10 +00002996 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2997 if (!success)
2998 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002999
3000 offset = addr_byte_size * BitCount (registers);
3001 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003002 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003003 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003004 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3005 return false;
3006 }
3007
3008 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3009 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003010 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003011 }
3012 return true;
3013}
Caroline Tice0b29e242011-02-08 23:16:02 +00003014
Johnny Chenef21b592011-02-10 01:52:38 +00003015// Load Register (immediate) calculates an address from a base register value and
3016// an immediate offset, loads a word from memory, and writes to a register.
3017// LDR (immediate, Thumb)
3018bool
3019EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3020{
3021#if 0
3022 // ARM pseudo code...
3023 if (ConditionPassed())
3024 {
3025 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3026 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3027 address = if index then offset_addr else R[n];
3028 data = MemU[address,4];
3029 if wback then R[n] = offset_addr;
3030 if t == 15 then
3031 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3032 elsif UnalignedSupport() || address<1:0> = '00' then
3033 R[t] = data;
3034 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3035 }
3036#endif
3037
3038 bool success = false;
3039 const uint32_t opcode = OpcodeAsUnsigned (&success);
3040 if (!success)
3041 return false;
3042
3043 if (ConditionPassed())
3044 {
3045 uint32_t Rt; // the destination register
3046 uint32_t Rn; // the base register
3047 uint32_t imm32; // the immediate offset used to form the address
3048 addr_t offset_addr; // the offset address
3049 addr_t address; // the calculated address
3050 uint32_t data; // the literal data value from memory load
3051 bool add, index, wback;
3052 switch (encoding) {
3053 case eEncodingT1:
3054 Rt = Bits32(opcode, 5, 3);
3055 Rn = Bits32(opcode, 2, 0);
3056 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3057 // index = TRUE; add = TRUE; wback = FALSE
3058 add = true;
3059 index = true;
3060 wback = false;
3061 break;
3062 default:
3063 return false;
3064 }
3065 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3066 if (!success)
3067 return false;
3068 if (add)
3069 offset_addr = base + imm32;
3070 else
3071 offset_addr = base - imm32;
3072
3073 address = (index ? offset_addr : base);
3074
3075 if (wback)
3076 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003077 EmulateInstruction::Context ctx;
3078 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3079 Register dwarf_reg;
3080 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3081 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3082
Johnny Chenef21b592011-02-10 01:52:38 +00003083 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3084 return false;
3085 }
3086
3087 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003088 EmulateInstruction::Context context;
3089 context.type = EmulateInstruction::eContextImmediate;
3090 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003091
3092 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003093 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003094 if (!success)
3095 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003096
3097 if (Rt == 15)
3098 {
3099 if (Bits32(address, 1, 0) == 0)
3100 {
Johnny Chen668b4512011-02-15 21:08:58 +00003101 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003102 return false;
3103 }
3104 else
3105 return false;
3106 }
3107 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3108 {
3109 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3110 return false;
3111 }
3112 else
3113 return false;
3114 }
3115 return true;
3116}
3117
Caroline Ticeaf556562011-02-15 18:42:15 +00003118// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3119// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3120// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003121bool
3122EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3123{
3124#if 0
3125 if ConditionPassed() then
3126 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3127 address = R[n];
3128
3129 for i = 0 to 14
3130 if registers<i> == ’1’ then
3131 if i == n && wback && i != LowestSetBit(registers) then
3132 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3133 else
3134 MemA[address,4] = R[i];
3135 address = address + 4;
3136
3137 if registers<15> == ’1’ then // Only possible for encoding A1
3138 MemA[address,4] = PCStoreValue();
3139 if wback then R[n] = R[n] + 4*BitCount(registers);
3140#endif
3141
3142 bool success = false;
3143 const uint32_t opcode = OpcodeAsUnsigned (&success);
3144 if (!success)
3145 return false;
3146
3147 if (ConditionPassed ())
3148 {
3149 uint32_t n;
3150 uint32_t registers = 0;
3151 bool wback;
3152 const uint32_t addr_byte_size = GetAddressByteSize();
3153
3154 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3155 switch (encoding)
3156 {
3157 case eEncodingT1:
3158 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3159 n = Bits32 (opcode, 10, 8);
3160 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003161 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003162 wback = true;
3163
3164 // if BitCount(registers) < 1 then UNPREDICTABLE;
3165 if (BitCount (registers) < 1)
3166 return false;
3167
3168 break;
3169
3170 case eEncodingT2:
3171 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3172 n = Bits32 (opcode, 19, 16);
3173 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003174 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003175 wback = BitIsSet (opcode, 21);
3176
3177 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3178 if ((n == 15) || (BitCount (registers) < 2))
3179 return false;
3180
3181 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3182 if (wback && BitIsSet (registers, n))
3183 return false;
3184
3185 break;
3186
3187 case eEncodingA1:
3188 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3189 n = Bits32 (opcode, 19, 16);
3190 registers = Bits32 (opcode, 15, 0);
3191 wback = BitIsSet (opcode, 21);
3192
3193 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3194 if ((n == 15) || (BitCount (registers) < 1))
3195 return false;
3196
3197 break;
3198
3199 default:
3200 return false;
3201 }
3202
3203 // address = R[n];
3204 int32_t offset = 0;
3205 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3206 if (!success)
3207 return false;
3208
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003209 EmulateInstruction::Context context;
3210 context.type = EmulateInstruction::eContextRegisterStore;
3211 Register base_reg;
3212 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003213
3214 // for i = 0 to 14
3215 for (int i = 0; i < 14; ++i)
3216 {
3217 int lowest_set_bit = 14;
3218 // if registers<i> == ’1’ then
3219 if (BitIsSet (registers, i))
3220 {
3221 if (i < lowest_set_bit)
3222 lowest_set_bit = i;
3223 // if i == n && wback && i != LowestSetBit(registers) then
3224 if ((i == n) && wback && (i != lowest_set_bit))
3225 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3226 WriteBits32UnknownToMemory (address + offset);
3227 else
3228 {
3229 // MemA[address,4] = R[i];
3230 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3231 if (!success)
3232 return false;
3233
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003234 Register data_reg;
3235 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3236 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003237 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003238 return false;
3239 }
3240
3241 // address = address + 4;
3242 offset += addr_byte_size;
3243 }
3244 }
3245
3246 // if registers<15> == ’1’ then // Only possible for encoding A1
3247 // MemA[address,4] = PCStoreValue();
3248 if (BitIsSet (registers, 15))
3249 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003250 Register pc_reg;
3251 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3252 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003253 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3254 if (!success)
3255 return false;
3256
Caroline Ticecc96eb52011-02-17 19:20:40 +00003257 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003258 return false;
3259 }
3260
3261 // if wback then R[n] = R[n] + 4*BitCount(registers);
3262 if (wback)
3263 {
3264 offset = addr_byte_size * BitCount (registers);
3265 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003266 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003267 addr_t data = address + offset;
3268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3269 return false;
3270 }
3271 }
3272 return true;
3273}
3274
Caroline Ticeaf556562011-02-15 18:42:15 +00003275// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3276// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3277// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003278bool
3279EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3280{
3281#if 0
3282 if ConditionPassed() then
3283 EncodingSpecificOperations();
3284 address = R[n] - 4*BitCount(registers) + 4;
3285
3286 for i = 0 to 14
3287 if registers<i> == ’1’ then
3288 if i == n && wback && i != LowestSetBit(registers) then
3289 MemA[address,4] = bits(32) UNKNOWN;
3290 else
3291 MemA[address,4] = R[i];
3292 address = address + 4;
3293
3294 if registers<15> == ’1’ then
3295 MemA[address,4] = PCStoreValue();
3296
3297 if wback then R[n] = R[n] - 4*BitCount(registers);
3298#endif
3299
3300 bool success = false;
3301 const uint32_t opcode = OpcodeAsUnsigned (&success);
3302 if (!success)
3303 return false;
3304
3305 if (ConditionPassed ())
3306 {
3307 uint32_t n;
3308 uint32_t registers = 0;
3309 bool wback;
3310 const uint32_t addr_byte_size = GetAddressByteSize();
3311
3312 // EncodingSpecificOperations();
3313 switch (encoding)
3314 {
3315 case eEncodingA1:
3316 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3317 n = Bits32 (opcode, 19, 16);
3318 registers = Bits32 (opcode, 15, 0);
3319 wback = BitIsSet (opcode, 21);
3320
3321 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3322 if ((n == 15) || (BitCount (registers) < 1))
3323 return false;
3324 break;
3325 default:
3326 return false;
3327 }
3328
3329 // address = R[n] - 4*BitCount(registers) + 4;
3330 int32_t offset = 0;
3331 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3332 if (!success)
3333 return false;
3334
3335 address = address - (addr_byte_size * BitCount (registers)) + 4;
3336
3337 EmulateInstruction::Context context;
3338 context.type = EmulateInstruction::eContextRegisterStore;
3339 Register base_reg;
3340 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3341
3342 // for i = 0 to 14
3343 for (int i = 0; i < 14; ++i)
3344 {
3345 int lowest_bit_set = 14;
3346 // if registers<i> == ’1’ then
3347 if (BitIsSet (registers, i))
3348 {
3349 if (i < lowest_bit_set)
3350 lowest_bit_set = i;
3351 //if i == n && wback && i != LowestSetBit(registers) then
3352 if ((i == n) && wback && (i != lowest_bit_set))
3353 // MemA[address,4] = bits(32) UNKNOWN;
3354 WriteBits32UnknownToMemory (address + offset);
3355 else
3356 {
3357 // MemA[address,4] = R[i];
3358 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3359 if (!success)
3360 return false;
3361
3362 Register data_reg;
3363 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3364 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003365 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003366 return false;
3367 }
3368
3369 // address = address + 4;
3370 offset += addr_byte_size;
3371 }
3372 }
3373
3374 // if registers<15> == ’1’ then
3375 // MemA[address,4] = PCStoreValue();
3376 if (BitIsSet (registers, 15))
3377 {
3378 Register pc_reg;
3379 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3380 context.SetRegisterPlusOffset (pc_reg, 8);
3381 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3382 if (!success)
3383 return false;
3384
Caroline Ticecc96eb52011-02-17 19:20:40 +00003385 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003386 return false;
3387 }
3388
3389 // if wback then R[n] = R[n] - 4*BitCount(registers);
3390 if (wback)
3391 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003392 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003393 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3394 context.SetImmediateSigned (offset);
3395 addr_t data = address + offset;
3396 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3397 return false;
3398 }
3399 }
3400 return true;
3401}
3402
Caroline Ticeaf556562011-02-15 18:42:15 +00003403// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3404// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3405// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003406bool
3407EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3408{
3409#if 0
3410 if ConditionPassed() then
3411 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3412 address = R[n] - 4*BitCount(registers);
3413
3414 for i = 0 to 14
3415 if registers<i> == ’1’ then
3416 if i == n && wback && i != LowestSetBit(registers) then
3417 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3418 else
3419 MemA[address,4] = R[i];
3420 address = address + 4;
3421
3422 if registers<15> == ’1’ then // Only possible for encoding A1
3423 MemA[address,4] = PCStoreValue();
3424
3425 if wback then R[n] = R[n] - 4*BitCount(registers);
3426#endif
3427
3428
3429 bool success = false;
3430 const uint32_t opcode = OpcodeAsUnsigned (&success);
3431 if (!success)
3432 return false;
3433
3434 if (ConditionPassed ())
3435 {
3436 uint32_t n;
3437 uint32_t registers = 0;
3438 bool wback;
3439 const uint32_t addr_byte_size = GetAddressByteSize();
3440
3441 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3442 switch (encoding)
3443 {
3444 case eEncodingT1:
3445 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3446 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3447 {
3448 // See PUSH
3449 }
3450 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3451 n = Bits32 (opcode, 19, 16);
3452 registers = Bits32 (opcode, 15, 0);
3453 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3454 wback = BitIsSet (opcode, 21);
3455 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3456 if ((n == 15) || BitCount (registers) < 2)
3457 return false;
3458 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3459 if (wback && BitIsSet (registers, n))
3460 return false;
3461 break;
3462
3463 case eEncodingA1:
3464 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3465 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3466 {
3467 // See Push
3468 }
3469 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3470 n = Bits32 (opcode, 19, 16);
3471 registers = Bits32 (opcode, 15, 0);
3472 wback = BitIsSet (opcode, 21);
3473 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3474 if ((n == 15) || BitCount (registers) < 1)
3475 return false;
3476 break;
3477
3478 default:
3479 return false;
3480 }
3481
3482 // address = R[n] - 4*BitCount(registers);
3483
3484 int32_t offset = 0;
3485 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3486 if (!success)
3487 return false;
3488
3489 address = address - (addr_byte_size * BitCount (registers));
3490
3491 EmulateInstruction::Context context;
3492 context.type = EmulateInstruction::eContextRegisterStore;
3493 Register base_reg;
3494 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3495
3496 // for i = 0 to 14
3497 for (int i = 0; i < 14; ++i)
3498 {
3499 uint32_t lowest_set_bit = 14;
3500 // if registers<i> == ’1’ then
3501 if (BitIsSet (registers, i))
3502 {
3503 if (i < lowest_set_bit)
3504 lowest_set_bit = i;
3505 // if i == n && wback && i != LowestSetBit(registers) then
3506 if ((i == n) && wback && (i != lowest_set_bit))
3507 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3508 WriteBits32UnknownToMemory (address + offset);
3509 else
3510 {
3511 // MemA[address,4] = R[i];
3512 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3513 if (!success)
3514 return false;
3515
3516 Register data_reg;
3517 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3518 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003519 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003520 return false;
3521 }
3522
3523 // address = address + 4;
3524 offset += addr_byte_size;
3525 }
3526 }
3527
3528 // if registers<15> == ’1’ then // Only possible for encoding A1
3529 // MemA[address,4] = PCStoreValue();
3530 if (BitIsSet (registers, 15))
3531 {
3532 Register pc_reg;
3533 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3534 context.SetRegisterPlusOffset (pc_reg, 8);
3535 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3536 if (!success)
3537 return false;
3538
Caroline Ticecc96eb52011-02-17 19:20:40 +00003539 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003540 return false;
3541 }
3542
3543 // if wback then R[n] = R[n] - 4*BitCount(registers);
3544 if (wback)
3545 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003546 offset = (addr_byte_size * BitCount (registers)) * -1;
3547 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3548 context.SetImmediateSigned (offset);
3549 addr_t data = address + offset;
3550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3551 return false;
3552 }
3553 }
3554 return true;
3555}
3556
3557// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3558// from a base register. The consecutive memory locations start just above this address, and the address of the last
3559// of those locations can optionally be written back to the base register.
3560bool
3561EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3562{
3563#if 0
3564 if ConditionPassed() then
3565 EncodingSpecificOperations();
3566 address = R[n] + 4;
3567
3568 for i = 0 to 14
3569 if registers<i> == ’1’ then
3570 if i == n && wback && i != LowestSetBit(registers) then
3571 MemA[address,4] = bits(32) UNKNOWN;
3572 else
3573 MemA[address,4] = R[i];
3574 address = address + 4;
3575
3576 if registers<15> == ’1’ then
3577 MemA[address,4] = PCStoreValue();
3578
3579 if wback then R[n] = R[n] + 4*BitCount(registers);
3580#endif
3581
3582 bool success = false;
3583 const uint32_t opcode = OpcodeAsUnsigned (&success);
3584 if (!success)
3585 return false;
3586
3587 if (ConditionPassed())
3588 {
3589 uint32_t n;
3590 uint32_t registers = 0;
3591 bool wback;
3592 const uint32_t addr_byte_size = GetAddressByteSize();
3593
3594 // EncodingSpecificOperations();
3595 switch (encoding)
3596 {
3597 case eEncodingA1:
3598 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3599 n = Bits32 (opcode, 19, 16);
3600 registers = Bits32 (opcode, 15, 0);
3601 wback = BitIsSet (opcode, 21);
3602
3603 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3604 if ((n == 15) && (BitCount (registers) < 1))
3605 return false;
3606 break;
3607 default:
3608 return false;
3609 }
3610 // address = R[n] + 4;
3611
3612 int32_t offset = 0;
3613 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3614 if (!success)
3615 return false;
3616
3617 address = address + addr_byte_size;
3618
3619 EmulateInstruction::Context context;
3620 context.type = EmulateInstruction::eContextRegisterStore;
3621 Register base_reg;
3622 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3623
3624 uint32_t lowest_set_bit = 14;
3625 // for i = 0 to 14
3626 for (int i = 0; i < 14; ++i)
3627 {
3628 // if registers<i> == ’1’ then
3629 if (BitIsSet (registers, i))
3630 {
3631 if (i < lowest_set_bit)
3632 lowest_set_bit = i;
3633 // if i == n && wback && i != LowestSetBit(registers) then
3634 if ((i == n) && wback && (i != lowest_set_bit))
3635 // MemA[address,4] = bits(32) UNKNOWN;
3636 WriteBits32UnknownToMemory (address + offset);
3637 // else
3638 else
3639 {
3640 // MemA[address,4] = R[i];
3641 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3642 if (!success)
3643 return false;
3644
3645 Register data_reg;
3646 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3647 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003648 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003649 return false;
3650 }
3651
3652 // address = address + 4;
3653 offset += addr_byte_size;
3654 }
3655 }
3656
3657 // if registers<15> == ’1’ then
3658 // MemA[address,4] = PCStoreValue();
3659 if (BitIsSet (registers, 15))
3660 {
3661 Register pc_reg;
3662 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3663 context.SetRegisterPlusOffset (pc_reg, 8);
3664 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3665 if (!success)
3666 return false;
3667
Caroline Ticecc96eb52011-02-17 19:20:40 +00003668 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003669 return false;
3670 }
3671
3672 // if wback then R[n] = R[n] + 4*BitCount(registers);
3673 if (wback)
3674 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003675 offset = addr_byte_size * BitCount (registers);
3676 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3677 context.SetImmediateSigned (offset);
3678 addr_t data = address + offset;
3679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3680 return false;
3681 }
3682 }
3683 return true;
3684}
Caroline Tice7fac8572011-02-15 22:53:54 +00003685
3686// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3687// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3688bool
3689EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3690{
3691#if 0
3692 if ConditionPassed() then
3693 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3694 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3695 address = if index then offset_addr else R[n];
3696 if UnalignedSupport() || address<1:0> == ’00’ then
3697 MemU[address,4] = R[t];
3698 else // Can only occur before ARMv7
3699 MemU[address,4] = bits(32) UNKNOWN;
3700 if wback then R[n] = offset_addr;
3701#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003702
Caroline Tice7fac8572011-02-15 22:53:54 +00003703 bool success = false;
3704 const uint32_t opcode = OpcodeAsUnsigned (&success);
3705 if (!success)
3706 return false;
3707
3708 if (ConditionPassed())
3709 {
3710 const uint32_t addr_byte_size = GetAddressByteSize();
3711
3712 uint32_t t;
3713 uint32_t n;
3714 uint32_t imm32;
3715 bool index;
3716 bool add;
3717 bool wback;
3718 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3719 switch (encoding)
3720 {
3721 case eEncodingT1:
3722 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3723 t = Bits32 (opcode, 2, 0);
3724 n = Bits32 (opcode, 5, 3);
3725 imm32 = Bits32 (opcode, 10, 6) << 2;
3726
3727 // index = TRUE; add = TRUE; wback = FALSE;
3728 index = true;
3729 add = false;
3730 wback = false;
3731 break;
3732
3733 case eEncodingT2:
3734 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3735 t = Bits32 (opcode, 10, 8);
3736 n = 13;
3737 imm32 = Bits32 (opcode, 7, 0) << 2;
3738
3739 // index = TRUE; add = TRUE; wback = FALSE;
3740 index = true;
3741 add = true;
3742 wback = false;
3743 break;
3744
3745 case eEncodingT3:
3746 // if Rn == ’1111’ then UNDEFINED;
3747 if (Bits32 (opcode, 19, 16) == 15)
3748 return false;
3749
3750 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3751 t = Bits32 (opcode, 15, 12);
3752 n = Bits32 (opcode, 19, 16);
3753 imm32 = Bits32 (opcode, 11, 0);
3754
3755 // index = TRUE; add = TRUE; wback = FALSE;
3756 index = true;
3757 add = true;
3758 wback = false;
3759
3760 // if t == 15 then UNPREDICTABLE;
3761 if (t == 15)
3762 return false;
3763 break;
3764
3765 case eEncodingT4:
3766 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3767 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3768 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3769 if ((Bits32 (opcode, 19, 16) == 15)
3770 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3771 return false;
3772
3773 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3774 t = Bits32 (opcode, 15, 12);
3775 n = Bits32 (opcode, 19, 16);
3776 imm32 = Bits32 (opcode, 7, 0);
3777
3778 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3779 index = BitIsSet (opcode, 10);
3780 add = BitIsSet (opcode, 9);
3781 wback = BitIsSet (opcode, 8);
3782
3783 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3784 if ((t == 15) || (wback && (n == t)))
3785 return false;
3786 break;
3787
3788 default:
3789 return false;
3790 }
3791
3792 addr_t offset_addr;
3793 addr_t address;
3794
3795 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3796 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3797 if (!success)
3798 return false;
3799
3800 if (add)
3801 offset_addr = base_address + imm32;
3802 else
3803 offset_addr = base_address - imm32;
3804
3805 // address = if index then offset_addr else R[n];
3806 if (index)
3807 address = offset_addr;
3808 else
3809 address = base_address;
3810
3811 EmulateInstruction::Context context;
3812 context.type = eContextRegisterStore;
3813 Register base_reg;
3814 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3815
3816 // if UnalignedSupport() || address<1:0> == ’00’ then
3817 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3818 {
3819 // MemU[address,4] = R[t];
3820 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3821 if (!success)
3822 return false;
3823
3824 Register data_reg;
3825 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3826 int32_t offset = address - base_address;
3827 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003828 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003829 return false;
3830 }
3831 else
3832 {
3833 // MemU[address,4] = bits(32) UNKNOWN;
3834 WriteBits32UnknownToMemory (address);
3835 }
3836
3837 // if wback then R[n] = offset_addr;
3838 if (wback)
3839 {
3840 context.type = eContextRegisterLoad;
3841 context.SetAddress (offset_addr);
3842 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3843 return false;
3844 }
3845 }
3846 return true;
3847}
Caroline Ticeaf556562011-02-15 18:42:15 +00003848
Caroline Tice3fd63e92011-02-16 00:33:43 +00003849// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3850// word from a register to memory. The offset register value can optionally be shifted.
3851bool
3852EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3853{
3854#if 0
3855 if ConditionPassed() then
3856 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3857 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3858 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3859 address = if index then offset_addr else R[n];
3860 if t == 15 then // Only possible for encoding A1
3861 data = PCStoreValue();
3862 else
3863 data = R[t];
3864 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3865 MemU[address,4] = data;
3866 else // Can only occur before ARMv7
3867 MemU[address,4] = bits(32) UNKNOWN;
3868 if wback then R[n] = offset_addr;
3869#endif
3870
3871 bool success = false;
3872 const uint32_t opcode = OpcodeAsUnsigned (&success);
3873 if (!success)
3874 return false;
3875
3876 if (ConditionPassed())
3877 {
3878 const uint32_t addr_byte_size = GetAddressByteSize();
3879
3880 uint32_t t;
3881 uint32_t n;
3882 uint32_t m;
3883 ARM_ShifterType shift_t;
3884 uint32_t shift_n;
3885 bool index;
3886 bool add;
3887 bool wback;
3888
3889 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3890 switch (encoding)
3891 {
3892 case eEncodingT1:
3893 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3894 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3895 t = Bits32 (opcode, 2, 0);
3896 n = Bits32 (opcode, 5, 3);
3897 m = Bits32 (opcode, 8, 6);
3898
3899 // index = TRUE; add = TRUE; wback = FALSE;
3900 index = true;
3901 add = true;
3902 wback = false;
3903
3904 // (shift_t, shift_n) = (SRType_LSL, 0);
3905 shift_t = SRType_LSL;
3906 shift_n = 0;
3907 break;
3908
3909 case eEncodingT2:
3910 // if Rn == ’1111’ then UNDEFINED;
3911 if (Bits32 (opcode, 19, 16) == 15)
3912 return false;
3913
3914 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3915 t = Bits32 (opcode, 15, 12);
3916 n = Bits32 (opcode, 19, 16);
3917 m = Bits32 (opcode, 3, 0);
3918
3919 // index = TRUE; add = TRUE; wback = FALSE;
3920 index = true;
3921 add = true;
3922 wback = false;
3923
3924 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3925 shift_t = SRType_LSL;
3926 shift_n = Bits32 (opcode, 5, 4);
3927
3928 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3929 if ((t == 15) || (BadReg (m)))
3930 return false;
3931 break;
3932
3933 case eEncodingA1:
3934 {
3935 // if P == ’0’ && W == ’1’ then SEE STRT;
3936 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3937 t = Bits32 (opcode, 15, 12);
3938 n = Bits32 (opcode, 19, 16);
3939 m = Bits32 (opcode, 3, 0);
3940
3941 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3942 index = BitIsSet (opcode, 24);
3943 add = BitIsSet (opcode, 23);
3944 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3945
3946 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3947 uint32_t typ = Bits32 (opcode, 6, 5);
3948 uint32_t imm5 = Bits32 (opcode, 11, 7);
3949 shift_n = DecodeImmShift(typ, imm5, shift_t);
3950
3951 // if m == 15 then UNPREDICTABLE;
3952 if (m == 15)
3953 return false;
3954
3955 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3956 if (wback && ((n == 15) || (n == t)))
3957 return false;
3958
3959 break;
3960 }
3961 default:
3962 return false;
3963 }
3964
3965 addr_t offset_addr;
3966 addr_t address;
3967 int32_t offset = 0;
3968
3969 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3970 if (!success)
3971 return false;
3972
3973 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3974 if (!success)
3975 return false;
3976
3977 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
3978 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
3979
3980 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3981 if (add)
3982 offset_addr = base_address + offset;
3983 else
3984 offset_addr = base_address - offset;
3985
3986 // address = if index then offset_addr else R[n];
3987 if (index)
3988 address = offset_addr;
3989 else
3990 address = base_address;
3991
3992 uint32_t data;
3993 // if t == 15 then // Only possible for encoding A1
3994 if (t == 15)
3995 // data = PCStoreValue();
3996 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3997 else
3998 // data = R[t];
3999 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4000
4001 if (!success)
4002 return false;
4003
4004 EmulateInstruction::Context context;
4005 context.type = eContextRegisterStore;
4006
4007 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4008 if (UnalignedSupport ()
4009 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4010 || CurrentInstrSet() == eModeARM)
4011 {
4012 // MemU[address,4] = data;
4013
4014 Register base_reg;
4015 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4016
4017 Register data_reg;
4018 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4019
4020 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004021 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004022 return false;
4023
4024 }
4025 else
4026 // MemU[address,4] = bits(32) UNKNOWN;
4027 WriteBits32UnknownToMemory (address);
4028
4029 // if wback then R[n] = offset_addr;
4030 if (wback)
4031 {
4032 context.type = eContextRegisterLoad;
4033 context.SetAddress (offset_addr);
4034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4035 return false;
4036 }
4037
4038 }
4039 return true;
4040}
Caroline Tice73a29de2011-02-16 20:22:22 +00004041
4042bool
4043EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4044{
4045#if 0
4046 if ConditionPassed() then
4047 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4048 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4049 address = if index then offset_addr else R[n];
4050 MemU[address,1] = R[t]<7:0>;
4051 if wback then R[n] = offset_addr;
4052#endif
4053
4054
4055 bool success = false;
4056 const uint32_t opcode = OpcodeAsUnsigned (&success);
4057 if (!success)
4058 return false;
4059
4060 if (ConditionPassed ())
4061 {
4062 uint32_t t;
4063 uint32_t n;
4064 uint32_t imm32;
4065 bool index;
4066 bool add;
4067 bool wback;
4068 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4069 switch (encoding)
4070 {
4071 case eEncodingT1:
4072 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4073 t = Bits32 (opcode, 2, 0);
4074 n = Bits32 (opcode, 5, 3);
4075 imm32 = Bits32 (opcode, 10, 6);
4076
4077 // index = TRUE; add = TRUE; wback = FALSE;
4078 index = true;
4079 add = true;
4080 wback = false;
4081 break;
4082
4083 case eEncodingT2:
4084 // if Rn == ’1111’ then UNDEFINED;
4085 if (Bits32 (opcode, 19, 16) == 15)
4086 return false;
4087
4088 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4089 t = Bits32 (opcode, 15, 12);
4090 n = Bits32 (opcode, 19, 16);
4091 imm32 = Bits32 (opcode, 11, 0);
4092
4093 // index = TRUE; add = TRUE; wback = FALSE;
4094 index = true;
4095 add = true;
4096 wback = false;
4097
4098 // if BadReg(t) then UNPREDICTABLE;
4099 if (BadReg (t))
4100 return false;
4101 break;
4102
4103 case eEncodingT3:
4104 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4105 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4106 if (Bits32 (opcode, 19, 16) == 15)
4107 return false;
4108
4109 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4110 t = Bits32 (opcode, 15, 12);
4111 n = Bits32 (opcode, 19, 16);
4112 imm32 = Bits32 (opcode, 7, 0);
4113
4114 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4115 index = BitIsSet (opcode, 10);
4116 add = BitIsSet (opcode, 9);
4117 wback = BitIsSet (opcode, 8);
4118
4119 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4120 if ((BadReg (t)) || (wback && (n == t)))
4121 return false;
4122 break;
4123
4124 default:
4125 return false;
4126 }
4127
4128 addr_t offset_addr;
4129 addr_t address;
4130 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4131 if (!success)
4132 return false;
4133
4134 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4135 if (add)
4136 offset_addr = base_address + imm32;
4137 else
4138 offset_addr = base_address - imm32;
4139
4140 // address = if index then offset_addr else R[n];
4141 if (index)
4142 address = offset_addr;
4143 else
4144 address = base_address;
4145
Caroline Ticecc96eb52011-02-17 19:20:40 +00004146 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004147 Register base_reg;
4148 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4149
4150 Register data_reg;
4151 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4152
4153 EmulateInstruction::Context context;
4154 context.type = eContextRegisterStore;
4155 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4156
4157 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4158 if (!success)
4159 return false;
4160
4161 data = Bits32 (data, 7, 0);
4162
Caroline Ticecc96eb52011-02-17 19:20:40 +00004163 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004164 return false;
4165
4166 // if wback then R[n] = offset_addr;
4167 if (wback)
4168 {
4169 context.type = eContextRegisterLoad;
4170 context.SetAddress (offset_addr);
4171 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4172 return false;
4173 }
4174
4175 }
4176
4177 return true;
4178}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004179
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004180EmulateInstructionARM::ARMOpcode*
4181EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004182{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004183 static ARMOpcode
4184 g_arm_opcodes[] =
4185 {
4186 //----------------------------------------------------------------------
4187 // Prologue instructions
4188 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004189
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004190 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004191 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
4192 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004193
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004194 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004195 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
4196 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004197 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00004198 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
4199 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
4200 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004201
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004202 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004203 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004204
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004205 // push one register
4206 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004207 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004208
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004209 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004210 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4211 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004212
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004213 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004214 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004215 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004216
Johnny Chenc28a76d2011-02-01 18:51:48 +00004217 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
4218 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004219 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004220 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4221
4222 //----------------------------------------------------------------------
4223 // Supervisor Call (previously Software Interrupt)
4224 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004225 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4226
4227 //----------------------------------------------------------------------
4228 // Branch instructions
4229 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004230 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004231 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4232 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4233 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4234 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004235 // for example, "bx lr"
4236 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004237
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004238 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004239 // Data-processing instructions
4240 //----------------------------------------------------------------------
4241 // move bitwise not
4242 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004243 // asr (immediate)
4244 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004245 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004246 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004247 // lsl (immediate)
4248 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4249 // lsl (register)
4250 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4251 // lsr (immediate)
4252 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4253 // lsr (register)
4254 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004255 // rrx is a special case encoding of ror (immediate)
4256 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4257 // ror (immediate)
4258 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4259 // ror (register)
4260 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004261
4262 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004263 // Load instructions
4264 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004265 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004266 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004267 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004268 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4269
4270 //----------------------------------------------------------------------
4271 // Store instructions
4272 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004273 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004274 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004275 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004276 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4277 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004278
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004279
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004280 };
4281 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4282
4283 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4284 {
4285 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4286 return &g_arm_opcodes[i];
4287 }
4288 return NULL;
4289}
Greg Clayton64c84432011-01-21 22:02:52 +00004290
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004291
4292EmulateInstructionARM::ARMOpcode*
4293EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004294{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004295
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004296 static ARMOpcode
4297 g_thumb_opcodes[] =
4298 {
4299 //----------------------------------------------------------------------
4300 // Prologue instructions
4301 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004302
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004303 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004304 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004305 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
4306 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004307
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004308 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004309 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004310 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00004311 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004312 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
4313 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004314
Johnny Chenc9de9102011-02-11 19:12:30 +00004315 // PC-relative load into register (see also EmulateAddSPRm)
4316 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004317
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004318 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004319 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
4320 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004321 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
4322 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004323
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004324 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004325 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4326 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004327
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004328 //----------------------------------------------------------------------
4329 // Epilogue instructions
4330 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004331
Johnny Chenc28a76d2011-02-01 18:51:48 +00004332 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
4333 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004334 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
4335 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
4336 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4337 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004338
4339 //----------------------------------------------------------------------
4340 // Supervisor Call (previously Software Interrupt)
4341 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004342 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4343
4344 //----------------------------------------------------------------------
4345 // If Then makes up to four following instructions conditional.
4346 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004347 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4348
4349 //----------------------------------------------------------------------
4350 // Branch instructions
4351 //----------------------------------------------------------------------
4352 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4353 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4354 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004355 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004356 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004357 // J1 == J2 == 1
4358 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4359 // J1 == J2 == 1
4360 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4361 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004362 // for example, "bx lr"
4363 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004364 // compare and branch
4365 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00004366 // table branch byte
4367 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
4368 // table branch halfword
4369 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004370
4371 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004372 // Data-processing instructions
4373 //----------------------------------------------------------------------
4374 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
4375 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004376 // move from high register to high register
4377 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
4378 // move from low register to low register
4379 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004380 // move immediate
4381 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
4382 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004383 // move bitwise not
4384 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004385 // compare a register with immediate
4386 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004387 // compare Rn with Rm (Rn and Rm both from r0-r7)
4388 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
4389 // compare Rn with Rm (Rn and Rm not both from r0-r7)
4390 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004391 // asr (immediate)
4392 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004393 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004394 // asr (register)
4395 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4396 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004397 // lsl (immediate)
4398 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4399 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4400 // lsl (register)
4401 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4402 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4403 // lsr (immediate)
4404 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4405 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4406 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004407 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004408 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004409 // rrx is a special case encoding of ror (immediate)
4410 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4411 // ror (immediate)
4412 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4413 // ror (register)
4414 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4415 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004416
4417 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004418 // Load instructions
4419 //----------------------------------------------------------------------
4420 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004421 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004422 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004423 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4424 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004425 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4426
4427 //----------------------------------------------------------------------
4428 // Store instructions
4429 //----------------------------------------------------------------------
4430 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004431 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004432 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4433 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4434 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4435 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004436 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4437 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004438 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4439 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4440 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4441 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004442 };
4443
4444 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4445 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4446 {
4447 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4448 return &g_thumb_opcodes[i];
4449 }
4450 return NULL;
4451}
Greg Clayton64c84432011-01-21 22:02:52 +00004452
Greg Clayton31e2a382011-01-30 20:03:56 +00004453bool
Greg Clayton395fc332011-02-15 21:59:32 +00004454EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004455{
4456 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004457 const char *arch_cstr = arch.AsCString ();
4458 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004459 {
Greg Clayton395fc332011-02-15 21:59:32 +00004460 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4461 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4462 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4463 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4464 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4465 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4466 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4467 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4468 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4469 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004470 }
4471 return m_arm_isa != 0;
4472}
4473
4474
Greg Clayton64c84432011-01-21 22:02:52 +00004475bool
4476EmulateInstructionARM::ReadInstruction ()
4477{
4478 bool success = false;
4479 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4480 if (success)
4481 {
4482 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4483 if (success)
4484 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004485 Context read_inst_context;
4486 read_inst_context.type = eContextReadOpcode;
4487 read_inst_context.SetNoArgs ();
4488
Greg Clayton64c84432011-01-21 22:02:52 +00004489 if (m_inst_cpsr & MASK_CPSR_T)
4490 {
4491 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004492 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004493
4494 if (success)
4495 {
4496 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4497 {
4498 m_inst.opcode_type = eOpcode16;
4499 m_inst.opcode.inst16 = thumb_opcode;
4500 }
4501 else
4502 {
4503 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004504 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004505 }
4506 }
4507 }
4508 else
4509 {
4510 m_inst_mode = eModeARM;
4511 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004512 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004513 }
4514 }
4515 }
4516 if (!success)
4517 {
4518 m_inst_mode = eModeInvalid;
4519 m_inst_pc = LLDB_INVALID_ADDRESS;
4520 }
4521 return success;
4522}
4523
Johnny Chenee9b1f72011-02-09 01:00:31 +00004524uint32_t
4525EmulateInstructionARM::ArchVersion ()
4526{
4527 return m_arm_isa;
4528}
4529
Greg Clayton64c84432011-01-21 22:02:52 +00004530bool
4531EmulateInstructionARM::ConditionPassed ()
4532{
4533 if (m_inst_cpsr == 0)
4534 return false;
4535
4536 const uint32_t cond = CurrentCond ();
4537
4538 if (cond == UINT32_MAX)
4539 return false;
4540
4541 bool result = false;
4542 switch (UnsignedBits(cond, 3, 1))
4543 {
4544 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4545 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4546 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4547 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4548 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4549 case 5:
4550 {
4551 bool n = (m_inst_cpsr & MASK_CPSR_N);
4552 bool v = (m_inst_cpsr & MASK_CPSR_V);
4553 result = n == v;
4554 }
4555 break;
4556 case 6:
4557 {
4558 bool n = (m_inst_cpsr & MASK_CPSR_N);
4559 bool v = (m_inst_cpsr & MASK_CPSR_V);
4560 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4561 }
4562 break;
4563 case 7:
4564 result = true;
4565 break;
4566 }
4567
4568 if (cond & 1)
4569 result = !result;
4570 return result;
4571}
4572
Johnny Chen9ee056b2011-02-08 00:06:35 +00004573uint32_t
4574EmulateInstructionARM::CurrentCond ()
4575{
4576 switch (m_inst_mode)
4577 {
4578 default:
4579 case eModeInvalid:
4580 break;
4581
4582 case eModeARM:
4583 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4584
4585 case eModeThumb:
4586 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4587 // 'cond' field of the encoding.
4588 if (m_inst.opcode_type == eOpcode16 &&
4589 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4590 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4591 {
4592 return Bits32(m_inst.opcode.inst16, 11, 7);
4593 }
4594 else if (m_inst.opcode_type == eOpcode32 &&
4595 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4596 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4597 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4598 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4599 {
4600 return Bits32(m_inst.opcode.inst32, 25, 22);
4601 }
4602
4603 return m_it_session.GetCond();
4604 }
4605 return UINT32_MAX; // Return invalid value
4606}
4607
Johnny Chen9ee056b2011-02-08 00:06:35 +00004608bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004609EmulateInstructionARM::InITBlock()
4610{
4611 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4612}
4613
4614bool
4615EmulateInstructionARM::LastInITBlock()
4616{
4617 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4618}
4619
4620bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004621EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4622{
4623 addr_t target;
4624
Johnny Chenee9b1f72011-02-09 01:00:31 +00004625 // Check the current instruction set.
4626 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004627 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004628 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004629 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004630
Johnny Chen9ee056b2011-02-08 00:06:35 +00004631 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004632 return false;
4633
4634 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004635}
4636
4637// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4638bool
Johnny Chen668b4512011-02-15 21:08:58 +00004639EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004640{
4641 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004642 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4643 // we want to record it and issue a WriteRegister callback so the clients
4644 // can track the mode changes accordingly.
4645 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004646
4647 if (BitIsSet(addr, 0))
4648 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004649 if (CurrentInstrSet() != eModeThumb)
4650 {
4651 SelectInstrSet(eModeThumb);
4652 cpsr_changed = true;
4653 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004654 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004655 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004656 }
4657 else if (BitIsClear(addr, 1))
4658 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004659 if (CurrentInstrSet() != eModeARM)
4660 {
4661 SelectInstrSet(eModeARM);
4662 cpsr_changed = true;
4663 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004664 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004665 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004666 }
4667 else
4668 return false; // address<1:0> == '10' => UNPREDICTABLE
4669
Johnny Chen0f309db2011-02-09 19:11:32 +00004670 if (cpsr_changed)
4671 {
Johnny Chen558133b2011-02-09 23:59:17 +00004672 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004673 return false;
4674 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004675 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004676 return false;
4677
4678 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004679}
Greg Clayton64c84432011-01-21 22:02:52 +00004680
Johnny Chenee9b1f72011-02-09 01:00:31 +00004681// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4682bool
Johnny Chen668b4512011-02-15 21:08:58 +00004683EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004684{
4685 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004686 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004687 else
4688 return BranchWritePC((const Context)context, addr);
4689}
4690
Johnny Chen26863dc2011-02-09 23:43:29 +00004691// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4692bool
Johnny Chen668b4512011-02-15 21:08:58 +00004693EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004694{
4695 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004696 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004697 else
4698 return BranchWritePC((const Context)context, addr);
4699}
4700
Johnny Chenee9b1f72011-02-09 01:00:31 +00004701EmulateInstructionARM::Mode
4702EmulateInstructionARM::CurrentInstrSet ()
4703{
4704 return m_inst_mode;
4705}
4706
4707// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004708// ReadInstruction() is performed. This function has a side effect of updating
4709// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004710bool
4711EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4712{
Johnny Chen558133b2011-02-09 23:59:17 +00004713 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004714 switch (arm_or_thumb)
4715 {
4716 default:
4717 return false;
4718 eModeARM:
4719 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004720 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004721 break;
4722 eModeThumb:
4723 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004724 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004725 break;
4726 }
4727 return true;
4728}
4729
Johnny Chenef21b592011-02-10 01:52:38 +00004730// This function returns TRUE if the processor currently provides support for
4731// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4732// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4733bool
4734EmulateInstructionARM::UnalignedSupport()
4735{
4736 return (ArchVersion() >= ARMv7);
4737}
4738
Johnny Chenbf6ad172011-02-11 01:29:53 +00004739// The main addition and subtraction instructions can produce status information
4740// about both unsigned carry and signed overflow conditions. This status
4741// information can be used to synthesize multi-word additions and subtractions.
4742EmulateInstructionARM::AddWithCarryResult
4743EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4744{
4745 uint32_t result;
4746 uint8_t carry_out;
4747 uint8_t overflow;
4748
4749 uint64_t unsigned_sum = x + y + carry_in;
4750 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4751
4752 result = UnsignedBits(unsigned_sum, 31, 0);
4753 carry_out = (result == unsigned_sum ? 0 : 1);
4754 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4755
4756 AddWithCarryResult res = { result, carry_out, overflow };
4757 return res;
4758}
4759
Johnny Chenca67d1c2011-02-17 01:35:27 +00004760// Write the result to the ARM core register Rd, and optionally update the
4761// condition flags based on the result.
4762//
4763// This helper method tries to encapsulate the following pseudocode from the
4764// ARM Architecture Reference Manual:
4765//
4766// if d == 15 then // Can only occur for encoding A1
4767// ALUWritePC(result); // setflags is always FALSE here
4768// else
4769// R[d] = result;
4770// if setflags then
4771// APSR.N = result<31>;
4772// APSR.Z = IsZeroBit(result);
4773// APSR.C = carry;
4774// // APSR.V unchanged
4775//
4776// In the above case, the API client does not pass in the overflow arg, which
4777// defaults to ~0u.
4778bool
4779EmulateInstructionARM::WriteCoreRegisterWithFlags (Context &context,
4780 const uint32_t result,
4781 const uint32_t Rd,
4782 bool setflags,
4783 const uint32_t carry,
4784 const uint32_t overflow)
4785{
4786 if (Rd == 15)
4787 {
4788 if (!ALUWritePC (context, result))
4789 return false;
4790 }
4791 else
4792 {
4793 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
4794 return false;
4795 if (setflags)
4796 {
4797 m_new_inst_cpsr = m_inst_cpsr;
4798 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
4799 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
4800 if (carry != ~0u)
4801 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
4802 if (overflow != ~0u)
4803 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
4804 if (m_new_inst_cpsr != m_inst_cpsr)
4805 {
4806 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
4807 return false;
4808 }
4809 }
4810 }
4811 return true;
4812}
4813
Greg Clayton64c84432011-01-21 22:02:52 +00004814bool
4815EmulateInstructionARM::EvaluateInstruction ()
4816{
Johnny Chenc315f862011-02-05 00:46:10 +00004817 // Advance the ITSTATE bits to their values for the next instruction.
4818 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4819 m_it_session.ITAdvance();
4820
Greg Clayton64c84432011-01-21 22:02:52 +00004821 return false;
4822}