blob: 2495937a35639a3c566a9d030ce72d8b5b98ba0e [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 Chend761dcf2011-02-17 22:03:29 +00001915// This instruction adds a register value and an optionally-shifted register value, and writes the result
1916// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001917bool
Johnny Chend761dcf2011-02-17 22:03:29 +00001918EmulateInstructionARM::EmulateAddReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001919{
1920#if 0
1921 // ARM pseudo code...
1922 if ConditionPassed() then
1923 EncodingSpecificOperations();
1924 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1925 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1926 if d == 15 then
1927 ALUWritePC(result); // setflags is always FALSE here
1928 else
1929 R[d] = result;
1930 if setflags then
1931 APSR.N = result<31>;
1932 APSR.Z = IsZeroBit(result);
1933 APSR.C = carry;
1934 APSR.V = overflow;
1935#endif
1936
1937 bool success = false;
1938 const uint32_t opcode = OpcodeAsUnsigned (&success);
1939 if (!success)
1940 return false;
1941
1942 if (ConditionPassed())
1943 {
1944 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00001945 ARM_ShifterType shift_t;
1946 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00001947 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00001948 switch (encoding)
1949 {
Johnny Chend761dcf2011-02-17 22:03:29 +00001950 case eEncodingT1:
1951 Rd = Bits32(opcode, 2, 0);
1952 Rn = Bits32(opcode, 5, 3);
1953 Rm = Bits32(opcode, 8, 6);
1954 setflags = !InITBlock();
1955 shift_t = SRType_LSL;
1956 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00001957 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00001958 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001959 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00001960 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00001961 shift_t = SRType_LSL;
1962 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00001963 if (Rn == 15 && Rm == 15)
1964 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00001965 if (Rd == 15 && InITBlock() && !LastInITBlock())
1966 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00001967 break;
1968 default:
1969 return false;
1970 }
1971
1972 int32_t result, val1, val2;
1973 // Read the first operand.
1974 if (Rn == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00001975 {
Johnny Chen26863dc2011-02-09 23:43:29 +00001976 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00001977 if (encoding == eEncodingT1 || encoding == eEncodingT2)
1978 val1 += 4;
1979 else
1980 val1 += 8;
1981 }
Johnny Chen26863dc2011-02-09 23:43:29 +00001982 else
1983 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1984 if (!success)
1985 return false;
1986
1987 // Read the second operand.
1988 if (Rm == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00001989 {
Johnny Chen26863dc2011-02-09 23:43:29 +00001990 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00001991 if (encoding == eEncodingT1 || encoding == eEncodingT2)
1992 val1 += 4;
1993 else
1994 val1 += 8;
1995 }
Johnny Chen26863dc2011-02-09 23:43:29 +00001996 else
1997 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1998 if (!success)
1999 return false;
2000
Johnny Chend761dcf2011-02-17 22:03:29 +00002001 val2 = Shift(val2, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
Johnny Chenca67d1c2011-02-17 01:35:27 +00002002 AddWithCarryResult res = AddWithCarry(val1, val2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002003 result = val1 + val2;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002004
2005 EmulateInstruction::Context context;
2006 context.type = EmulateInstruction::eContextImmediate;
2007 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002008
2009 if (!WriteCoreRegisterWithFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2010 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002011 }
2012 return true;
2013}
2014
Johnny Chene4a4d302011-02-11 21:53:58 +00002015// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002016bool
2017EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
2018{
2019#if 0
2020 // ARM pseudo code...
2021 if ConditionPassed() then
2022 EncodingSpecificOperations();
2023 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2024 APSR.N = result<31>;
2025 APSR.Z = IsZeroBit(result);
2026 APSR.C = carry;
2027 APSR.V = overflow;
2028#endif
2029
2030 bool success = false;
2031 const uint32_t opcode = OpcodeAsUnsigned (&success);
2032 if (!success)
2033 return false;
2034
2035 uint32_t Rn; // the first operand
2036 uint32_t imm32; // the immediate value to be compared with
2037 switch (encoding) {
2038 case eEncodingT1:
2039 Rn = Bits32(opcode, 10, 8);
2040 imm32 = Bits32(opcode, 7, 0);
2041 break;
2042 default:
2043 return false;
2044 }
2045 // Read the register value from the operand register Rn.
2046 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2047 if (!success)
2048 return false;
2049
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002050 EmulateInstruction::Context context;
2051 context.type = EmulateInstruction::eContextImmediate;
2052 context.SetNoArgs ();
2053
Johnny Chend4dc4442011-02-11 02:02:56 +00002054 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2055 m_new_inst_cpsr = m_inst_cpsr;
2056 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2057 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2058 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2059 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2060 if (m_new_inst_cpsr != m_inst_cpsr)
2061 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002062 EmulateInstruction::Context context;
2063 context.type = EmulateInstruction::eContextImmediate;
2064 context.SetNoArgs ();
Johnny Chend4dc4442011-02-11 02:02:56 +00002065 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2066 return false;
2067 }
2068 return true;
2069}
2070
Johnny Chene4a4d302011-02-11 21:53:58 +00002071// CMP (register)
2072bool
2073EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2074{
2075#if 0
2076 // ARM pseudo code...
2077 if ConditionPassed() then
2078 EncodingSpecificOperations();
2079 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2080 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2081 APSR.N = result<31>;
2082 APSR.Z = IsZeroBit(result);
2083 APSR.C = carry;
2084 APSR.V = overflow;
2085#endif
2086
2087 bool success = false;
2088 const uint32_t opcode = OpcodeAsUnsigned (&success);
2089 if (!success)
2090 return false;
2091
2092 uint32_t Rn; // the first operand
2093 uint32_t Rm; // the second operand
2094 switch (encoding) {
2095 case eEncodingT1:
2096 Rn = Bits32(opcode, 2, 0);
2097 Rm = Bits32(opcode, 5, 3);
2098 break;
2099 case eEncodingT2:
2100 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2101 Rm = Bits32(opcode, 6, 3);
2102 if (Rn < 8 && Rm < 8)
2103 return false;
2104 if (Rn == 15 || Rm == 15)
2105 return false;
2106 break;
2107 default:
2108 return false;
2109 }
2110 // Read the register value from register Rn.
2111 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2112 if (!success)
2113 return false;
2114 // Read the register value from register Rm.
2115 // The register value is not being shifted since we don't handle ARM for now.
2116 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2117 if (!success)
2118 return false;
2119
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002120 EmulateInstruction::Context context;
2121 context.type = EmulateInstruction::eContextImmediate;
2122 context.SetNoArgs();
2123
Johnny Chene4a4d302011-02-11 21:53:58 +00002124 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2125 m_new_inst_cpsr = m_inst_cpsr;
2126 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2127 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2128 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2129 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2130 if (m_new_inst_cpsr != m_inst_cpsr)
2131 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002132 EmulateInstruction::Context context;
2133 context.type = EmulateInstruction::eContextImmediate;
2134 context.SetNoArgs ();
Johnny Chene4a4d302011-02-11 21:53:58 +00002135 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2136 return false;
2137 }
2138 return true;
2139}
2140
Johnny Chen82f16aa2011-02-15 20:10:55 +00002141// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2142// shifting in copies of its sign bit, and writes the result to the destination register. It can
2143// optionally update the condition flags based on the result.
2144bool
2145EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2146{
2147#if 0
2148 // ARM pseudo code...
2149 if ConditionPassed() then
2150 EncodingSpecificOperations();
2151 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2152 if d == 15 then // Can only occur for ARM encoding
2153 ALUWritePC(result); // setflags is always FALSE here
2154 else
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
Johnny Chen41a0a152011-02-16 01:27:54 +00002163 return EmulateShiftImm(encoding, SRType_ASR);
2164}
2165
2166// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2167// shifting in copies of its sign bit, and writes the result to the destination register.
2168// The variable number of bits is read from the bottom byte of a register. It can optionally update
2169// the condition flags based on the result.
2170bool
2171EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2172{
2173#if 0
2174 // ARM pseudo code...
2175 if ConditionPassed() then
2176 EncodingSpecificOperations();
2177 shift_n = UInt(R[m]<7:0>);
2178 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2179 R[d] = result;
2180 if setflags then
2181 APSR.N = result<31>;
2182 APSR.Z = IsZeroBit(result);
2183 APSR.C = carry;
2184 // APSR.V unchanged
2185#endif
2186
2187 return EmulateShiftReg(encoding, SRType_ASR);
2188}
2189
2190// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2191// shifting in zeros, and writes the result to the destination register. It can optionally
2192// update the condition flags based on the result.
2193bool
2194EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2195{
2196#if 0
2197 // ARM pseudo code...
2198 if ConditionPassed() then
2199 EncodingSpecificOperations();
2200 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2201 if d == 15 then // Can only occur for ARM encoding
2202 ALUWritePC(result); // setflags is always FALSE here
2203 else
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 EmulateShiftImm(encoding, SRType_LSL);
2213}
2214
2215// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2216// shifting in zeros, and writes the result to the destination register. The variable number
2217// of bits is read from the bottom byte of a register. It can optionally update the condition
2218// flags based on the result.
2219bool
2220EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2221{
2222#if 0
2223 // ARM pseudo code...
2224 if ConditionPassed() then
2225 EncodingSpecificOperations();
2226 shift_n = UInt(R[m]<7:0>);
2227 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2228 R[d] = result;
2229 if setflags then
2230 APSR.N = result<31>;
2231 APSR.Z = IsZeroBit(result);
2232 APSR.C = carry;
2233 // APSR.V unchanged
2234#endif
2235
2236 return EmulateShiftReg(encoding, SRType_LSL);
2237}
2238
2239// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2240// shifting in zeros, and writes the result to the destination register. It can optionally
2241// update the condition flags based on the result.
2242bool
2243EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2244{
2245#if 0
2246 // ARM pseudo code...
2247 if ConditionPassed() then
2248 EncodingSpecificOperations();
2249 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2250 if d == 15 then // Can only occur for ARM encoding
2251 ALUWritePC(result); // setflags is always FALSE here
2252 else
2253 R[d] = result;
2254 if setflags then
2255 APSR.N = result<31>;
2256 APSR.Z = IsZeroBit(result);
2257 APSR.C = carry;
2258 // APSR.V unchanged
2259#endif
2260
2261 return EmulateShiftImm(encoding, SRType_LSR);
2262}
2263
2264// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2265// shifting in zeros, and writes the result to the destination register. The variable number
2266// of bits is read from the bottom byte of a register. It can optionally update the condition
2267// flags based on the result.
2268bool
2269EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2270{
2271#if 0
2272 // ARM pseudo code...
2273 if ConditionPassed() then
2274 EncodingSpecificOperations();
2275 shift_n = UInt(R[m]<7:0>);
2276 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2277 R[d] = result;
2278 if setflags then
2279 APSR.N = result<31>;
2280 APSR.Z = IsZeroBit(result);
2281 APSR.C = carry;
2282 // APSR.V unchanged
2283#endif
2284
2285 return EmulateShiftReg(encoding, SRType_LSR);
2286}
2287
Johnny Cheneeab4852011-02-16 22:14:44 +00002288// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2289// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2290// It can optionally update the condition flags based on the result.
2291bool
2292EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2293{
2294#if 0
2295 // ARM pseudo code...
2296 if ConditionPassed() then
2297 EncodingSpecificOperations();
2298 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2299 if d == 15 then // Can only occur for ARM encoding
2300 ALUWritePC(result); // setflags is always FALSE here
2301 else
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 EmulateShiftImm(encoding, SRType_ROR);
2311}
2312
2313// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2314// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2315// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2316// flags based on the result.
2317bool
2318EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2319{
2320#if 0
2321 // ARM pseudo code...
2322 if ConditionPassed() then
2323 EncodingSpecificOperations();
2324 shift_n = UInt(R[m]<7:0>);
2325 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2326 R[d] = result;
2327 if setflags then
2328 APSR.N = result<31>;
2329 APSR.Z = IsZeroBit(result);
2330 APSR.C = carry;
2331 // APSR.V unchanged
2332#endif
2333
2334 return EmulateShiftReg(encoding, SRType_ROR);
2335}
2336
2337// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2338// with the carry flag shifted into bit [31].
2339//
2340// RRX can optionally update the condition flags based on the result.
2341// In that case, bit [0] is shifted into the carry flag.
2342bool
2343EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2344{
2345#if 0
2346 // ARM pseudo code...
2347 if ConditionPassed() then
2348 EncodingSpecificOperations();
2349 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2350 if d == 15 then // Can only occur for ARM encoding
2351 ALUWritePC(result); // setflags is always FALSE here
2352 else
2353 R[d] = result;
2354 if setflags then
2355 APSR.N = result<31>;
2356 APSR.Z = IsZeroBit(result);
2357 APSR.C = carry;
2358 // APSR.V unchanged
2359#endif
2360
2361 return EmulateShiftImm(encoding, SRType_RRX);
2362}
2363
Johnny Chen41a0a152011-02-16 01:27:54 +00002364bool
2365EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2366{
2367 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2368
Johnny Chen82f16aa2011-02-15 20:10:55 +00002369 bool success = false;
2370 const uint32_t opcode = OpcodeAsUnsigned (&success);
2371 if (!success)
2372 return false;
2373
2374 if (ConditionPassed())
2375 {
Johnny Chene7f89532011-02-15 23:22:46 +00002376 uint32_t Rd; // the destination register
2377 uint32_t Rm; // the first operand register
2378 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002379 uint32_t carry; // the carry bit after the shift operation
2380 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002381
2382 // Special case handling!
2383 // A8.6.139 ROR (immediate) -- Encoding T1
2384 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2385 {
2386 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2387 // have the same decoding of bit fields as the other Thumb2 shift operations.
2388 encoding = eEncodingT2;
2389 }
2390
Johnny Chen82f16aa2011-02-15 20:10:55 +00002391 switch (encoding) {
2392 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002393 // Due to the above special case handling!
2394 assert(shift_type != SRType_ROR);
2395
Johnny Chen82f16aa2011-02-15 20:10:55 +00002396 Rd = Bits32(opcode, 2, 0);
2397 Rm = Bits32(opcode, 5, 3);
2398 setflags = !InITBlock();
2399 imm5 = Bits32(opcode, 10, 6);
2400 break;
2401 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002402 // A8.6.141 RRX
2403 assert(shift_type != SRType_RRX);
2404
Johnny Chen82f16aa2011-02-15 20:10:55 +00002405 Rd = Bits32(opcode, 11, 8);
2406 Rm = Bits32(opcode, 3, 0);
2407 setflags = BitIsSet(opcode, 20);
2408 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2409 if (BadReg(Rd) || BadReg(Rm))
2410 return false;
2411 break;
2412 case eEncodingA1:
2413 Rd = Bits32(opcode, 15, 12);
2414 Rm = Bits32(opcode, 3, 0);
2415 setflags = BitIsSet(opcode, 20);
2416 imm5 = Bits32(opcode, 11, 7);
2417 break;
2418 default:
2419 return false;
2420 }
2421
Johnny Cheneeab4852011-02-16 22:14:44 +00002422 // A8.6.139 ROR (immediate)
2423 if (shift_type == SRType_ROR && imm5 == 0)
2424 shift_type = SRType_RRX;
2425
Johnny Chen82f16aa2011-02-15 20:10:55 +00002426 // Get the first operand.
2427 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2428 if (!success)
2429 return false;
2430
Johnny Cheneeab4852011-02-16 22:14:44 +00002431 // Decode the shift amount if not RRX.
2432 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002433
Johnny Chen41a0a152011-02-16 01:27:54 +00002434 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002435
2436 // The context specifies that an immediate is to be moved into Rd.
2437 EmulateInstruction::Context context;
2438 context.type = EmulateInstruction::eContextImmediate;
2439 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002440
Johnny Chenca67d1c2011-02-17 01:35:27 +00002441 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
2442 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002443 }
2444 return true;
2445}
2446
Johnny Chene7f89532011-02-15 23:22:46 +00002447bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002448EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002449{
Johnny Chen41a0a152011-02-16 01:27:54 +00002450 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002451
2452 bool success = false;
2453 const uint32_t opcode = OpcodeAsUnsigned (&success);
2454 if (!success)
2455 return false;
2456
2457 if (ConditionPassed())
2458 {
2459 uint32_t Rd; // the destination register
2460 uint32_t Rn; // the first operand register
2461 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2462 uint32_t carry; // the carry bit after the shift operation
2463 bool setflags;
2464 switch (encoding) {
2465 case eEncodingT1:
2466 Rd = Bits32(opcode, 2, 0);
2467 Rn = Rd;
2468 Rm = Bits32(opcode, 5, 3);
2469 setflags = !InITBlock();
2470 break;
2471 case eEncodingT2:
2472 Rd = Bits32(opcode, 11, 8);
2473 Rn = Bits32(opcode, 19, 16);
2474 Rm = Bits32(opcode, 3, 0);
2475 setflags = BitIsSet(opcode, 20);
2476 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2477 return false;
2478 break;
2479 case eEncodingA1:
2480 Rd = Bits32(opcode, 15, 12);
2481 Rn = Bits32(opcode, 3, 0);
2482 Rm = Bits32(opcode, 11, 8);
2483 setflags = BitIsSet(opcode, 20);
2484 if (Rd == 15 || Rn == 15 || Rm == 15)
2485 return false;
2486 break;
2487 default:
2488 return false;
2489 }
2490
2491 // Get the first operand.
2492 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2493 if (!success)
2494 return false;
2495 // Get the Rm register content.
2496 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2497 if (!success)
2498 return false;
2499
2500 // Get the shift amount.
2501 uint32_t amt = Bits32(val, 7, 0);
2502
Johnny Chen41a0a152011-02-16 01:27:54 +00002503 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002504
2505 // The context specifies that an immediate is to be moved into Rd.
2506 EmulateInstruction::Context context;
2507 context.type = EmulateInstruction::eContextImmediate;
2508 context.SetNoArgs ();
2509
Johnny Chenca67d1c2011-02-17 01:35:27 +00002510 if (!WriteCoreRegisterWithFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002511 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002512 }
2513 return true;
2514}
2515
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002516// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002517// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002518// can be written back to the base register.
2519bool
2520EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2521{
2522#if 0
2523 // ARM pseudo code...
2524 if ConditionPassed()
2525 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2526 address = R[n];
2527
2528 for i = 0 to 14
2529 if registers<i> == '1' then
2530 R[i] = MemA[address, 4]; address = address + 4;
2531 if registers<15> == '1' then
2532 LoadWritePC (MemA[address, 4]);
2533
2534 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2535 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2536
2537#endif
2538
2539 bool success = false;
2540 const uint32_t opcode = OpcodeAsUnsigned (&success);
2541 if (!success)
2542 return false;
2543
2544 if (ConditionPassed())
2545 {
2546 uint32_t n;
2547 uint32_t registers = 0;
2548 bool wback;
2549 const uint32_t addr_byte_size = GetAddressByteSize();
2550 switch (encoding)
2551 {
2552 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002553 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002554 n = Bits32 (opcode, 10, 8);
2555 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002556 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002557 wback = BitIsClear (registers, n);
2558 // if BitCount(registers) < 1 then UNPREDICTABLE;
2559 if (BitCount(registers) < 1)
2560 return false;
2561 break;
2562 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002563 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2564 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002565 n = Bits32 (opcode, 19, 16);
2566 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002567 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002568 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002569
2570 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002571 if ((n == 15)
2572 || (BitCount (registers) < 2)
2573 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2574 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002575
2576 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002577 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002578 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002579
2580 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002581 if (wback
2582 && BitIsSet (registers, n))
2583 return false;
2584 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002585
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002586 case eEncodingA1:
2587 n = Bits32 (opcode, 19, 16);
2588 registers = Bits32 (opcode, 15, 0);
2589 wback = BitIsSet (opcode, 21);
2590 if ((n == 15)
2591 || (BitCount (registers) < 1))
2592 return false;
2593 break;
2594 default:
2595 return false;
2596 }
2597
2598 int32_t offset = 0;
2599 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2600 if (!success)
2601 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002602
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002603 EmulateInstruction::Context context;
2604 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2605 Register dwarf_reg;
2606 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2607 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002608
2609 for (int i = 0; i < 14; ++i)
2610 {
2611 if (BitIsSet (registers, i))
2612 {
Caroline Tice85aab332011-02-08 23:56:10 +00002613 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002614 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002615 if (wback && (n == 13)) // Pop Instruction
2616 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2617
2618 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002619 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002620 if (!success)
2621 return false;
2622
2623 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2624 return false;
2625
2626 offset += addr_byte_size;
2627 }
2628 }
2629
2630 if (BitIsSet (registers, 15))
2631 {
2632 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002633 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002634 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002635 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002636 if (!success)
2637 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002638 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002639 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002640 return false;
2641 }
2642
2643 if (wback && BitIsClear (registers, n))
2644 {
Caroline Ticefa172202011-02-11 22:49:54 +00002645 // R[n] = R[n] + 4 * BitCount (registers)
2646 int32_t offset = addr_byte_size * BitCount (registers);
2647 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002648 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002649
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002650 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2651 return false;
2652 }
2653 if (wback && BitIsSet (registers, n))
2654 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002655 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002656 }
2657 return true;
2658}
Caroline Tice713c2662011-02-11 17:59:55 +00002659
2660// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2661// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2662// can optionally be written back tot he base registers.
2663bool
2664EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2665{
2666#if 0
2667 // ARM pseudo code...
2668 if ConditionPassed() then
2669 EncodingSpecificOperations();
2670 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002671
Caroline Tice713c2662011-02-11 17:59:55 +00002672 for i = 0 to 14
2673 if registers<i> == ’1’ then
2674 R[i] = MemA[address,4]; address = address + 4;
2675
2676 if registers<15> == ’1’ then
2677 LoadWritePC(MemA[address,4]);
2678
2679 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2680 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2681#endif
2682
2683 bool success = false;
2684 const uint32_t opcode = OpcodeAsUnsigned (&success);
2685 if (!success)
2686 return false;
2687
2688 if (ConditionPassed())
2689 {
2690 uint32_t n;
2691 uint32_t registers = 0;
2692 bool wback;
2693 const uint32_t addr_byte_size = GetAddressByteSize();
2694
2695 // EncodingSpecificOperations();
2696 switch (encoding)
2697 {
2698 case eEncodingA1:
2699 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2700 n = Bits32 (opcode, 19, 16);
2701 registers = Bits32 (opcode, 15, 0);
2702 wback = BitIsSet (opcode, 21);
2703
2704 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2705 if ((n == 15) || (BitCount (registers) < 1))
2706 return false;
2707
2708 break;
2709
2710 default:
2711 return false;
2712 }
2713 // address = R[n] - 4*BitCount(registers) + 4;
2714
2715 int32_t offset = 0;
2716 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2717
2718 if (!success)
2719 return false;
2720
2721 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2722
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002723 EmulateInstruction::Context context;
2724 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2725 Register dwarf_reg;
2726 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2727 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002728
2729 // for i = 0 to 14
2730 for (int i = 0; i < 14; ++i)
2731 {
2732 // if registers<i> == ’1’ then
2733 if (BitIsSet (registers, i))
2734 {
2735 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002736 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002737 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002738 if (!success)
2739 return false;
2740 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2741 return false;
2742 offset += addr_byte_size;
2743 }
2744 }
2745
2746 // if registers<15> == ’1’ then
2747 // LoadWritePC(MemA[address,4]);
2748 if (BitIsSet (registers, 15))
2749 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002750 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002751 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002752 if (!success)
2753 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002754 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002755 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002756 return false;
2757 }
2758
2759 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2760 if (wback && BitIsClear (registers, n))
2761 {
Caroline Tice713c2662011-02-11 17:59:55 +00002762 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2763 if (!success)
2764 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002765
2766 offset = (addr_byte_size * BitCount (registers)) * -1;
2767 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002768 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002769 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002770 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2771 return false;
2772 }
2773
2774 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2775 if (wback && BitIsSet (registers, n))
2776 return WriteBits32Unknown (n);
2777 }
2778 return true;
2779}
2780
2781// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2782// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2783// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002784bool
2785EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2786{
2787#if 0
2788 // ARM pseudo code...
2789 if ConditionPassed() then
2790 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2791 address = R[n] - 4*BitCount(registers);
2792
2793 for i = 0 to 14
2794 if registers<i> == ’1’ then
2795 R[i] = MemA[address,4]; address = address + 4;
2796 if registers<15> == ’1’ then
2797 LoadWritePC(MemA[address,4]);
2798
2799 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2800 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2801#endif
2802
2803 bool success = false;
2804 const uint32_t opcode = OpcodeAsUnsigned (&success);
2805 if (!success)
2806 return false;
2807
2808 if (ConditionPassed())
2809 {
2810 uint32_t n;
2811 uint32_t registers = 0;
2812 bool wback;
2813 const uint32_t addr_byte_size = GetAddressByteSize();
2814 switch (encoding)
2815 {
2816 case eEncodingT1:
2817 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2818 n = Bits32 (opcode, 19, 16);
2819 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002820 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002821 wback = BitIsSet (opcode, 21);
2822
2823 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2824 if ((n == 15)
2825 || (BitCount (registers) < 2)
2826 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2827 return false;
2828
2829 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002830 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002831 return false;
2832
2833 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2834 if (wback && BitIsSet (registers, n))
2835 return false;
2836
2837 break;
2838
2839 case eEncodingA1:
2840 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2841 n = Bits32 (opcode, 19, 16);
2842 registers = Bits32 (opcode, 15, 0);
2843 wback = BitIsSet (opcode, 21);
2844
2845 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2846 if ((n == 15) || (BitCount (registers) < 1))
2847 return false;
2848
2849 break;
2850
2851 default:
2852 return false;
2853 }
2854
Caroline Tice713c2662011-02-11 17:59:55 +00002855 // address = R[n] - 4*BitCount(registers);
2856
Caroline Tice0b29e242011-02-08 23:16:02 +00002857 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002858 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2859
2860 if (!success)
2861 return false;
2862
2863 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002864 EmulateInstruction::Context context;
2865 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2866 Register dwarf_reg;
2867 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2868 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002869
2870 for (int i = 0; i < 14; ++i)
2871 {
2872 if (BitIsSet (registers, i))
2873 {
2874 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002875 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002876 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002877 if (!success)
2878 return false;
2879
2880 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2881 return false;
2882
2883 offset += addr_byte_size;
2884 }
2885 }
2886
2887 // if registers<15> == ’1’ then
2888 // LoadWritePC(MemA[address,4]);
2889 if (BitIsSet (registers, 15))
2890 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002891 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002892 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002893 if (!success)
2894 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002895 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002896 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002897 return false;
2898 }
2899
2900 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2901 if (wback && BitIsClear (registers, n))
2902 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002903 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2904 if (!success)
2905 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002906
2907 offset = (addr_byte_size * BitCount (registers)) * -1;
2908 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002909 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002910 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2912 return false;
2913 }
2914
2915 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2916 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002917 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002918 }
2919 return true;
2920}
Caroline Tice85aab332011-02-08 23:56:10 +00002921
Caroline Tice713c2662011-02-11 17:59:55 +00002922// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2923// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2924// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002925bool
2926EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2927{
2928#if 0
2929 if ConditionPassed() then
2930 EncodingSpecificOperations();
2931 address = R[n] + 4;
2932
2933 for i = 0 to 14
2934 if registers<i> == ’1’ then
2935 R[i] = MemA[address,4]; address = address + 4;
2936 if registers<15> == ’1’ then
2937 LoadWritePC(MemA[address,4]);
2938
2939 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2940 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2941#endif
2942
2943 bool success = false;
2944 const uint32_t opcode = OpcodeAsUnsigned (&success);
2945 if (!success)
2946 return false;
2947
2948 if (ConditionPassed())
2949 {
2950 uint32_t n;
2951 uint32_t registers = 0;
2952 bool wback;
2953 const uint32_t addr_byte_size = GetAddressByteSize();
2954 switch (encoding)
2955 {
2956 case eEncodingA1:
2957 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2958 n = Bits32 (opcode, 19, 16);
2959 registers = Bits32 (opcode, 15, 0);
2960 wback = BitIsSet (opcode, 21);
2961
2962 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2963 if ((n == 15) || (BitCount (registers) < 1))
2964 return false;
2965
2966 break;
2967 default:
2968 return false;
2969 }
2970 // address = R[n] + 4;
2971
2972 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002973 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2974
2975 if (!success)
2976 return false;
2977
2978 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002979
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002980 EmulateInstruction::Context context;
2981 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2982 Register dwarf_reg;
2983 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2984 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002985
2986 for (int i = 0; i < 14; ++i)
2987 {
2988 if (BitIsSet (registers, i))
2989 {
2990 // R[i] = MemA[address,4]; address = address + 4;
2991
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002992 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002993 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002994 if (!success)
2995 return false;
2996
2997 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2998 return false;
2999
3000 offset += addr_byte_size;
3001 }
3002 }
3003
3004 // if registers<15> == ’1’ then
3005 // LoadWritePC(MemA[address,4]);
3006 if (BitIsSet (registers, 15))
3007 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003008 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003009 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003010 if (!success)
3011 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003012 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003013 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003014 return false;
3015 }
3016
3017 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3018 if (wback && BitIsClear (registers, n))
3019 {
Caroline Tice85aab332011-02-08 23:56:10 +00003020 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3021 if (!success)
3022 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003023
3024 offset = addr_byte_size * BitCount (registers);
3025 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003026 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003027 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003028 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3029 return false;
3030 }
3031
3032 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3033 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003034 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003035 }
3036 return true;
3037}
Caroline Tice0b29e242011-02-08 23:16:02 +00003038
Johnny Chenef21b592011-02-10 01:52:38 +00003039// Load Register (immediate) calculates an address from a base register value and
3040// an immediate offset, loads a word from memory, and writes to a register.
3041// LDR (immediate, Thumb)
3042bool
3043EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3044{
3045#if 0
3046 // ARM pseudo code...
3047 if (ConditionPassed())
3048 {
3049 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3050 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3051 address = if index then offset_addr else R[n];
3052 data = MemU[address,4];
3053 if wback then R[n] = offset_addr;
3054 if t == 15 then
3055 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3056 elsif UnalignedSupport() || address<1:0> = '00' then
3057 R[t] = data;
3058 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3059 }
3060#endif
3061
3062 bool success = false;
3063 const uint32_t opcode = OpcodeAsUnsigned (&success);
3064 if (!success)
3065 return false;
3066
3067 if (ConditionPassed())
3068 {
3069 uint32_t Rt; // the destination register
3070 uint32_t Rn; // the base register
3071 uint32_t imm32; // the immediate offset used to form the address
3072 addr_t offset_addr; // the offset address
3073 addr_t address; // the calculated address
3074 uint32_t data; // the literal data value from memory load
3075 bool add, index, wback;
3076 switch (encoding) {
3077 case eEncodingT1:
3078 Rt = Bits32(opcode, 5, 3);
3079 Rn = Bits32(opcode, 2, 0);
3080 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3081 // index = TRUE; add = TRUE; wback = FALSE
3082 add = true;
3083 index = true;
3084 wback = false;
3085 break;
3086 default:
3087 return false;
3088 }
3089 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3090 if (!success)
3091 return false;
3092 if (add)
3093 offset_addr = base + imm32;
3094 else
3095 offset_addr = base - imm32;
3096
3097 address = (index ? offset_addr : base);
3098
3099 if (wback)
3100 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003101 EmulateInstruction::Context ctx;
3102 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3103 Register dwarf_reg;
3104 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3105 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3106
Johnny Chenef21b592011-02-10 01:52:38 +00003107 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3108 return false;
3109 }
3110
3111 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003112 EmulateInstruction::Context context;
3113 context.type = EmulateInstruction::eContextImmediate;
3114 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003115
3116 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003117 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003118 if (!success)
3119 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003120
3121 if (Rt == 15)
3122 {
3123 if (Bits32(address, 1, 0) == 0)
3124 {
Johnny Chen668b4512011-02-15 21:08:58 +00003125 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003126 return false;
3127 }
3128 else
3129 return false;
3130 }
3131 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3132 {
3133 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3134 return false;
3135 }
3136 else
3137 return false;
3138 }
3139 return true;
3140}
3141
Caroline Ticeaf556562011-02-15 18:42:15 +00003142// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3143// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3144// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003145bool
3146EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3147{
3148#if 0
3149 if ConditionPassed() then
3150 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3151 address = R[n];
3152
3153 for i = 0 to 14
3154 if registers<i> == ’1’ then
3155 if i == n && wback && i != LowestSetBit(registers) then
3156 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3157 else
3158 MemA[address,4] = R[i];
3159 address = address + 4;
3160
3161 if registers<15> == ’1’ then // Only possible for encoding A1
3162 MemA[address,4] = PCStoreValue();
3163 if wback then R[n] = R[n] + 4*BitCount(registers);
3164#endif
3165
3166 bool success = false;
3167 const uint32_t opcode = OpcodeAsUnsigned (&success);
3168 if (!success)
3169 return false;
3170
3171 if (ConditionPassed ())
3172 {
3173 uint32_t n;
3174 uint32_t registers = 0;
3175 bool wback;
3176 const uint32_t addr_byte_size = GetAddressByteSize();
3177
3178 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3179 switch (encoding)
3180 {
3181 case eEncodingT1:
3182 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3183 n = Bits32 (opcode, 10, 8);
3184 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003185 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003186 wback = true;
3187
3188 // if BitCount(registers) < 1 then UNPREDICTABLE;
3189 if (BitCount (registers) < 1)
3190 return false;
3191
3192 break;
3193
3194 case eEncodingT2:
3195 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3196 n = Bits32 (opcode, 19, 16);
3197 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003198 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003199 wback = BitIsSet (opcode, 21);
3200
3201 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3202 if ((n == 15) || (BitCount (registers) < 2))
3203 return false;
3204
3205 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3206 if (wback && BitIsSet (registers, n))
3207 return false;
3208
3209 break;
3210
3211 case eEncodingA1:
3212 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3213 n = Bits32 (opcode, 19, 16);
3214 registers = Bits32 (opcode, 15, 0);
3215 wback = BitIsSet (opcode, 21);
3216
3217 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3218 if ((n == 15) || (BitCount (registers) < 1))
3219 return false;
3220
3221 break;
3222
3223 default:
3224 return false;
3225 }
3226
3227 // address = R[n];
3228 int32_t offset = 0;
3229 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3230 if (!success)
3231 return false;
3232
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003233 EmulateInstruction::Context context;
3234 context.type = EmulateInstruction::eContextRegisterStore;
3235 Register base_reg;
3236 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003237
3238 // for i = 0 to 14
3239 for (int i = 0; i < 14; ++i)
3240 {
3241 int lowest_set_bit = 14;
3242 // if registers<i> == ’1’ then
3243 if (BitIsSet (registers, i))
3244 {
3245 if (i < lowest_set_bit)
3246 lowest_set_bit = i;
3247 // if i == n && wback && i != LowestSetBit(registers) then
3248 if ((i == n) && wback && (i != lowest_set_bit))
3249 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3250 WriteBits32UnknownToMemory (address + offset);
3251 else
3252 {
3253 // MemA[address,4] = R[i];
3254 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3255 if (!success)
3256 return false;
3257
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003258 Register data_reg;
3259 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3260 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003261 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003262 return false;
3263 }
3264
3265 // address = address + 4;
3266 offset += addr_byte_size;
3267 }
3268 }
3269
3270 // if registers<15> == ’1’ then // Only possible for encoding A1
3271 // MemA[address,4] = PCStoreValue();
3272 if (BitIsSet (registers, 15))
3273 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003274 Register pc_reg;
3275 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3276 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003277 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3278 if (!success)
3279 return false;
3280
Caroline Ticecc96eb52011-02-17 19:20:40 +00003281 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003282 return false;
3283 }
3284
3285 // if wback then R[n] = R[n] + 4*BitCount(registers);
3286 if (wback)
3287 {
3288 offset = addr_byte_size * BitCount (registers);
3289 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003290 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003291 addr_t data = address + offset;
3292 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3293 return false;
3294 }
3295 }
3296 return true;
3297}
3298
Caroline Ticeaf556562011-02-15 18:42:15 +00003299// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3300// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3301// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003302bool
3303EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3304{
3305#if 0
3306 if ConditionPassed() then
3307 EncodingSpecificOperations();
3308 address = R[n] - 4*BitCount(registers) + 4;
3309
3310 for i = 0 to 14
3311 if registers<i> == ’1’ then
3312 if i == n && wback && i != LowestSetBit(registers) then
3313 MemA[address,4] = bits(32) UNKNOWN;
3314 else
3315 MemA[address,4] = R[i];
3316 address = address + 4;
3317
3318 if registers<15> == ’1’ then
3319 MemA[address,4] = PCStoreValue();
3320
3321 if wback then R[n] = R[n] - 4*BitCount(registers);
3322#endif
3323
3324 bool success = false;
3325 const uint32_t opcode = OpcodeAsUnsigned (&success);
3326 if (!success)
3327 return false;
3328
3329 if (ConditionPassed ())
3330 {
3331 uint32_t n;
3332 uint32_t registers = 0;
3333 bool wback;
3334 const uint32_t addr_byte_size = GetAddressByteSize();
3335
3336 // EncodingSpecificOperations();
3337 switch (encoding)
3338 {
3339 case eEncodingA1:
3340 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3341 n = Bits32 (opcode, 19, 16);
3342 registers = Bits32 (opcode, 15, 0);
3343 wback = BitIsSet (opcode, 21);
3344
3345 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3346 if ((n == 15) || (BitCount (registers) < 1))
3347 return false;
3348 break;
3349 default:
3350 return false;
3351 }
3352
3353 // address = R[n] - 4*BitCount(registers) + 4;
3354 int32_t offset = 0;
3355 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3356 if (!success)
3357 return false;
3358
3359 address = address - (addr_byte_size * BitCount (registers)) + 4;
3360
3361 EmulateInstruction::Context context;
3362 context.type = EmulateInstruction::eContextRegisterStore;
3363 Register base_reg;
3364 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3365
3366 // for i = 0 to 14
3367 for (int i = 0; i < 14; ++i)
3368 {
3369 int lowest_bit_set = 14;
3370 // if registers<i> == ’1’ then
3371 if (BitIsSet (registers, i))
3372 {
3373 if (i < lowest_bit_set)
3374 lowest_bit_set = i;
3375 //if i == n && wback && i != LowestSetBit(registers) then
3376 if ((i == n) && wback && (i != lowest_bit_set))
3377 // MemA[address,4] = bits(32) UNKNOWN;
3378 WriteBits32UnknownToMemory (address + offset);
3379 else
3380 {
3381 // MemA[address,4] = R[i];
3382 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3383 if (!success)
3384 return false;
3385
3386 Register data_reg;
3387 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3388 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003389 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003390 return false;
3391 }
3392
3393 // address = address + 4;
3394 offset += addr_byte_size;
3395 }
3396 }
3397
3398 // if registers<15> == ’1’ then
3399 // MemA[address,4] = PCStoreValue();
3400 if (BitIsSet (registers, 15))
3401 {
3402 Register pc_reg;
3403 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3404 context.SetRegisterPlusOffset (pc_reg, 8);
3405 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3406 if (!success)
3407 return false;
3408
Caroline Ticecc96eb52011-02-17 19:20:40 +00003409 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003410 return false;
3411 }
3412
3413 // if wback then R[n] = R[n] - 4*BitCount(registers);
3414 if (wback)
3415 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003416 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003417 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3418 context.SetImmediateSigned (offset);
3419 addr_t data = address + offset;
3420 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3421 return false;
3422 }
3423 }
3424 return true;
3425}
3426
Caroline Ticeaf556562011-02-15 18:42:15 +00003427// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3428// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3429// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003430bool
3431EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3432{
3433#if 0
3434 if ConditionPassed() then
3435 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3436 address = R[n] - 4*BitCount(registers);
3437
3438 for i = 0 to 14
3439 if registers<i> == ’1’ then
3440 if i == n && wback && i != LowestSetBit(registers) then
3441 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3442 else
3443 MemA[address,4] = R[i];
3444 address = address + 4;
3445
3446 if registers<15> == ’1’ then // Only possible for encoding A1
3447 MemA[address,4] = PCStoreValue();
3448
3449 if wback then R[n] = R[n] - 4*BitCount(registers);
3450#endif
3451
3452
3453 bool success = false;
3454 const uint32_t opcode = OpcodeAsUnsigned (&success);
3455 if (!success)
3456 return false;
3457
3458 if (ConditionPassed ())
3459 {
3460 uint32_t n;
3461 uint32_t registers = 0;
3462 bool wback;
3463 const uint32_t addr_byte_size = GetAddressByteSize();
3464
3465 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3466 switch (encoding)
3467 {
3468 case eEncodingT1:
3469 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3470 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3471 {
3472 // See PUSH
3473 }
3474 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3475 n = Bits32 (opcode, 19, 16);
3476 registers = Bits32 (opcode, 15, 0);
3477 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3478 wback = BitIsSet (opcode, 21);
3479 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3480 if ((n == 15) || BitCount (registers) < 2)
3481 return false;
3482 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3483 if (wback && BitIsSet (registers, n))
3484 return false;
3485 break;
3486
3487 case eEncodingA1:
3488 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3489 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3490 {
3491 // See Push
3492 }
3493 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3494 n = Bits32 (opcode, 19, 16);
3495 registers = Bits32 (opcode, 15, 0);
3496 wback = BitIsSet (opcode, 21);
3497 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3498 if ((n == 15) || BitCount (registers) < 1)
3499 return false;
3500 break;
3501
3502 default:
3503 return false;
3504 }
3505
3506 // address = R[n] - 4*BitCount(registers);
3507
3508 int32_t offset = 0;
3509 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3510 if (!success)
3511 return false;
3512
3513 address = address - (addr_byte_size * BitCount (registers));
3514
3515 EmulateInstruction::Context context;
3516 context.type = EmulateInstruction::eContextRegisterStore;
3517 Register base_reg;
3518 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3519
3520 // for i = 0 to 14
3521 for (int i = 0; i < 14; ++i)
3522 {
3523 uint32_t lowest_set_bit = 14;
3524 // if registers<i> == ’1’ then
3525 if (BitIsSet (registers, i))
3526 {
3527 if (i < lowest_set_bit)
3528 lowest_set_bit = i;
3529 // if i == n && wback && i != LowestSetBit(registers) then
3530 if ((i == n) && wback && (i != lowest_set_bit))
3531 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3532 WriteBits32UnknownToMemory (address + offset);
3533 else
3534 {
3535 // MemA[address,4] = R[i];
3536 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3537 if (!success)
3538 return false;
3539
3540 Register data_reg;
3541 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3542 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003543 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003544 return false;
3545 }
3546
3547 // address = address + 4;
3548 offset += addr_byte_size;
3549 }
3550 }
3551
3552 // if registers<15> == ’1’ then // Only possible for encoding A1
3553 // MemA[address,4] = PCStoreValue();
3554 if (BitIsSet (registers, 15))
3555 {
3556 Register pc_reg;
3557 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3558 context.SetRegisterPlusOffset (pc_reg, 8);
3559 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3560 if (!success)
3561 return false;
3562
Caroline Ticecc96eb52011-02-17 19:20:40 +00003563 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003564 return false;
3565 }
3566
3567 // if wback then R[n] = R[n] - 4*BitCount(registers);
3568 if (wback)
3569 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003570 offset = (addr_byte_size * BitCount (registers)) * -1;
3571 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3572 context.SetImmediateSigned (offset);
3573 addr_t data = address + offset;
3574 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3575 return false;
3576 }
3577 }
3578 return true;
3579}
3580
3581// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3582// from a base register. The consecutive memory locations start just above this address, and the address of the last
3583// of those locations can optionally be written back to the base register.
3584bool
3585EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3586{
3587#if 0
3588 if ConditionPassed() then
3589 EncodingSpecificOperations();
3590 address = R[n] + 4;
3591
3592 for i = 0 to 14
3593 if registers<i> == ’1’ then
3594 if i == n && wback && i != LowestSetBit(registers) then
3595 MemA[address,4] = bits(32) UNKNOWN;
3596 else
3597 MemA[address,4] = R[i];
3598 address = address + 4;
3599
3600 if registers<15> == ’1’ then
3601 MemA[address,4] = PCStoreValue();
3602
3603 if wback then R[n] = R[n] + 4*BitCount(registers);
3604#endif
3605
3606 bool success = false;
3607 const uint32_t opcode = OpcodeAsUnsigned (&success);
3608 if (!success)
3609 return false;
3610
3611 if (ConditionPassed())
3612 {
3613 uint32_t n;
3614 uint32_t registers = 0;
3615 bool wback;
3616 const uint32_t addr_byte_size = GetAddressByteSize();
3617
3618 // EncodingSpecificOperations();
3619 switch (encoding)
3620 {
3621 case eEncodingA1:
3622 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3623 n = Bits32 (opcode, 19, 16);
3624 registers = Bits32 (opcode, 15, 0);
3625 wback = BitIsSet (opcode, 21);
3626
3627 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3628 if ((n == 15) && (BitCount (registers) < 1))
3629 return false;
3630 break;
3631 default:
3632 return false;
3633 }
3634 // address = R[n] + 4;
3635
3636 int32_t offset = 0;
3637 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3638 if (!success)
3639 return false;
3640
3641 address = address + addr_byte_size;
3642
3643 EmulateInstruction::Context context;
3644 context.type = EmulateInstruction::eContextRegisterStore;
3645 Register base_reg;
3646 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3647
3648 uint32_t lowest_set_bit = 14;
3649 // for i = 0 to 14
3650 for (int i = 0; i < 14; ++i)
3651 {
3652 // if registers<i> == ’1’ then
3653 if (BitIsSet (registers, i))
3654 {
3655 if (i < lowest_set_bit)
3656 lowest_set_bit = i;
3657 // if i == n && wback && i != LowestSetBit(registers) then
3658 if ((i == n) && wback && (i != lowest_set_bit))
3659 // MemA[address,4] = bits(32) UNKNOWN;
3660 WriteBits32UnknownToMemory (address + offset);
3661 // else
3662 else
3663 {
3664 // MemA[address,4] = R[i];
3665 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3666 if (!success)
3667 return false;
3668
3669 Register data_reg;
3670 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3671 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003672 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003673 return false;
3674 }
3675
3676 // address = address + 4;
3677 offset += addr_byte_size;
3678 }
3679 }
3680
3681 // if registers<15> == ’1’ then
3682 // MemA[address,4] = PCStoreValue();
3683 if (BitIsSet (registers, 15))
3684 {
3685 Register pc_reg;
3686 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3687 context.SetRegisterPlusOffset (pc_reg, 8);
3688 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3689 if (!success)
3690 return false;
3691
Caroline Ticecc96eb52011-02-17 19:20:40 +00003692 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003693 return false;
3694 }
3695
3696 // if wback then R[n] = R[n] + 4*BitCount(registers);
3697 if (wback)
3698 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003699 offset = addr_byte_size * BitCount (registers);
3700 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3701 context.SetImmediateSigned (offset);
3702 addr_t data = address + offset;
3703 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3704 return false;
3705 }
3706 }
3707 return true;
3708}
Caroline Tice7fac8572011-02-15 22:53:54 +00003709
3710// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3711// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3712bool
3713EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3714{
3715#if 0
3716 if ConditionPassed() then
3717 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3718 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3719 address = if index then offset_addr else R[n];
3720 if UnalignedSupport() || address<1:0> == ’00’ then
3721 MemU[address,4] = R[t];
3722 else // Can only occur before ARMv7
3723 MemU[address,4] = bits(32) UNKNOWN;
3724 if wback then R[n] = offset_addr;
3725#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003726
Caroline Tice7fac8572011-02-15 22:53:54 +00003727 bool success = false;
3728 const uint32_t opcode = OpcodeAsUnsigned (&success);
3729 if (!success)
3730 return false;
3731
3732 if (ConditionPassed())
3733 {
3734 const uint32_t addr_byte_size = GetAddressByteSize();
3735
3736 uint32_t t;
3737 uint32_t n;
3738 uint32_t imm32;
3739 bool index;
3740 bool add;
3741 bool wback;
3742 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3743 switch (encoding)
3744 {
3745 case eEncodingT1:
3746 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3747 t = Bits32 (opcode, 2, 0);
3748 n = Bits32 (opcode, 5, 3);
3749 imm32 = Bits32 (opcode, 10, 6) << 2;
3750
3751 // index = TRUE; add = TRUE; wback = FALSE;
3752 index = true;
3753 add = false;
3754 wback = false;
3755 break;
3756
3757 case eEncodingT2:
3758 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3759 t = Bits32 (opcode, 10, 8);
3760 n = 13;
3761 imm32 = Bits32 (opcode, 7, 0) << 2;
3762
3763 // index = TRUE; add = TRUE; wback = FALSE;
3764 index = true;
3765 add = true;
3766 wback = false;
3767 break;
3768
3769 case eEncodingT3:
3770 // if Rn == ’1111’ then UNDEFINED;
3771 if (Bits32 (opcode, 19, 16) == 15)
3772 return false;
3773
3774 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3775 t = Bits32 (opcode, 15, 12);
3776 n = Bits32 (opcode, 19, 16);
3777 imm32 = Bits32 (opcode, 11, 0);
3778
3779 // index = TRUE; add = TRUE; wback = FALSE;
3780 index = true;
3781 add = true;
3782 wback = false;
3783
3784 // if t == 15 then UNPREDICTABLE;
3785 if (t == 15)
3786 return false;
3787 break;
3788
3789 case eEncodingT4:
3790 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3791 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3792 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3793 if ((Bits32 (opcode, 19, 16) == 15)
3794 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3795 return false;
3796
3797 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3798 t = Bits32 (opcode, 15, 12);
3799 n = Bits32 (opcode, 19, 16);
3800 imm32 = Bits32 (opcode, 7, 0);
3801
3802 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3803 index = BitIsSet (opcode, 10);
3804 add = BitIsSet (opcode, 9);
3805 wback = BitIsSet (opcode, 8);
3806
3807 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3808 if ((t == 15) || (wback && (n == t)))
3809 return false;
3810 break;
3811
3812 default:
3813 return false;
3814 }
3815
3816 addr_t offset_addr;
3817 addr_t address;
3818
3819 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3820 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3821 if (!success)
3822 return false;
3823
3824 if (add)
3825 offset_addr = base_address + imm32;
3826 else
3827 offset_addr = base_address - imm32;
3828
3829 // address = if index then offset_addr else R[n];
3830 if (index)
3831 address = offset_addr;
3832 else
3833 address = base_address;
3834
3835 EmulateInstruction::Context context;
3836 context.type = eContextRegisterStore;
3837 Register base_reg;
3838 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3839
3840 // if UnalignedSupport() || address<1:0> == ’00’ then
3841 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3842 {
3843 // MemU[address,4] = R[t];
3844 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3845 if (!success)
3846 return false;
3847
3848 Register data_reg;
3849 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3850 int32_t offset = address - base_address;
3851 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003852 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003853 return false;
3854 }
3855 else
3856 {
3857 // MemU[address,4] = bits(32) UNKNOWN;
3858 WriteBits32UnknownToMemory (address);
3859 }
3860
3861 // if wback then R[n] = offset_addr;
3862 if (wback)
3863 {
3864 context.type = eContextRegisterLoad;
3865 context.SetAddress (offset_addr);
3866 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3867 return false;
3868 }
3869 }
3870 return true;
3871}
Caroline Ticeaf556562011-02-15 18:42:15 +00003872
Caroline Tice3fd63e92011-02-16 00:33:43 +00003873// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3874// word from a register to memory. The offset register value can optionally be shifted.
3875bool
3876EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3877{
3878#if 0
3879 if ConditionPassed() then
3880 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3881 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3882 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3883 address = if index then offset_addr else R[n];
3884 if t == 15 then // Only possible for encoding A1
3885 data = PCStoreValue();
3886 else
3887 data = R[t];
3888 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3889 MemU[address,4] = data;
3890 else // Can only occur before ARMv7
3891 MemU[address,4] = bits(32) UNKNOWN;
3892 if wback then R[n] = offset_addr;
3893#endif
3894
3895 bool success = false;
3896 const uint32_t opcode = OpcodeAsUnsigned (&success);
3897 if (!success)
3898 return false;
3899
3900 if (ConditionPassed())
3901 {
3902 const uint32_t addr_byte_size = GetAddressByteSize();
3903
3904 uint32_t t;
3905 uint32_t n;
3906 uint32_t m;
3907 ARM_ShifterType shift_t;
3908 uint32_t shift_n;
3909 bool index;
3910 bool add;
3911 bool wback;
3912
3913 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3914 switch (encoding)
3915 {
3916 case eEncodingT1:
3917 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3918 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3919 t = Bits32 (opcode, 2, 0);
3920 n = Bits32 (opcode, 5, 3);
3921 m = Bits32 (opcode, 8, 6);
3922
3923 // index = TRUE; add = TRUE; wback = FALSE;
3924 index = true;
3925 add = true;
3926 wback = false;
3927
3928 // (shift_t, shift_n) = (SRType_LSL, 0);
3929 shift_t = SRType_LSL;
3930 shift_n = 0;
3931 break;
3932
3933 case eEncodingT2:
3934 // if Rn == ’1111’ then UNDEFINED;
3935 if (Bits32 (opcode, 19, 16) == 15)
3936 return false;
3937
3938 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3939 t = Bits32 (opcode, 15, 12);
3940 n = Bits32 (opcode, 19, 16);
3941 m = Bits32 (opcode, 3, 0);
3942
3943 // index = TRUE; add = TRUE; wback = FALSE;
3944 index = true;
3945 add = true;
3946 wback = false;
3947
3948 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3949 shift_t = SRType_LSL;
3950 shift_n = Bits32 (opcode, 5, 4);
3951
3952 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3953 if ((t == 15) || (BadReg (m)))
3954 return false;
3955 break;
3956
3957 case eEncodingA1:
3958 {
3959 // if P == ’0’ && W == ’1’ then SEE STRT;
3960 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3961 t = Bits32 (opcode, 15, 12);
3962 n = Bits32 (opcode, 19, 16);
3963 m = Bits32 (opcode, 3, 0);
3964
3965 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3966 index = BitIsSet (opcode, 24);
3967 add = BitIsSet (opcode, 23);
3968 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3969
3970 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3971 uint32_t typ = Bits32 (opcode, 6, 5);
3972 uint32_t imm5 = Bits32 (opcode, 11, 7);
3973 shift_n = DecodeImmShift(typ, imm5, shift_t);
3974
3975 // if m == 15 then UNPREDICTABLE;
3976 if (m == 15)
3977 return false;
3978
3979 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3980 if (wback && ((n == 15) || (n == t)))
3981 return false;
3982
3983 break;
3984 }
3985 default:
3986 return false;
3987 }
3988
3989 addr_t offset_addr;
3990 addr_t address;
3991 int32_t offset = 0;
3992
3993 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3994 if (!success)
3995 return false;
3996
3997 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3998 if (!success)
3999 return false;
4000
4001 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4002 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
4003
4004 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4005 if (add)
4006 offset_addr = base_address + offset;
4007 else
4008 offset_addr = base_address - offset;
4009
4010 // address = if index then offset_addr else R[n];
4011 if (index)
4012 address = offset_addr;
4013 else
4014 address = base_address;
4015
4016 uint32_t data;
4017 // if t == 15 then // Only possible for encoding A1
4018 if (t == 15)
4019 // data = PCStoreValue();
4020 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4021 else
4022 // data = R[t];
4023 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4024
4025 if (!success)
4026 return false;
4027
4028 EmulateInstruction::Context context;
4029 context.type = eContextRegisterStore;
4030
4031 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4032 if (UnalignedSupport ()
4033 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4034 || CurrentInstrSet() == eModeARM)
4035 {
4036 // MemU[address,4] = data;
4037
4038 Register base_reg;
4039 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4040
4041 Register data_reg;
4042 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4043
4044 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004045 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004046 return false;
4047
4048 }
4049 else
4050 // MemU[address,4] = bits(32) UNKNOWN;
4051 WriteBits32UnknownToMemory (address);
4052
4053 // if wback then R[n] = offset_addr;
4054 if (wback)
4055 {
4056 context.type = eContextRegisterLoad;
4057 context.SetAddress (offset_addr);
4058 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4059 return false;
4060 }
4061
4062 }
4063 return true;
4064}
Caroline Tice73a29de2011-02-16 20:22:22 +00004065
4066bool
4067EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4068{
4069#if 0
4070 if ConditionPassed() then
4071 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4072 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4073 address = if index then offset_addr else R[n];
4074 MemU[address,1] = R[t]<7:0>;
4075 if wback then R[n] = offset_addr;
4076#endif
4077
4078
4079 bool success = false;
4080 const uint32_t opcode = OpcodeAsUnsigned (&success);
4081 if (!success)
4082 return false;
4083
4084 if (ConditionPassed ())
4085 {
4086 uint32_t t;
4087 uint32_t n;
4088 uint32_t imm32;
4089 bool index;
4090 bool add;
4091 bool wback;
4092 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4093 switch (encoding)
4094 {
4095 case eEncodingT1:
4096 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4097 t = Bits32 (opcode, 2, 0);
4098 n = Bits32 (opcode, 5, 3);
4099 imm32 = Bits32 (opcode, 10, 6);
4100
4101 // index = TRUE; add = TRUE; wback = FALSE;
4102 index = true;
4103 add = true;
4104 wback = false;
4105 break;
4106
4107 case eEncodingT2:
4108 // if Rn == ’1111’ then UNDEFINED;
4109 if (Bits32 (opcode, 19, 16) == 15)
4110 return false;
4111
4112 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4113 t = Bits32 (opcode, 15, 12);
4114 n = Bits32 (opcode, 19, 16);
4115 imm32 = Bits32 (opcode, 11, 0);
4116
4117 // index = TRUE; add = TRUE; wback = FALSE;
4118 index = true;
4119 add = true;
4120 wback = false;
4121
4122 // if BadReg(t) then UNPREDICTABLE;
4123 if (BadReg (t))
4124 return false;
4125 break;
4126
4127 case eEncodingT3:
4128 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4129 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4130 if (Bits32 (opcode, 19, 16) == 15)
4131 return false;
4132
4133 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4134 t = Bits32 (opcode, 15, 12);
4135 n = Bits32 (opcode, 19, 16);
4136 imm32 = Bits32 (opcode, 7, 0);
4137
4138 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4139 index = BitIsSet (opcode, 10);
4140 add = BitIsSet (opcode, 9);
4141 wback = BitIsSet (opcode, 8);
4142
4143 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4144 if ((BadReg (t)) || (wback && (n == t)))
4145 return false;
4146 break;
4147
4148 default:
4149 return false;
4150 }
4151
4152 addr_t offset_addr;
4153 addr_t address;
4154 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4155 if (!success)
4156 return false;
4157
4158 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4159 if (add)
4160 offset_addr = base_address + imm32;
4161 else
4162 offset_addr = base_address - imm32;
4163
4164 // address = if index then offset_addr else R[n];
4165 if (index)
4166 address = offset_addr;
4167 else
4168 address = base_address;
4169
Caroline Ticecc96eb52011-02-17 19:20:40 +00004170 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004171 Register base_reg;
4172 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4173
4174 Register data_reg;
4175 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4176
4177 EmulateInstruction::Context context;
4178 context.type = eContextRegisterStore;
4179 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4180
4181 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4182 if (!success)
4183 return false;
4184
4185 data = Bits32 (data, 7, 0);
4186
Caroline Ticecc96eb52011-02-17 19:20:40 +00004187 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004188 return false;
4189
4190 // if wback then R[n] = offset_addr;
4191 if (wback)
4192 {
4193 context.type = eContextRegisterLoad;
4194 context.SetAddress (offset_addr);
4195 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4196 return false;
4197 }
4198
4199 }
4200
4201 return true;
4202}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004203
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004204EmulateInstructionARM::ARMOpcode*
4205EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004206{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004207 static ARMOpcode
4208 g_arm_opcodes[] =
4209 {
4210 //----------------------------------------------------------------------
4211 // Prologue instructions
4212 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004213
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004214 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004215 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
4216 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004217
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004218 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004219 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
4220 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004221 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00004222 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
4223 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
4224 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004225
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004226 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004227 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004228
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004229 // push one register
4230 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004231 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004232
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004233 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004234 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4235 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004236
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004237 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004238 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004239 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004240
Johnny Chenc28a76d2011-02-01 18:51:48 +00004241 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
4242 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004243 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004244 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4245
4246 //----------------------------------------------------------------------
4247 // Supervisor Call (previously Software Interrupt)
4248 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004249 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4250
4251 //----------------------------------------------------------------------
4252 // Branch instructions
4253 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004254 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004255 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4256 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4257 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4258 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004259 // for example, "bx lr"
4260 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004261
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004262 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004263 // Data-processing instructions
4264 //----------------------------------------------------------------------
4265 // move bitwise not
4266 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004267 // asr (immediate)
4268 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004269 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004270 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004271 // lsl (immediate)
4272 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4273 // lsl (register)
4274 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4275 // lsr (immediate)
4276 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4277 // lsr (register)
4278 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004279 // rrx is a special case encoding of ror (immediate)
4280 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4281 // ror (immediate)
4282 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4283 // ror (register)
4284 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004285
4286 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004287 // Load instructions
4288 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004289 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004290 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004291 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004292 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4293
4294 //----------------------------------------------------------------------
4295 // Store instructions
4296 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004297 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004298 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004299 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004300 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4301 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004302
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004303
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004304 };
4305 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4306
4307 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4308 {
4309 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4310 return &g_arm_opcodes[i];
4311 }
4312 return NULL;
4313}
Greg Clayton64c84432011-01-21 22:02:52 +00004314
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004315
4316EmulateInstructionARM::ARMOpcode*
4317EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004318{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004319
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004320 static ARMOpcode
4321 g_thumb_opcodes[] =
4322 {
4323 //----------------------------------------------------------------------
4324 // Prologue instructions
4325 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004326
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004327 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00004328 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004329 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
4330 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004331
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004332 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00004333 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004334 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00004335 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004336 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
4337 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004338
Johnny Chenc9de9102011-02-11 19:12:30 +00004339 // PC-relative load into register (see also EmulateAddSPRm)
4340 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004341
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004342 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00004343 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
4344 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004345 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
4346 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004347
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004348 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004349 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4350 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004351
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004352 //----------------------------------------------------------------------
4353 // Epilogue instructions
4354 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004355
Johnny Chenc28a76d2011-02-01 18:51:48 +00004356 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
4357 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00004358 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
4359 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
4360 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4361 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004362
4363 //----------------------------------------------------------------------
4364 // Supervisor Call (previously Software Interrupt)
4365 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004366 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4367
4368 //----------------------------------------------------------------------
4369 // If Then makes up to four following instructions conditional.
4370 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004371 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4372
4373 //----------------------------------------------------------------------
4374 // Branch instructions
4375 //----------------------------------------------------------------------
4376 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4377 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4378 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004379 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004380 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004381 // J1 == J2 == 1
4382 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4383 // J1 == J2 == 1
4384 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4385 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004386 // for example, "bx lr"
4387 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004388 // compare and branch
4389 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00004390 // table branch byte
4391 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
4392 // table branch halfword
4393 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004394
4395 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004396 // Data-processing instructions
4397 //----------------------------------------------------------------------
Johnny Chend761dcf2011-02-17 22:03:29 +00004398 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004399 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chend761dcf2011-02-17 22:03:29 +00004400 // Can update PC!
4401 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddReg, "add<c> <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004402 // move from high register to high register
4403 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
4404 // move from low register to low register
4405 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004406 // move immediate
4407 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
4408 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004409 // move bitwise not
4410 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004411 // compare a register with immediate
4412 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004413 // compare Rn with Rm (Rn and Rm both from r0-r7)
4414 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
4415 // compare Rn with Rm (Rn and Rm not both from r0-r7)
4416 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004417 // asr (immediate)
4418 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004419 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004420 // asr (register)
4421 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4422 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004423 // lsl (immediate)
4424 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4425 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4426 // lsl (register)
4427 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4428 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4429 // lsr (immediate)
4430 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4431 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4432 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004433 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004434 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004435 // rrx is a special case encoding of ror (immediate)
4436 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4437 // ror (immediate)
4438 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4439 // ror (register)
4440 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4441 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004442
4443 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004444 // Load instructions
4445 //----------------------------------------------------------------------
4446 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004447 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004448 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004449 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4450 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004451 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4452
4453 //----------------------------------------------------------------------
4454 // Store instructions
4455 //----------------------------------------------------------------------
4456 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004457 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004458 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4459 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4460 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4461 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004462 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4463 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004464 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4465 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4466 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4467 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004468 };
4469
4470 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4471 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4472 {
4473 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4474 return &g_thumb_opcodes[i];
4475 }
4476 return NULL;
4477}
Greg Clayton64c84432011-01-21 22:02:52 +00004478
Greg Clayton31e2a382011-01-30 20:03:56 +00004479bool
Greg Clayton395fc332011-02-15 21:59:32 +00004480EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004481{
4482 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004483 const char *arch_cstr = arch.AsCString ();
4484 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004485 {
Greg Clayton395fc332011-02-15 21:59:32 +00004486 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4487 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4488 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4489 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4490 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4491 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4492 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4493 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4494 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4495 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004496 }
4497 return m_arm_isa != 0;
4498}
4499
4500
Greg Clayton64c84432011-01-21 22:02:52 +00004501bool
4502EmulateInstructionARM::ReadInstruction ()
4503{
4504 bool success = false;
4505 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4506 if (success)
4507 {
4508 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4509 if (success)
4510 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004511 Context read_inst_context;
4512 read_inst_context.type = eContextReadOpcode;
4513 read_inst_context.SetNoArgs ();
4514
Greg Clayton64c84432011-01-21 22:02:52 +00004515 if (m_inst_cpsr & MASK_CPSR_T)
4516 {
4517 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004518 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004519
4520 if (success)
4521 {
4522 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4523 {
4524 m_inst.opcode_type = eOpcode16;
4525 m_inst.opcode.inst16 = thumb_opcode;
4526 }
4527 else
4528 {
4529 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004530 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004531 }
4532 }
4533 }
4534 else
4535 {
4536 m_inst_mode = eModeARM;
4537 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004538 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004539 }
4540 }
4541 }
4542 if (!success)
4543 {
4544 m_inst_mode = eModeInvalid;
4545 m_inst_pc = LLDB_INVALID_ADDRESS;
4546 }
4547 return success;
4548}
4549
Johnny Chenee9b1f72011-02-09 01:00:31 +00004550uint32_t
4551EmulateInstructionARM::ArchVersion ()
4552{
4553 return m_arm_isa;
4554}
4555
Greg Clayton64c84432011-01-21 22:02:52 +00004556bool
4557EmulateInstructionARM::ConditionPassed ()
4558{
4559 if (m_inst_cpsr == 0)
4560 return false;
4561
4562 const uint32_t cond = CurrentCond ();
4563
4564 if (cond == UINT32_MAX)
4565 return false;
4566
4567 bool result = false;
4568 switch (UnsignedBits(cond, 3, 1))
4569 {
4570 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4571 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4572 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4573 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4574 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4575 case 5:
4576 {
4577 bool n = (m_inst_cpsr & MASK_CPSR_N);
4578 bool v = (m_inst_cpsr & MASK_CPSR_V);
4579 result = n == v;
4580 }
4581 break;
4582 case 6:
4583 {
4584 bool n = (m_inst_cpsr & MASK_CPSR_N);
4585 bool v = (m_inst_cpsr & MASK_CPSR_V);
4586 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4587 }
4588 break;
4589 case 7:
4590 result = true;
4591 break;
4592 }
4593
4594 if (cond & 1)
4595 result = !result;
4596 return result;
4597}
4598
Johnny Chen9ee056b2011-02-08 00:06:35 +00004599uint32_t
4600EmulateInstructionARM::CurrentCond ()
4601{
4602 switch (m_inst_mode)
4603 {
4604 default:
4605 case eModeInvalid:
4606 break;
4607
4608 case eModeARM:
4609 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4610
4611 case eModeThumb:
4612 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4613 // 'cond' field of the encoding.
4614 if (m_inst.opcode_type == eOpcode16 &&
4615 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4616 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4617 {
4618 return Bits32(m_inst.opcode.inst16, 11, 7);
4619 }
4620 else if (m_inst.opcode_type == eOpcode32 &&
4621 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4622 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4623 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4624 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4625 {
4626 return Bits32(m_inst.opcode.inst32, 25, 22);
4627 }
4628
4629 return m_it_session.GetCond();
4630 }
4631 return UINT32_MAX; // Return invalid value
4632}
4633
Johnny Chen9ee056b2011-02-08 00:06:35 +00004634bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004635EmulateInstructionARM::InITBlock()
4636{
4637 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4638}
4639
4640bool
4641EmulateInstructionARM::LastInITBlock()
4642{
4643 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4644}
4645
4646bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004647EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4648{
4649 addr_t target;
4650
Johnny Chenee9b1f72011-02-09 01:00:31 +00004651 // Check the current instruction set.
4652 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004653 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004654 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004655 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004656
Johnny Chen9ee056b2011-02-08 00:06:35 +00004657 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004658 return false;
4659
4660 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004661}
4662
4663// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4664bool
Johnny Chen668b4512011-02-15 21:08:58 +00004665EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004666{
4667 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004668 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4669 // we want to record it and issue a WriteRegister callback so the clients
4670 // can track the mode changes accordingly.
4671 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004672
4673 if (BitIsSet(addr, 0))
4674 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004675 if (CurrentInstrSet() != eModeThumb)
4676 {
4677 SelectInstrSet(eModeThumb);
4678 cpsr_changed = true;
4679 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004680 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004681 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004682 }
4683 else if (BitIsClear(addr, 1))
4684 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004685 if (CurrentInstrSet() != eModeARM)
4686 {
4687 SelectInstrSet(eModeARM);
4688 cpsr_changed = true;
4689 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004690 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004691 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004692 }
4693 else
4694 return false; // address<1:0> == '10' => UNPREDICTABLE
4695
Johnny Chen0f309db2011-02-09 19:11:32 +00004696 if (cpsr_changed)
4697 {
Johnny Chen558133b2011-02-09 23:59:17 +00004698 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004699 return false;
4700 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004701 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004702 return false;
4703
4704 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004705}
Greg Clayton64c84432011-01-21 22:02:52 +00004706
Johnny Chenee9b1f72011-02-09 01:00:31 +00004707// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4708bool
Johnny Chen668b4512011-02-15 21:08:58 +00004709EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004710{
4711 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004712 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004713 else
4714 return BranchWritePC((const Context)context, addr);
4715}
4716
Johnny Chen26863dc2011-02-09 23:43:29 +00004717// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4718bool
Johnny Chen668b4512011-02-15 21:08:58 +00004719EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004720{
4721 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004722 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004723 else
4724 return BranchWritePC((const Context)context, addr);
4725}
4726
Johnny Chenee9b1f72011-02-09 01:00:31 +00004727EmulateInstructionARM::Mode
4728EmulateInstructionARM::CurrentInstrSet ()
4729{
4730 return m_inst_mode;
4731}
4732
4733// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004734// ReadInstruction() is performed. This function has a side effect of updating
4735// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004736bool
4737EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4738{
Johnny Chen558133b2011-02-09 23:59:17 +00004739 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004740 switch (arm_or_thumb)
4741 {
4742 default:
4743 return false;
4744 eModeARM:
4745 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004746 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004747 break;
4748 eModeThumb:
4749 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004750 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004751 break;
4752 }
4753 return true;
4754}
4755
Johnny Chenef21b592011-02-10 01:52:38 +00004756// This function returns TRUE if the processor currently provides support for
4757// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4758// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4759bool
4760EmulateInstructionARM::UnalignedSupport()
4761{
4762 return (ArchVersion() >= ARMv7);
4763}
4764
Johnny Chenbf6ad172011-02-11 01:29:53 +00004765// The main addition and subtraction instructions can produce status information
4766// about both unsigned carry and signed overflow conditions. This status
4767// information can be used to synthesize multi-word additions and subtractions.
4768EmulateInstructionARM::AddWithCarryResult
4769EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4770{
4771 uint32_t result;
4772 uint8_t carry_out;
4773 uint8_t overflow;
4774
4775 uint64_t unsigned_sum = x + y + carry_in;
4776 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4777
4778 result = UnsignedBits(unsigned_sum, 31, 0);
4779 carry_out = (result == unsigned_sum ? 0 : 1);
4780 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4781
4782 AddWithCarryResult res = { result, carry_out, overflow };
4783 return res;
4784}
4785
Johnny Chenca67d1c2011-02-17 01:35:27 +00004786// Write the result to the ARM core register Rd, and optionally update the
4787// condition flags based on the result.
4788//
4789// This helper method tries to encapsulate the following pseudocode from the
4790// ARM Architecture Reference Manual:
4791//
4792// if d == 15 then // Can only occur for encoding A1
4793// ALUWritePC(result); // setflags is always FALSE here
4794// else
4795// R[d] = result;
4796// if setflags then
4797// APSR.N = result<31>;
4798// APSR.Z = IsZeroBit(result);
4799// APSR.C = carry;
4800// // APSR.V unchanged
4801//
4802// In the above case, the API client does not pass in the overflow arg, which
4803// defaults to ~0u.
4804bool
4805EmulateInstructionARM::WriteCoreRegisterWithFlags (Context &context,
4806 const uint32_t result,
4807 const uint32_t Rd,
4808 bool setflags,
4809 const uint32_t carry,
4810 const uint32_t overflow)
4811{
4812 if (Rd == 15)
4813 {
4814 if (!ALUWritePC (context, result))
4815 return false;
4816 }
4817 else
4818 {
4819 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
4820 return false;
4821 if (setflags)
4822 {
4823 m_new_inst_cpsr = m_inst_cpsr;
4824 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
4825 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
4826 if (carry != ~0u)
4827 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
4828 if (overflow != ~0u)
4829 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
4830 if (m_new_inst_cpsr != m_inst_cpsr)
4831 {
4832 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
4833 return false;
4834 }
4835 }
4836 }
4837 return true;
4838}
4839
Greg Clayton64c84432011-01-21 22:02:52 +00004840bool
4841EmulateInstructionARM::EvaluateInstruction ()
4842{
Johnny Chenc315f862011-02-05 00:46:10 +00004843 // Advance the ITSTATE bits to their values for the next instruction.
4844 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4845 m_it_session.ITAdvance();
4846
Greg Clayton64c84432011-01-21 22:02:52 +00004847 return false;
4848}