blob: 032f01e2c1a93e2787641bcb7cc6f8c6232bbe8b [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
Johnny Chen9f687722011-02-18 00:02:28 +0000183EmulateInstructionARM::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
Johnny Chen9f687722011-02-18 00:02:28 +0000312EmulateInstructionARM::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
Johnny Chen9f687722011-02-18 00:02:28 +0000443EmulateInstructionARM::EmulateADDRdSPImm (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
Johnny Chen9f687722011-02-18 00:02:28 +0000505EmulateInstructionARM::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
Johnny Chen9f687722011-02-18 00:02:28 +0000562EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000563{
Johnny Chen9f687722011-02-18 00:02:28 +0000564 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000565}
566
567// Move from register to register.
568// MOV (register)
569bool
Johnny Chen9f687722011-02-18 00:02:28 +0000570EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000571{
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
Johnny Chen10530c22011-02-17 22:37:12 +0000625 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000626 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
Johnny Chen9f687722011-02-18 00:02:28 +0000635EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000636{
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
Johnny Chen10530c22011-02-17 22:37:12 +0000691 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000692 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
Johnny Chen9f687722011-02-18 00:02:28 +0000702EmulateInstructionARM::EmulateMVNRdImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000703{
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
Johnny Chen10530c22011-02-17 22:37:12 +0000756 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000757 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
Johnny Chen864a8e82011-02-18 00:07:39 +0000868EmulateInstructionARM::EmulateADDSPImm (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
Johnny Chen864a8e82011-02-18 00:07:39 +0000922EmulateInstructionARM::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
Johnny Chen864a8e82011-02-18 00:07:39 +00001199EmulateInstructionARM::EmulateSUBR7IPImm (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
Johnny Chen864a8e82011-02-18 00:07:39 +00001255EmulateInstructionARM::EmulateSUBIPSPImm (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
Johnny Chen864a8e82011-02-18 00:07:39 +00001310EmulateInstructionARM::EmulateSUBSPImm (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;
Johnny Chen104c8b62011-02-17 23:27:44 +00001896 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001897 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 Chen9f687722011-02-18 00:02:28 +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
Johnny Chen10530c22011-02-17 22:37:12 +00002009 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002010 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
Johnny Chen9f687722011-02-18 00:02:28 +00002017EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002018{
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
Johnny Chen10530c22011-02-17 22:37:12 +00002050 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2051
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002052 EmulateInstruction::Context context;
2053 context.type = EmulateInstruction::eContextImmediate;
2054 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002055 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2056 return false;
2057
Johnny Chend4dc4442011-02-11 02:02:56 +00002058 return true;
2059}
2060
Johnny Chene4a4d302011-02-11 21:53:58 +00002061// CMP (register)
2062bool
Johnny Chen9f687722011-02-18 00:02:28 +00002063EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002064{
2065#if 0
2066 // ARM pseudo code...
2067 if ConditionPassed() then
2068 EncodingSpecificOperations();
2069 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2070 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2071 APSR.N = result<31>;
2072 APSR.Z = IsZeroBit(result);
2073 APSR.C = carry;
2074 APSR.V = overflow;
2075#endif
2076
2077 bool success = false;
2078 const uint32_t opcode = OpcodeAsUnsigned (&success);
2079 if (!success)
2080 return false;
2081
2082 uint32_t Rn; // the first operand
2083 uint32_t Rm; // the second operand
2084 switch (encoding) {
2085 case eEncodingT1:
2086 Rn = Bits32(opcode, 2, 0);
2087 Rm = Bits32(opcode, 5, 3);
2088 break;
2089 case eEncodingT2:
2090 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2091 Rm = Bits32(opcode, 6, 3);
2092 if (Rn < 8 && Rm < 8)
2093 return false;
2094 if (Rn == 15 || Rm == 15)
2095 return false;
2096 break;
2097 default:
2098 return false;
2099 }
2100 // Read the register value from register Rn.
2101 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2102 if (!success)
2103 return false;
2104 // Read the register value from register Rm.
2105 // The register value is not being shifted since we don't handle ARM for now.
2106 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2107 if (!success)
2108 return false;
2109
Johnny Chen10530c22011-02-17 22:37:12 +00002110 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2111
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002112 EmulateInstruction::Context context;
2113 context.type = EmulateInstruction::eContextImmediate;
2114 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002115 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2116 return false;
2117
Johnny Chene4a4d302011-02-11 21:53:58 +00002118 return true;
2119}
2120
Johnny Chen82f16aa2011-02-15 20:10:55 +00002121// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2122// shifting in copies of its sign bit, and writes the result to the destination register. It can
2123// optionally update the condition flags based on the result.
2124bool
2125EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2126{
2127#if 0
2128 // ARM pseudo code...
2129 if ConditionPassed() then
2130 EncodingSpecificOperations();
2131 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2132 if d == 15 then // Can only occur for ARM encoding
2133 ALUWritePC(result); // setflags is always FALSE here
2134 else
2135 R[d] = result;
2136 if setflags then
2137 APSR.N = result<31>;
2138 APSR.Z = IsZeroBit(result);
2139 APSR.C = carry;
2140 // APSR.V unchanged
2141#endif
2142
Johnny Chen41a0a152011-02-16 01:27:54 +00002143 return EmulateShiftImm(encoding, SRType_ASR);
2144}
2145
2146// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2147// shifting in copies of its sign bit, and writes the result to the destination register.
2148// The variable number of bits is read from the bottom byte of a register. It can optionally update
2149// the condition flags based on the result.
2150bool
2151EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2152{
2153#if 0
2154 // ARM pseudo code...
2155 if ConditionPassed() then
2156 EncodingSpecificOperations();
2157 shift_n = UInt(R[m]<7:0>);
2158 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2159 R[d] = result;
2160 if setflags then
2161 APSR.N = result<31>;
2162 APSR.Z = IsZeroBit(result);
2163 APSR.C = carry;
2164 // APSR.V unchanged
2165#endif
2166
2167 return EmulateShiftReg(encoding, SRType_ASR);
2168}
2169
2170// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2171// shifting in zeros, and writes the result to the destination register. It can optionally
2172// update the condition flags based on the result.
2173bool
2174EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2175{
2176#if 0
2177 // ARM pseudo code...
2178 if ConditionPassed() then
2179 EncodingSpecificOperations();
2180 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2181 if d == 15 then // Can only occur for ARM encoding
2182 ALUWritePC(result); // setflags is always FALSE here
2183 else
2184 R[d] = result;
2185 if setflags then
2186 APSR.N = result<31>;
2187 APSR.Z = IsZeroBit(result);
2188 APSR.C = carry;
2189 // APSR.V unchanged
2190#endif
2191
2192 return EmulateShiftImm(encoding, SRType_LSL);
2193}
2194
2195// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2196// shifting in zeros, and writes the result to the destination register. The variable number
2197// of bits is read from the bottom byte of a register. It can optionally update the condition
2198// flags based on the result.
2199bool
2200EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2201{
2202#if 0
2203 // ARM pseudo code...
2204 if ConditionPassed() then
2205 EncodingSpecificOperations();
2206 shift_n = UInt(R[m]<7:0>);
2207 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2208 R[d] = result;
2209 if setflags then
2210 APSR.N = result<31>;
2211 APSR.Z = IsZeroBit(result);
2212 APSR.C = carry;
2213 // APSR.V unchanged
2214#endif
2215
2216 return EmulateShiftReg(encoding, SRType_LSL);
2217}
2218
2219// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2220// shifting in zeros, and writes the result to the destination register. It can optionally
2221// update the condition flags based on the result.
2222bool
2223EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2224{
2225#if 0
2226 // ARM pseudo code...
2227 if ConditionPassed() then
2228 EncodingSpecificOperations();
2229 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2230 if d == 15 then // Can only occur for ARM encoding
2231 ALUWritePC(result); // setflags is always FALSE here
2232 else
2233 R[d] = result;
2234 if setflags then
2235 APSR.N = result<31>;
2236 APSR.Z = IsZeroBit(result);
2237 APSR.C = carry;
2238 // APSR.V unchanged
2239#endif
2240
2241 return EmulateShiftImm(encoding, SRType_LSR);
2242}
2243
2244// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2245// shifting in zeros, and writes the result to the destination register. The variable number
2246// of bits is read from the bottom byte of a register. It can optionally update the condition
2247// flags based on the result.
2248bool
2249EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2250{
2251#if 0
2252 // ARM pseudo code...
2253 if ConditionPassed() then
2254 EncodingSpecificOperations();
2255 shift_n = UInt(R[m]<7:0>);
2256 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2257 R[d] = result;
2258 if setflags then
2259 APSR.N = result<31>;
2260 APSR.Z = IsZeroBit(result);
2261 APSR.C = carry;
2262 // APSR.V unchanged
2263#endif
2264
2265 return EmulateShiftReg(encoding, SRType_LSR);
2266}
2267
Johnny Cheneeab4852011-02-16 22:14:44 +00002268// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2269// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2270// It can optionally update the condition flags based on the result.
2271bool
2272EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2273{
2274#if 0
2275 // ARM pseudo code...
2276 if ConditionPassed() then
2277 EncodingSpecificOperations();
2278 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2279 if d == 15 then // Can only occur for ARM encoding
2280 ALUWritePC(result); // setflags is always FALSE here
2281 else
2282 R[d] = result;
2283 if setflags then
2284 APSR.N = result<31>;
2285 APSR.Z = IsZeroBit(result);
2286 APSR.C = carry;
2287 // APSR.V unchanged
2288#endif
2289
2290 return EmulateShiftImm(encoding, SRType_ROR);
2291}
2292
2293// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2294// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2295// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2296// flags based on the result.
2297bool
2298EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2299{
2300#if 0
2301 // ARM pseudo code...
2302 if ConditionPassed() then
2303 EncodingSpecificOperations();
2304 shift_n = UInt(R[m]<7:0>);
2305 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2306 R[d] = result;
2307 if setflags then
2308 APSR.N = result<31>;
2309 APSR.Z = IsZeroBit(result);
2310 APSR.C = carry;
2311 // APSR.V unchanged
2312#endif
2313
2314 return EmulateShiftReg(encoding, SRType_ROR);
2315}
2316
2317// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2318// with the carry flag shifted into bit [31].
2319//
2320// RRX can optionally update the condition flags based on the result.
2321// In that case, bit [0] is shifted into the carry flag.
2322bool
2323EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2324{
2325#if 0
2326 // ARM pseudo code...
2327 if ConditionPassed() then
2328 EncodingSpecificOperations();
2329 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2330 if d == 15 then // Can only occur for ARM encoding
2331 ALUWritePC(result); // setflags is always FALSE here
2332 else
2333 R[d] = result;
2334 if setflags then
2335 APSR.N = result<31>;
2336 APSR.Z = IsZeroBit(result);
2337 APSR.C = carry;
2338 // APSR.V unchanged
2339#endif
2340
2341 return EmulateShiftImm(encoding, SRType_RRX);
2342}
2343
Johnny Chen41a0a152011-02-16 01:27:54 +00002344bool
2345EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2346{
2347 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2348
Johnny Chen82f16aa2011-02-15 20:10:55 +00002349 bool success = false;
2350 const uint32_t opcode = OpcodeAsUnsigned (&success);
2351 if (!success)
2352 return false;
2353
2354 if (ConditionPassed())
2355 {
Johnny Chene7f89532011-02-15 23:22:46 +00002356 uint32_t Rd; // the destination register
2357 uint32_t Rm; // the first operand register
2358 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002359 uint32_t carry; // the carry bit after the shift operation
2360 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002361
2362 // Special case handling!
2363 // A8.6.139 ROR (immediate) -- Encoding T1
2364 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2365 {
2366 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2367 // have the same decoding of bit fields as the other Thumb2 shift operations.
2368 encoding = eEncodingT2;
2369 }
2370
Johnny Chen82f16aa2011-02-15 20:10:55 +00002371 switch (encoding) {
2372 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002373 // Due to the above special case handling!
2374 assert(shift_type != SRType_ROR);
2375
Johnny Chen82f16aa2011-02-15 20:10:55 +00002376 Rd = Bits32(opcode, 2, 0);
2377 Rm = Bits32(opcode, 5, 3);
2378 setflags = !InITBlock();
2379 imm5 = Bits32(opcode, 10, 6);
2380 break;
2381 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002382 // A8.6.141 RRX
2383 assert(shift_type != SRType_RRX);
2384
Johnny Chen82f16aa2011-02-15 20:10:55 +00002385 Rd = Bits32(opcode, 11, 8);
2386 Rm = Bits32(opcode, 3, 0);
2387 setflags = BitIsSet(opcode, 20);
2388 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2389 if (BadReg(Rd) || BadReg(Rm))
2390 return false;
2391 break;
2392 case eEncodingA1:
2393 Rd = Bits32(opcode, 15, 12);
2394 Rm = Bits32(opcode, 3, 0);
2395 setflags = BitIsSet(opcode, 20);
2396 imm5 = Bits32(opcode, 11, 7);
2397 break;
2398 default:
2399 return false;
2400 }
2401
Johnny Cheneeab4852011-02-16 22:14:44 +00002402 // A8.6.139 ROR (immediate)
2403 if (shift_type == SRType_ROR && imm5 == 0)
2404 shift_type = SRType_RRX;
2405
Johnny Chen82f16aa2011-02-15 20:10:55 +00002406 // Get the first operand.
2407 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2408 if (!success)
2409 return false;
2410
Johnny Cheneeab4852011-02-16 22:14:44 +00002411 // Decode the shift amount if not RRX.
2412 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002413
Johnny Chen41a0a152011-02-16 01:27:54 +00002414 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002415
2416 // The context specifies that an immediate is to be moved into Rd.
2417 EmulateInstruction::Context context;
2418 context.type = EmulateInstruction::eContextImmediate;
2419 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002420
Johnny Chen10530c22011-02-17 22:37:12 +00002421 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002422 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002423 }
2424 return true;
2425}
2426
Johnny Chene7f89532011-02-15 23:22:46 +00002427bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002428EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002429{
Johnny Chen41a0a152011-02-16 01:27:54 +00002430 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002431
2432 bool success = false;
2433 const uint32_t opcode = OpcodeAsUnsigned (&success);
2434 if (!success)
2435 return false;
2436
2437 if (ConditionPassed())
2438 {
2439 uint32_t Rd; // the destination register
2440 uint32_t Rn; // the first operand register
2441 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2442 uint32_t carry; // the carry bit after the shift operation
2443 bool setflags;
2444 switch (encoding) {
2445 case eEncodingT1:
2446 Rd = Bits32(opcode, 2, 0);
2447 Rn = Rd;
2448 Rm = Bits32(opcode, 5, 3);
2449 setflags = !InITBlock();
2450 break;
2451 case eEncodingT2:
2452 Rd = Bits32(opcode, 11, 8);
2453 Rn = Bits32(opcode, 19, 16);
2454 Rm = Bits32(opcode, 3, 0);
2455 setflags = BitIsSet(opcode, 20);
2456 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2457 return false;
2458 break;
2459 case eEncodingA1:
2460 Rd = Bits32(opcode, 15, 12);
2461 Rn = Bits32(opcode, 3, 0);
2462 Rm = Bits32(opcode, 11, 8);
2463 setflags = BitIsSet(opcode, 20);
2464 if (Rd == 15 || Rn == 15 || Rm == 15)
2465 return false;
2466 break;
2467 default:
2468 return false;
2469 }
2470
2471 // Get the first operand.
2472 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2473 if (!success)
2474 return false;
2475 // Get the Rm register content.
2476 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2477 if (!success)
2478 return false;
2479
2480 // Get the shift amount.
2481 uint32_t amt = Bits32(val, 7, 0);
2482
Johnny Chen41a0a152011-02-16 01:27:54 +00002483 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002484
2485 // The context specifies that an immediate is to be moved into Rd.
2486 EmulateInstruction::Context context;
2487 context.type = EmulateInstruction::eContextImmediate;
2488 context.SetNoArgs ();
2489
Johnny Chen10530c22011-02-17 22:37:12 +00002490 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002491 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002492 }
2493 return true;
2494}
2495
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002496// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002497// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002498// can be written back to the base register.
2499bool
2500EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2501{
2502#if 0
2503 // ARM pseudo code...
2504 if ConditionPassed()
2505 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2506 address = R[n];
2507
2508 for i = 0 to 14
2509 if registers<i> == '1' then
2510 R[i] = MemA[address, 4]; address = address + 4;
2511 if registers<15> == '1' then
2512 LoadWritePC (MemA[address, 4]);
2513
2514 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2515 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2516
2517#endif
2518
2519 bool success = false;
2520 const uint32_t opcode = OpcodeAsUnsigned (&success);
2521 if (!success)
2522 return false;
2523
2524 if (ConditionPassed())
2525 {
2526 uint32_t n;
2527 uint32_t registers = 0;
2528 bool wback;
2529 const uint32_t addr_byte_size = GetAddressByteSize();
2530 switch (encoding)
2531 {
2532 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002533 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002534 n = Bits32 (opcode, 10, 8);
2535 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002536 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002537 wback = BitIsClear (registers, n);
2538 // if BitCount(registers) < 1 then UNPREDICTABLE;
2539 if (BitCount(registers) < 1)
2540 return false;
2541 break;
2542 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002543 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2544 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002545 n = Bits32 (opcode, 19, 16);
2546 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002547 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002548 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002549
2550 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002551 if ((n == 15)
2552 || (BitCount (registers) < 2)
2553 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2554 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002555
2556 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002557 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002558 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002559
2560 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002561 if (wback
2562 && BitIsSet (registers, n))
2563 return false;
2564 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002565
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002566 case eEncodingA1:
2567 n = Bits32 (opcode, 19, 16);
2568 registers = Bits32 (opcode, 15, 0);
2569 wback = BitIsSet (opcode, 21);
2570 if ((n == 15)
2571 || (BitCount (registers) < 1))
2572 return false;
2573 break;
2574 default:
2575 return false;
2576 }
2577
2578 int32_t offset = 0;
2579 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2580 if (!success)
2581 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002582
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002583 EmulateInstruction::Context context;
2584 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2585 Register dwarf_reg;
2586 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2587 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002588
2589 for (int i = 0; i < 14; ++i)
2590 {
2591 if (BitIsSet (registers, i))
2592 {
Caroline Tice85aab332011-02-08 23:56:10 +00002593 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002594 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002595 if (wback && (n == 13)) // Pop Instruction
2596 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2597
2598 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002599 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002600 if (!success)
2601 return false;
2602
2603 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2604 return false;
2605
2606 offset += addr_byte_size;
2607 }
2608 }
2609
2610 if (BitIsSet (registers, 15))
2611 {
2612 //LoadWritePC (MemA [address, 4]);
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 Ticecc96eb52011-02-17 19:20:40 +00002615 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002616 if (!success)
2617 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002618 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002619 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002620 return false;
2621 }
2622
2623 if (wback && BitIsClear (registers, n))
2624 {
Caroline Ticefa172202011-02-11 22:49:54 +00002625 // R[n] = R[n] + 4 * BitCount (registers)
2626 int32_t offset = addr_byte_size * BitCount (registers);
2627 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002628 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002629
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002630 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2631 return false;
2632 }
2633 if (wback && BitIsSet (registers, n))
2634 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002635 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002636 }
2637 return true;
2638}
Caroline Tice713c2662011-02-11 17:59:55 +00002639
2640// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2641// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2642// can optionally be written back tot he base registers.
2643bool
2644EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2645{
2646#if 0
2647 // ARM pseudo code...
2648 if ConditionPassed() then
2649 EncodingSpecificOperations();
2650 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002651
Caroline Tice713c2662011-02-11 17:59:55 +00002652 for i = 0 to 14
2653 if registers<i> == ’1’ then
2654 R[i] = MemA[address,4]; address = address + 4;
2655
2656 if registers<15> == ’1’ then
2657 LoadWritePC(MemA[address,4]);
2658
2659 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2660 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2661#endif
2662
2663 bool success = false;
2664 const uint32_t opcode = OpcodeAsUnsigned (&success);
2665 if (!success)
2666 return false;
2667
2668 if (ConditionPassed())
2669 {
2670 uint32_t n;
2671 uint32_t registers = 0;
2672 bool wback;
2673 const uint32_t addr_byte_size = GetAddressByteSize();
2674
2675 // EncodingSpecificOperations();
2676 switch (encoding)
2677 {
2678 case eEncodingA1:
2679 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2680 n = Bits32 (opcode, 19, 16);
2681 registers = Bits32 (opcode, 15, 0);
2682 wback = BitIsSet (opcode, 21);
2683
2684 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2685 if ((n == 15) || (BitCount (registers) < 1))
2686 return false;
2687
2688 break;
2689
2690 default:
2691 return false;
2692 }
2693 // address = R[n] - 4*BitCount(registers) + 4;
2694
2695 int32_t offset = 0;
2696 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2697
2698 if (!success)
2699 return false;
2700
2701 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2702
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002703 EmulateInstruction::Context context;
2704 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2705 Register dwarf_reg;
2706 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2707 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002708
2709 // for i = 0 to 14
2710 for (int i = 0; i < 14; ++i)
2711 {
2712 // if registers<i> == ’1’ then
2713 if (BitIsSet (registers, i))
2714 {
2715 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002716 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002717 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002718 if (!success)
2719 return false;
2720 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2721 return false;
2722 offset += addr_byte_size;
2723 }
2724 }
2725
2726 // if registers<15> == ’1’ then
2727 // LoadWritePC(MemA[address,4]);
2728 if (BitIsSet (registers, 15))
2729 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002730 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002731 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002732 if (!success)
2733 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002734 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002735 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002736 return false;
2737 }
2738
2739 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2740 if (wback && BitIsClear (registers, n))
2741 {
Caroline Tice713c2662011-02-11 17:59:55 +00002742 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2743 if (!success)
2744 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002745
2746 offset = (addr_byte_size * BitCount (registers)) * -1;
2747 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002748 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002749 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002750 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2751 return false;
2752 }
2753
2754 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2755 if (wback && BitIsSet (registers, n))
2756 return WriteBits32Unknown (n);
2757 }
2758 return true;
2759}
2760
2761// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2762// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2763// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002764bool
2765EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2766{
2767#if 0
2768 // ARM pseudo code...
2769 if ConditionPassed() then
2770 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2771 address = R[n] - 4*BitCount(registers);
2772
2773 for i = 0 to 14
2774 if registers<i> == ’1’ then
2775 R[i] = MemA[address,4]; address = address + 4;
2776 if registers<15> == ’1’ then
2777 LoadWritePC(MemA[address,4]);
2778
2779 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2780 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2781#endif
2782
2783 bool success = false;
2784 const uint32_t opcode = OpcodeAsUnsigned (&success);
2785 if (!success)
2786 return false;
2787
2788 if (ConditionPassed())
2789 {
2790 uint32_t n;
2791 uint32_t registers = 0;
2792 bool wback;
2793 const uint32_t addr_byte_size = GetAddressByteSize();
2794 switch (encoding)
2795 {
2796 case eEncodingT1:
2797 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2798 n = Bits32 (opcode, 19, 16);
2799 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002800 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002801 wback = BitIsSet (opcode, 21);
2802
2803 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2804 if ((n == 15)
2805 || (BitCount (registers) < 2)
2806 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2807 return false;
2808
2809 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002810 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002811 return false;
2812
2813 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2814 if (wback && BitIsSet (registers, n))
2815 return false;
2816
2817 break;
2818
2819 case eEncodingA1:
2820 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2821 n = Bits32 (opcode, 19, 16);
2822 registers = Bits32 (opcode, 15, 0);
2823 wback = BitIsSet (opcode, 21);
2824
2825 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2826 if ((n == 15) || (BitCount (registers) < 1))
2827 return false;
2828
2829 break;
2830
2831 default:
2832 return false;
2833 }
2834
Caroline Tice713c2662011-02-11 17:59:55 +00002835 // address = R[n] - 4*BitCount(registers);
2836
Caroline Tice0b29e242011-02-08 23:16:02 +00002837 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002838 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2839
2840 if (!success)
2841 return false;
2842
2843 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002844 EmulateInstruction::Context context;
2845 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2846 Register dwarf_reg;
2847 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2848 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002849
2850 for (int i = 0; i < 14; ++i)
2851 {
2852 if (BitIsSet (registers, i))
2853 {
2854 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002855 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002856 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002857 if (!success)
2858 return false;
2859
2860 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2861 return false;
2862
2863 offset += addr_byte_size;
2864 }
2865 }
2866
2867 // if registers<15> == ’1’ then
2868 // LoadWritePC(MemA[address,4]);
2869 if (BitIsSet (registers, 15))
2870 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002871 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002872 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002873 if (!success)
2874 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002875 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002876 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002877 return false;
2878 }
2879
2880 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2881 if (wback && BitIsClear (registers, n))
2882 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002883 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2884 if (!success)
2885 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002886
2887 offset = (addr_byte_size * BitCount (registers)) * -1;
2888 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002889 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002890 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002891 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2892 return false;
2893 }
2894
2895 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2896 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002897 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002898 }
2899 return true;
2900}
Caroline Tice85aab332011-02-08 23:56:10 +00002901
Caroline Tice713c2662011-02-11 17:59:55 +00002902// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2903// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2904// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002905bool
2906EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2907{
2908#if 0
2909 if ConditionPassed() then
2910 EncodingSpecificOperations();
2911 address = R[n] + 4;
2912
2913 for i = 0 to 14
2914 if registers<i> == ’1’ then
2915 R[i] = MemA[address,4]; address = address + 4;
2916 if registers<15> == ’1’ then
2917 LoadWritePC(MemA[address,4]);
2918
2919 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2920 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2921#endif
2922
2923 bool success = false;
2924 const uint32_t opcode = OpcodeAsUnsigned (&success);
2925 if (!success)
2926 return false;
2927
2928 if (ConditionPassed())
2929 {
2930 uint32_t n;
2931 uint32_t registers = 0;
2932 bool wback;
2933 const uint32_t addr_byte_size = GetAddressByteSize();
2934 switch (encoding)
2935 {
2936 case eEncodingA1:
2937 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2938 n = Bits32 (opcode, 19, 16);
2939 registers = Bits32 (opcode, 15, 0);
2940 wback = BitIsSet (opcode, 21);
2941
2942 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2943 if ((n == 15) || (BitCount (registers) < 1))
2944 return false;
2945
2946 break;
2947 default:
2948 return false;
2949 }
2950 // address = R[n] + 4;
2951
2952 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002953 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2954
2955 if (!success)
2956 return false;
2957
2958 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002959
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002960 EmulateInstruction::Context context;
2961 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2962 Register dwarf_reg;
2963 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2964 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00002965
2966 for (int i = 0; i < 14; ++i)
2967 {
2968 if (BitIsSet (registers, i))
2969 {
2970 // R[i] = MemA[address,4]; address = address + 4;
2971
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002972 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002973 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002974 if (!success)
2975 return false;
2976
2977 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2978 return false;
2979
2980 offset += addr_byte_size;
2981 }
2982 }
2983
2984 // if registers<15> == ’1’ then
2985 // LoadWritePC(MemA[address,4]);
2986 if (BitIsSet (registers, 15))
2987 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002988 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002989 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00002990 if (!success)
2991 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002992 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002993 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002994 return false;
2995 }
2996
2997 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2998 if (wback && BitIsClear (registers, n))
2999 {
Caroline Tice85aab332011-02-08 23:56:10 +00003000 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3001 if (!success)
3002 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003003
3004 offset = addr_byte_size * BitCount (registers);
3005 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003006 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003007 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003008 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3009 return false;
3010 }
3011
3012 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3013 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003014 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003015 }
3016 return true;
3017}
Caroline Tice0b29e242011-02-08 23:16:02 +00003018
Johnny Chenef21b592011-02-10 01:52:38 +00003019// Load Register (immediate) calculates an address from a base register value and
3020// an immediate offset, loads a word from memory, and writes to a register.
3021// LDR (immediate, Thumb)
3022bool
3023EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3024{
3025#if 0
3026 // ARM pseudo code...
3027 if (ConditionPassed())
3028 {
3029 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3030 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3031 address = if index then offset_addr else R[n];
3032 data = MemU[address,4];
3033 if wback then R[n] = offset_addr;
3034 if t == 15 then
3035 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3036 elsif UnalignedSupport() || address<1:0> = '00' then
3037 R[t] = data;
3038 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3039 }
3040#endif
3041
3042 bool success = false;
3043 const uint32_t opcode = OpcodeAsUnsigned (&success);
3044 if (!success)
3045 return false;
3046
3047 if (ConditionPassed())
3048 {
3049 uint32_t Rt; // the destination register
3050 uint32_t Rn; // the base register
3051 uint32_t imm32; // the immediate offset used to form the address
3052 addr_t offset_addr; // the offset address
3053 addr_t address; // the calculated address
3054 uint32_t data; // the literal data value from memory load
3055 bool add, index, wback;
3056 switch (encoding) {
3057 case eEncodingT1:
3058 Rt = Bits32(opcode, 5, 3);
3059 Rn = Bits32(opcode, 2, 0);
3060 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3061 // index = TRUE; add = TRUE; wback = FALSE
3062 add = true;
3063 index = true;
3064 wback = false;
3065 break;
3066 default:
3067 return false;
3068 }
3069 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3070 if (!success)
3071 return false;
3072 if (add)
3073 offset_addr = base + imm32;
3074 else
3075 offset_addr = base - imm32;
3076
3077 address = (index ? offset_addr : base);
3078
3079 if (wback)
3080 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003081 EmulateInstruction::Context ctx;
3082 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3083 Register dwarf_reg;
3084 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3085 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3086
Johnny Chenef21b592011-02-10 01:52:38 +00003087 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3088 return false;
3089 }
3090
3091 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003092 EmulateInstruction::Context context;
3093 context.type = EmulateInstruction::eContextImmediate;
3094 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003095
3096 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003097 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003098 if (!success)
3099 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003100
3101 if (Rt == 15)
3102 {
3103 if (Bits32(address, 1, 0) == 0)
3104 {
Johnny Chen668b4512011-02-15 21:08:58 +00003105 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003106 return false;
3107 }
3108 else
3109 return false;
3110 }
3111 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3112 {
3113 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3114 return false;
3115 }
3116 else
3117 return false;
3118 }
3119 return true;
3120}
3121
Caroline Ticeaf556562011-02-15 18:42:15 +00003122// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3123// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3124// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003125bool
3126EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3127{
3128#if 0
3129 if ConditionPassed() then
3130 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3131 address = R[n];
3132
3133 for i = 0 to 14
3134 if registers<i> == ’1’ then
3135 if i == n && wback && i != LowestSetBit(registers) then
3136 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3137 else
3138 MemA[address,4] = R[i];
3139 address = address + 4;
3140
3141 if registers<15> == ’1’ then // Only possible for encoding A1
3142 MemA[address,4] = PCStoreValue();
3143 if wback then R[n] = R[n] + 4*BitCount(registers);
3144#endif
3145
3146 bool success = false;
3147 const uint32_t opcode = OpcodeAsUnsigned (&success);
3148 if (!success)
3149 return false;
3150
3151 if (ConditionPassed ())
3152 {
3153 uint32_t n;
3154 uint32_t registers = 0;
3155 bool wback;
3156 const uint32_t addr_byte_size = GetAddressByteSize();
3157
3158 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3159 switch (encoding)
3160 {
3161 case eEncodingT1:
3162 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3163 n = Bits32 (opcode, 10, 8);
3164 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003165 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003166 wback = true;
3167
3168 // if BitCount(registers) < 1 then UNPREDICTABLE;
3169 if (BitCount (registers) < 1)
3170 return false;
3171
3172 break;
3173
3174 case eEncodingT2:
3175 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3176 n = Bits32 (opcode, 19, 16);
3177 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003178 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003179 wback = BitIsSet (opcode, 21);
3180
3181 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3182 if ((n == 15) || (BitCount (registers) < 2))
3183 return false;
3184
3185 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3186 if (wback && BitIsSet (registers, n))
3187 return false;
3188
3189 break;
3190
3191 case eEncodingA1:
3192 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3193 n = Bits32 (opcode, 19, 16);
3194 registers = Bits32 (opcode, 15, 0);
3195 wback = BitIsSet (opcode, 21);
3196
3197 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3198 if ((n == 15) || (BitCount (registers) < 1))
3199 return false;
3200
3201 break;
3202
3203 default:
3204 return false;
3205 }
3206
3207 // address = R[n];
3208 int32_t offset = 0;
3209 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3210 if (!success)
3211 return false;
3212
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003213 EmulateInstruction::Context context;
3214 context.type = EmulateInstruction::eContextRegisterStore;
3215 Register base_reg;
3216 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003217
3218 // for i = 0 to 14
3219 for (int i = 0; i < 14; ++i)
3220 {
3221 int lowest_set_bit = 14;
3222 // if registers<i> == ’1’ then
3223 if (BitIsSet (registers, i))
3224 {
3225 if (i < lowest_set_bit)
3226 lowest_set_bit = i;
3227 // if i == n && wback && i != LowestSetBit(registers) then
3228 if ((i == n) && wback && (i != lowest_set_bit))
3229 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3230 WriteBits32UnknownToMemory (address + offset);
3231 else
3232 {
3233 // MemA[address,4] = R[i];
3234 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3235 if (!success)
3236 return false;
3237
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003238 Register data_reg;
3239 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3240 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003241 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003242 return false;
3243 }
3244
3245 // address = address + 4;
3246 offset += addr_byte_size;
3247 }
3248 }
3249
3250 // if registers<15> == ’1’ then // Only possible for encoding A1
3251 // MemA[address,4] = PCStoreValue();
3252 if (BitIsSet (registers, 15))
3253 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003254 Register pc_reg;
3255 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3256 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003257 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3258 if (!success)
3259 return false;
3260
Caroline Ticecc96eb52011-02-17 19:20:40 +00003261 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003262 return false;
3263 }
3264
3265 // if wback then R[n] = R[n] + 4*BitCount(registers);
3266 if (wback)
3267 {
3268 offset = addr_byte_size * BitCount (registers);
3269 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003270 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003271 addr_t data = address + offset;
3272 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3273 return false;
3274 }
3275 }
3276 return true;
3277}
3278
Caroline Ticeaf556562011-02-15 18:42:15 +00003279// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3280// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3281// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003282bool
3283EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3284{
3285#if 0
3286 if ConditionPassed() then
3287 EncodingSpecificOperations();
3288 address = R[n] - 4*BitCount(registers) + 4;
3289
3290 for i = 0 to 14
3291 if registers<i> == ’1’ then
3292 if i == n && wback && i != LowestSetBit(registers) then
3293 MemA[address,4] = bits(32) UNKNOWN;
3294 else
3295 MemA[address,4] = R[i];
3296 address = address + 4;
3297
3298 if registers<15> == ’1’ then
3299 MemA[address,4] = PCStoreValue();
3300
3301 if wback then R[n] = R[n] - 4*BitCount(registers);
3302#endif
3303
3304 bool success = false;
3305 const uint32_t opcode = OpcodeAsUnsigned (&success);
3306 if (!success)
3307 return false;
3308
3309 if (ConditionPassed ())
3310 {
3311 uint32_t n;
3312 uint32_t registers = 0;
3313 bool wback;
3314 const uint32_t addr_byte_size = GetAddressByteSize();
3315
3316 // EncodingSpecificOperations();
3317 switch (encoding)
3318 {
3319 case eEncodingA1:
3320 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3321 n = Bits32 (opcode, 19, 16);
3322 registers = Bits32 (opcode, 15, 0);
3323 wback = BitIsSet (opcode, 21);
3324
3325 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3326 if ((n == 15) || (BitCount (registers) < 1))
3327 return false;
3328 break;
3329 default:
3330 return false;
3331 }
3332
3333 // address = R[n] - 4*BitCount(registers) + 4;
3334 int32_t offset = 0;
3335 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3336 if (!success)
3337 return false;
3338
3339 address = address - (addr_byte_size * BitCount (registers)) + 4;
3340
3341 EmulateInstruction::Context context;
3342 context.type = EmulateInstruction::eContextRegisterStore;
3343 Register base_reg;
3344 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3345
3346 // for i = 0 to 14
3347 for (int i = 0; i < 14; ++i)
3348 {
3349 int lowest_bit_set = 14;
3350 // if registers<i> == ’1’ then
3351 if (BitIsSet (registers, i))
3352 {
3353 if (i < lowest_bit_set)
3354 lowest_bit_set = i;
3355 //if i == n && wback && i != LowestSetBit(registers) then
3356 if ((i == n) && wback && (i != lowest_bit_set))
3357 // MemA[address,4] = bits(32) UNKNOWN;
3358 WriteBits32UnknownToMemory (address + offset);
3359 else
3360 {
3361 // MemA[address,4] = R[i];
3362 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3363 if (!success)
3364 return false;
3365
3366 Register data_reg;
3367 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3368 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003369 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003370 return false;
3371 }
3372
3373 // address = address + 4;
3374 offset += addr_byte_size;
3375 }
3376 }
3377
3378 // if registers<15> == ’1’ then
3379 // MemA[address,4] = PCStoreValue();
3380 if (BitIsSet (registers, 15))
3381 {
3382 Register pc_reg;
3383 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3384 context.SetRegisterPlusOffset (pc_reg, 8);
3385 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3386 if (!success)
3387 return false;
3388
Caroline Ticecc96eb52011-02-17 19:20:40 +00003389 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003390 return false;
3391 }
3392
3393 // if wback then R[n] = R[n] - 4*BitCount(registers);
3394 if (wback)
3395 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003396 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003397 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3398 context.SetImmediateSigned (offset);
3399 addr_t data = address + offset;
3400 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3401 return false;
3402 }
3403 }
3404 return true;
3405}
3406
Caroline Ticeaf556562011-02-15 18:42:15 +00003407// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3408// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3409// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003410bool
3411EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3412{
3413#if 0
3414 if ConditionPassed() then
3415 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3416 address = R[n] - 4*BitCount(registers);
3417
3418 for i = 0 to 14
3419 if registers<i> == ’1’ then
3420 if i == n && wback && i != LowestSetBit(registers) then
3421 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3422 else
3423 MemA[address,4] = R[i];
3424 address = address + 4;
3425
3426 if registers<15> == ’1’ then // Only possible for encoding A1
3427 MemA[address,4] = PCStoreValue();
3428
3429 if wback then R[n] = R[n] - 4*BitCount(registers);
3430#endif
3431
3432
3433 bool success = false;
3434 const uint32_t opcode = OpcodeAsUnsigned (&success);
3435 if (!success)
3436 return false;
3437
3438 if (ConditionPassed ())
3439 {
3440 uint32_t n;
3441 uint32_t registers = 0;
3442 bool wback;
3443 const uint32_t addr_byte_size = GetAddressByteSize();
3444
3445 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3446 switch (encoding)
3447 {
3448 case eEncodingT1:
3449 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3450 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3451 {
3452 // See PUSH
3453 }
3454 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3455 n = Bits32 (opcode, 19, 16);
3456 registers = Bits32 (opcode, 15, 0);
3457 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3458 wback = BitIsSet (opcode, 21);
3459 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3460 if ((n == 15) || BitCount (registers) < 2)
3461 return false;
3462 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3463 if (wback && BitIsSet (registers, n))
3464 return false;
3465 break;
3466
3467 case eEncodingA1:
3468 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3469 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3470 {
3471 // See Push
3472 }
3473 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3474 n = Bits32 (opcode, 19, 16);
3475 registers = Bits32 (opcode, 15, 0);
3476 wback = BitIsSet (opcode, 21);
3477 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3478 if ((n == 15) || BitCount (registers) < 1)
3479 return false;
3480 break;
3481
3482 default:
3483 return false;
3484 }
3485
3486 // address = R[n] - 4*BitCount(registers);
3487
3488 int32_t offset = 0;
3489 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3490 if (!success)
3491 return false;
3492
3493 address = address - (addr_byte_size * BitCount (registers));
3494
3495 EmulateInstruction::Context context;
3496 context.type = EmulateInstruction::eContextRegisterStore;
3497 Register base_reg;
3498 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3499
3500 // for i = 0 to 14
3501 for (int i = 0; i < 14; ++i)
3502 {
3503 uint32_t lowest_set_bit = 14;
3504 // if registers<i> == ’1’ then
3505 if (BitIsSet (registers, i))
3506 {
3507 if (i < lowest_set_bit)
3508 lowest_set_bit = i;
3509 // if i == n && wback && i != LowestSetBit(registers) then
3510 if ((i == n) && wback && (i != lowest_set_bit))
3511 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3512 WriteBits32UnknownToMemory (address + offset);
3513 else
3514 {
3515 // MemA[address,4] = R[i];
3516 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3517 if (!success)
3518 return false;
3519
3520 Register data_reg;
3521 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3522 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003523 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003524 return false;
3525 }
3526
3527 // address = address + 4;
3528 offset += addr_byte_size;
3529 }
3530 }
3531
3532 // if registers<15> == ’1’ then // Only possible for encoding A1
3533 // MemA[address,4] = PCStoreValue();
3534 if (BitIsSet (registers, 15))
3535 {
3536 Register pc_reg;
3537 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3538 context.SetRegisterPlusOffset (pc_reg, 8);
3539 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3540 if (!success)
3541 return false;
3542
Caroline Ticecc96eb52011-02-17 19:20:40 +00003543 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003544 return false;
3545 }
3546
3547 // if wback then R[n] = R[n] - 4*BitCount(registers);
3548 if (wback)
3549 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003550 offset = (addr_byte_size * BitCount (registers)) * -1;
3551 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3552 context.SetImmediateSigned (offset);
3553 addr_t data = address + offset;
3554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3555 return false;
3556 }
3557 }
3558 return true;
3559}
3560
3561// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3562// from a base register. The consecutive memory locations start just above this address, and the address of the last
3563// of those locations can optionally be written back to the base register.
3564bool
3565EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3566{
3567#if 0
3568 if ConditionPassed() then
3569 EncodingSpecificOperations();
3570 address = R[n] + 4;
3571
3572 for i = 0 to 14
3573 if registers<i> == ’1’ then
3574 if i == n && wback && i != LowestSetBit(registers) then
3575 MemA[address,4] = bits(32) UNKNOWN;
3576 else
3577 MemA[address,4] = R[i];
3578 address = address + 4;
3579
3580 if registers<15> == ’1’ then
3581 MemA[address,4] = PCStoreValue();
3582
3583 if wback then R[n] = R[n] + 4*BitCount(registers);
3584#endif
3585
3586 bool success = false;
3587 const uint32_t opcode = OpcodeAsUnsigned (&success);
3588 if (!success)
3589 return false;
3590
3591 if (ConditionPassed())
3592 {
3593 uint32_t n;
3594 uint32_t registers = 0;
3595 bool wback;
3596 const uint32_t addr_byte_size = GetAddressByteSize();
3597
3598 // EncodingSpecificOperations();
3599 switch (encoding)
3600 {
3601 case eEncodingA1:
3602 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3603 n = Bits32 (opcode, 19, 16);
3604 registers = Bits32 (opcode, 15, 0);
3605 wback = BitIsSet (opcode, 21);
3606
3607 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3608 if ((n == 15) && (BitCount (registers) < 1))
3609 return false;
3610 break;
3611 default:
3612 return false;
3613 }
3614 // address = R[n] + 4;
3615
3616 int32_t offset = 0;
3617 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3618 if (!success)
3619 return false;
3620
3621 address = address + addr_byte_size;
3622
3623 EmulateInstruction::Context context;
3624 context.type = EmulateInstruction::eContextRegisterStore;
3625 Register base_reg;
3626 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3627
3628 uint32_t lowest_set_bit = 14;
3629 // for i = 0 to 14
3630 for (int i = 0; i < 14; ++i)
3631 {
3632 // if registers<i> == ’1’ then
3633 if (BitIsSet (registers, i))
3634 {
3635 if (i < lowest_set_bit)
3636 lowest_set_bit = i;
3637 // if i == n && wback && i != LowestSetBit(registers) then
3638 if ((i == n) && wback && (i != lowest_set_bit))
3639 // MemA[address,4] = bits(32) UNKNOWN;
3640 WriteBits32UnknownToMemory (address + offset);
3641 // else
3642 else
3643 {
3644 // MemA[address,4] = R[i];
3645 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3646 if (!success)
3647 return false;
3648
3649 Register data_reg;
3650 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3651 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003652 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003653 return false;
3654 }
3655
3656 // address = address + 4;
3657 offset += addr_byte_size;
3658 }
3659 }
3660
3661 // if registers<15> == ’1’ then
3662 // MemA[address,4] = PCStoreValue();
3663 if (BitIsSet (registers, 15))
3664 {
3665 Register pc_reg;
3666 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3667 context.SetRegisterPlusOffset (pc_reg, 8);
3668 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3669 if (!success)
3670 return false;
3671
Caroline Ticecc96eb52011-02-17 19:20:40 +00003672 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003673 return false;
3674 }
3675
3676 // if wback then R[n] = R[n] + 4*BitCount(registers);
3677 if (wback)
3678 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003679 offset = addr_byte_size * BitCount (registers);
3680 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3681 context.SetImmediateSigned (offset);
3682 addr_t data = address + offset;
3683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3684 return false;
3685 }
3686 }
3687 return true;
3688}
Caroline Tice7fac8572011-02-15 22:53:54 +00003689
3690// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3691// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3692bool
3693EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3694{
3695#if 0
3696 if ConditionPassed() then
3697 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3698 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3699 address = if index then offset_addr else R[n];
3700 if UnalignedSupport() || address<1:0> == ’00’ then
3701 MemU[address,4] = R[t];
3702 else // Can only occur before ARMv7
3703 MemU[address,4] = bits(32) UNKNOWN;
3704 if wback then R[n] = offset_addr;
3705#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003706
Caroline Tice7fac8572011-02-15 22:53:54 +00003707 bool success = false;
3708 const uint32_t opcode = OpcodeAsUnsigned (&success);
3709 if (!success)
3710 return false;
3711
3712 if (ConditionPassed())
3713 {
3714 const uint32_t addr_byte_size = GetAddressByteSize();
3715
3716 uint32_t t;
3717 uint32_t n;
3718 uint32_t imm32;
3719 bool index;
3720 bool add;
3721 bool wback;
3722 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3723 switch (encoding)
3724 {
3725 case eEncodingT1:
3726 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3727 t = Bits32 (opcode, 2, 0);
3728 n = Bits32 (opcode, 5, 3);
3729 imm32 = Bits32 (opcode, 10, 6) << 2;
3730
3731 // index = TRUE; add = TRUE; wback = FALSE;
3732 index = true;
3733 add = false;
3734 wback = false;
3735 break;
3736
3737 case eEncodingT2:
3738 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3739 t = Bits32 (opcode, 10, 8);
3740 n = 13;
3741 imm32 = Bits32 (opcode, 7, 0) << 2;
3742
3743 // index = TRUE; add = TRUE; wback = FALSE;
3744 index = true;
3745 add = true;
3746 wback = false;
3747 break;
3748
3749 case eEncodingT3:
3750 // if Rn == ’1111’ then UNDEFINED;
3751 if (Bits32 (opcode, 19, 16) == 15)
3752 return false;
3753
3754 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3755 t = Bits32 (opcode, 15, 12);
3756 n = Bits32 (opcode, 19, 16);
3757 imm32 = Bits32 (opcode, 11, 0);
3758
3759 // index = TRUE; add = TRUE; wback = FALSE;
3760 index = true;
3761 add = true;
3762 wback = false;
3763
3764 // if t == 15 then UNPREDICTABLE;
3765 if (t == 15)
3766 return false;
3767 break;
3768
3769 case eEncodingT4:
3770 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3771 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3772 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3773 if ((Bits32 (opcode, 19, 16) == 15)
3774 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3775 return false;
3776
3777 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3778 t = Bits32 (opcode, 15, 12);
3779 n = Bits32 (opcode, 19, 16);
3780 imm32 = Bits32 (opcode, 7, 0);
3781
3782 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3783 index = BitIsSet (opcode, 10);
3784 add = BitIsSet (opcode, 9);
3785 wback = BitIsSet (opcode, 8);
3786
3787 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3788 if ((t == 15) || (wback && (n == t)))
3789 return false;
3790 break;
3791
3792 default:
3793 return false;
3794 }
3795
3796 addr_t offset_addr;
3797 addr_t address;
3798
3799 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3800 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3801 if (!success)
3802 return false;
3803
3804 if (add)
3805 offset_addr = base_address + imm32;
3806 else
3807 offset_addr = base_address - imm32;
3808
3809 // address = if index then offset_addr else R[n];
3810 if (index)
3811 address = offset_addr;
3812 else
3813 address = base_address;
3814
3815 EmulateInstruction::Context context;
3816 context.type = eContextRegisterStore;
3817 Register base_reg;
3818 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3819
3820 // if UnalignedSupport() || address<1:0> == ’00’ then
3821 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3822 {
3823 // MemU[address,4] = R[t];
3824 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3825 if (!success)
3826 return false;
3827
3828 Register data_reg;
3829 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3830 int32_t offset = address - base_address;
3831 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003832 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003833 return false;
3834 }
3835 else
3836 {
3837 // MemU[address,4] = bits(32) UNKNOWN;
3838 WriteBits32UnknownToMemory (address);
3839 }
3840
3841 // if wback then R[n] = offset_addr;
3842 if (wback)
3843 {
3844 context.type = eContextRegisterLoad;
3845 context.SetAddress (offset_addr);
3846 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3847 return false;
3848 }
3849 }
3850 return true;
3851}
Caroline Ticeaf556562011-02-15 18:42:15 +00003852
Caroline Tice3fd63e92011-02-16 00:33:43 +00003853// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3854// word from a register to memory. The offset register value can optionally be shifted.
3855bool
3856EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3857{
3858#if 0
3859 if ConditionPassed() then
3860 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3861 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3862 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3863 address = if index then offset_addr else R[n];
3864 if t == 15 then // Only possible for encoding A1
3865 data = PCStoreValue();
3866 else
3867 data = R[t];
3868 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3869 MemU[address,4] = data;
3870 else // Can only occur before ARMv7
3871 MemU[address,4] = bits(32) UNKNOWN;
3872 if wback then R[n] = offset_addr;
3873#endif
3874
3875 bool success = false;
3876 const uint32_t opcode = OpcodeAsUnsigned (&success);
3877 if (!success)
3878 return false;
3879
3880 if (ConditionPassed())
3881 {
3882 const uint32_t addr_byte_size = GetAddressByteSize();
3883
3884 uint32_t t;
3885 uint32_t n;
3886 uint32_t m;
3887 ARM_ShifterType shift_t;
3888 uint32_t shift_n;
3889 bool index;
3890 bool add;
3891 bool wback;
3892
3893 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3894 switch (encoding)
3895 {
3896 case eEncodingT1:
3897 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3898 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3899 t = Bits32 (opcode, 2, 0);
3900 n = Bits32 (opcode, 5, 3);
3901 m = Bits32 (opcode, 8, 6);
3902
3903 // index = TRUE; add = TRUE; wback = FALSE;
3904 index = true;
3905 add = true;
3906 wback = false;
3907
3908 // (shift_t, shift_n) = (SRType_LSL, 0);
3909 shift_t = SRType_LSL;
3910 shift_n = 0;
3911 break;
3912
3913 case eEncodingT2:
3914 // if Rn == ’1111’ then UNDEFINED;
3915 if (Bits32 (opcode, 19, 16) == 15)
3916 return false;
3917
3918 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3919 t = Bits32 (opcode, 15, 12);
3920 n = Bits32 (opcode, 19, 16);
3921 m = Bits32 (opcode, 3, 0);
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, UInt(imm2));
3929 shift_t = SRType_LSL;
3930 shift_n = Bits32 (opcode, 5, 4);
3931
3932 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3933 if ((t == 15) || (BadReg (m)))
3934 return false;
3935 break;
3936
3937 case eEncodingA1:
3938 {
3939 // if P == ’0’ && W == ’1’ then SEE STRT;
3940 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3941 t = Bits32 (opcode, 15, 12);
3942 n = Bits32 (opcode, 19, 16);
3943 m = Bits32 (opcode, 3, 0);
3944
3945 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3946 index = BitIsSet (opcode, 24);
3947 add = BitIsSet (opcode, 23);
3948 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
3949
3950 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
3951 uint32_t typ = Bits32 (opcode, 6, 5);
3952 uint32_t imm5 = Bits32 (opcode, 11, 7);
3953 shift_n = DecodeImmShift(typ, imm5, shift_t);
3954
3955 // if m == 15 then UNPREDICTABLE;
3956 if (m == 15)
3957 return false;
3958
3959 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
3960 if (wback && ((n == 15) || (n == t)))
3961 return false;
3962
3963 break;
3964 }
3965 default:
3966 return false;
3967 }
3968
3969 addr_t offset_addr;
3970 addr_t address;
3971 int32_t offset = 0;
3972
3973 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3974 if (!success)
3975 return false;
3976
3977 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
3978 if (!success)
3979 return false;
3980
3981 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
3982 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
3983
3984 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3985 if (add)
3986 offset_addr = base_address + offset;
3987 else
3988 offset_addr = base_address - offset;
3989
3990 // address = if index then offset_addr else R[n];
3991 if (index)
3992 address = offset_addr;
3993 else
3994 address = base_address;
3995
3996 uint32_t data;
3997 // if t == 15 then // Only possible for encoding A1
3998 if (t == 15)
3999 // data = PCStoreValue();
4000 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4001 else
4002 // data = R[t];
4003 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4004
4005 if (!success)
4006 return false;
4007
4008 EmulateInstruction::Context context;
4009 context.type = eContextRegisterStore;
4010
4011 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4012 if (UnalignedSupport ()
4013 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4014 || CurrentInstrSet() == eModeARM)
4015 {
4016 // MemU[address,4] = data;
4017
4018 Register base_reg;
4019 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4020
4021 Register data_reg;
4022 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4023
4024 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004025 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004026 return false;
4027
4028 }
4029 else
4030 // MemU[address,4] = bits(32) UNKNOWN;
4031 WriteBits32UnknownToMemory (address);
4032
4033 // if wback then R[n] = offset_addr;
4034 if (wback)
4035 {
4036 context.type = eContextRegisterLoad;
4037 context.SetAddress (offset_addr);
4038 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4039 return false;
4040 }
4041
4042 }
4043 return true;
4044}
Caroline Tice73a29de2011-02-16 20:22:22 +00004045
4046bool
4047EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4048{
4049#if 0
4050 if ConditionPassed() then
4051 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4052 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4053 address = if index then offset_addr else R[n];
4054 MemU[address,1] = R[t]<7:0>;
4055 if wback then R[n] = offset_addr;
4056#endif
4057
4058
4059 bool success = false;
4060 const uint32_t opcode = OpcodeAsUnsigned (&success);
4061 if (!success)
4062 return false;
4063
4064 if (ConditionPassed ())
4065 {
4066 uint32_t t;
4067 uint32_t n;
4068 uint32_t imm32;
4069 bool index;
4070 bool add;
4071 bool wback;
4072 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4073 switch (encoding)
4074 {
4075 case eEncodingT1:
4076 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4077 t = Bits32 (opcode, 2, 0);
4078 n = Bits32 (opcode, 5, 3);
4079 imm32 = Bits32 (opcode, 10, 6);
4080
4081 // index = TRUE; add = TRUE; wback = FALSE;
4082 index = true;
4083 add = true;
4084 wback = false;
4085 break;
4086
4087 case eEncodingT2:
4088 // if Rn == ’1111’ then UNDEFINED;
4089 if (Bits32 (opcode, 19, 16) == 15)
4090 return false;
4091
4092 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4093 t = Bits32 (opcode, 15, 12);
4094 n = Bits32 (opcode, 19, 16);
4095 imm32 = Bits32 (opcode, 11, 0);
4096
4097 // index = TRUE; add = TRUE; wback = FALSE;
4098 index = true;
4099 add = true;
4100 wback = false;
4101
4102 // if BadReg(t) then UNPREDICTABLE;
4103 if (BadReg (t))
4104 return false;
4105 break;
4106
4107 case eEncodingT3:
4108 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4109 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4110 if (Bits32 (opcode, 19, 16) == 15)
4111 return false;
4112
4113 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4114 t = Bits32 (opcode, 15, 12);
4115 n = Bits32 (opcode, 19, 16);
4116 imm32 = Bits32 (opcode, 7, 0);
4117
4118 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4119 index = BitIsSet (opcode, 10);
4120 add = BitIsSet (opcode, 9);
4121 wback = BitIsSet (opcode, 8);
4122
4123 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4124 if ((BadReg (t)) || (wback && (n == t)))
4125 return false;
4126 break;
4127
4128 default:
4129 return false;
4130 }
4131
4132 addr_t offset_addr;
4133 addr_t address;
4134 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4135 if (!success)
4136 return false;
4137
4138 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4139 if (add)
4140 offset_addr = base_address + imm32;
4141 else
4142 offset_addr = base_address - imm32;
4143
4144 // address = if index then offset_addr else R[n];
4145 if (index)
4146 address = offset_addr;
4147 else
4148 address = base_address;
4149
Caroline Ticecc96eb52011-02-17 19:20:40 +00004150 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004151 Register base_reg;
4152 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4153
4154 Register data_reg;
4155 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4156
4157 EmulateInstruction::Context context;
4158 context.type = eContextRegisterStore;
4159 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4160
4161 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4162 if (!success)
4163 return false;
4164
4165 data = Bits32 (data, 7, 0);
4166
Caroline Ticecc96eb52011-02-17 19:20:40 +00004167 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004168 return false;
4169
4170 // if wback then R[n] = offset_addr;
4171 if (wback)
4172 {
4173 context.type = eContextRegisterLoad;
4174 context.SetAddress (offset_addr);
4175 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4176 return false;
4177 }
4178
4179 }
4180
4181 return true;
4182}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004183
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004184EmulateInstructionARM::ARMOpcode*
4185EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004186{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004187 static ARMOpcode
4188 g_arm_opcodes[] =
4189 {
4190 //----------------------------------------------------------------------
4191 // Prologue instructions
4192 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004193
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004194 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00004195 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
4196 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004197
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004198 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00004199 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004200 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004201 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00004202 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
4203 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004204 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004205
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004206 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00004207 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004208
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004209 // push one register
4210 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004211 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004212
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004213 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004214 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4215 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004216
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004217 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004218 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004219 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004220
Johnny Chen9f687722011-02-18 00:02:28 +00004221 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
4222 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004223 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004224 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4225
4226 //----------------------------------------------------------------------
4227 // Supervisor Call (previously Software Interrupt)
4228 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004229 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4230
4231 //----------------------------------------------------------------------
4232 // Branch instructions
4233 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004234 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004235 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4236 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4237 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4238 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004239 // for example, "bx lr"
4240 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004241
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004242 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004243 // Data-processing instructions
4244 //----------------------------------------------------------------------
4245 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00004246 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004247 // asr (immediate)
4248 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004249 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004250 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004251 // lsl (immediate)
4252 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4253 // lsl (register)
4254 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4255 // lsr (immediate)
4256 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4257 // lsr (register)
4258 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004259 // rrx is a special case encoding of ror (immediate)
4260 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4261 // ror (immediate)
4262 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4263 // ror (register)
4264 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004265
4266 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004267 // Load instructions
4268 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004269 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004270 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004271 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004272 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
4273
4274 //----------------------------------------------------------------------
4275 // Store instructions
4276 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004277 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004278 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004279 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004280 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4281 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004282
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004283
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004284 };
4285 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4286
4287 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4288 {
4289 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4290 return &g_arm_opcodes[i];
4291 }
4292 return NULL;
4293}
Greg Clayton64c84432011-01-21 22:02:52 +00004294
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004295
4296EmulateInstructionARM::ARMOpcode*
4297EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004298{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004299
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004300 static ARMOpcode
4301 g_thumb_opcodes[] =
4302 {
4303 //----------------------------------------------------------------------
4304 // Prologue instructions
4305 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004306
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004307 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00004308 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
4309 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
4310 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004311
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004312 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00004313 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004314 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00004315 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004316 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00004317 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004318
Johnny Chen864a8e82011-02-18 00:07:39 +00004319 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00004320 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004321
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004322 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00004323 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
4324 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
4325 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
4326 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004327
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004328 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004329 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4330 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004331
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004332 //----------------------------------------------------------------------
4333 // Epilogue instructions
4334 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004335
Johnny Chen864a8e82011-02-18 00:07:39 +00004336 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00004337 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
4338 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
4339 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004340 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4341 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004342
4343 //----------------------------------------------------------------------
4344 // Supervisor Call (previously Software Interrupt)
4345 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004346 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4347
4348 //----------------------------------------------------------------------
4349 // If Then makes up to four following instructions conditional.
4350 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004351 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4352
4353 //----------------------------------------------------------------------
4354 // Branch instructions
4355 //----------------------------------------------------------------------
4356 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4357 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4358 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004359 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004360 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004361 // J1 == J2 == 1
4362 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4363 // J1 == J2 == 1
4364 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4365 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004366 // for example, "bx lr"
4367 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004368 // compare and branch
4369 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00004370 // table branch byte
4371 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
4372 // table branch halfword
4373 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004374
4375 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004376 // Data-processing instructions
4377 //----------------------------------------------------------------------
Johnny Chen9f687722011-02-18 00:02:28 +00004378 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004379 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chend761dcf2011-02-17 22:03:29 +00004380 // Can update PC!
Johnny Chen9f687722011-02-18 00:02:28 +00004381 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004382 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00004383 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004384 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00004385 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004386 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00004387 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
4388 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004389 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00004390 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004391 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00004392 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004393 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00004394 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004395 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00004396 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004397 // asr (immediate)
4398 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004399 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004400 // asr (register)
4401 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4402 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004403 // lsl (immediate)
4404 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4405 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4406 // lsl (register)
4407 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4408 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4409 // lsr (immediate)
4410 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4411 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4412 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004413 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004414 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004415 // rrx is a special case encoding of ror (immediate)
4416 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4417 // ror (immediate)
4418 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4419 // ror (register)
4420 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4421 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004422
4423 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004424 // Load instructions
4425 //----------------------------------------------------------------------
4426 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004427 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004428 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004429 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4430 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004431 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4432
4433 //----------------------------------------------------------------------
4434 // Store instructions
4435 //----------------------------------------------------------------------
4436 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004437 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004438 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4439 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4440 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4441 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004442 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4443 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004444 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4445 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4446 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4447 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004448 };
4449
4450 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4451 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4452 {
4453 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4454 return &g_thumb_opcodes[i];
4455 }
4456 return NULL;
4457}
Greg Clayton64c84432011-01-21 22:02:52 +00004458
Greg Clayton31e2a382011-01-30 20:03:56 +00004459bool
Greg Clayton395fc332011-02-15 21:59:32 +00004460EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004461{
4462 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004463 const char *arch_cstr = arch.AsCString ();
4464 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004465 {
Greg Clayton395fc332011-02-15 21:59:32 +00004466 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4467 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4468 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4469 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4470 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4471 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4472 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4473 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4474 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4475 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004476 }
4477 return m_arm_isa != 0;
4478}
4479
4480
Greg Clayton64c84432011-01-21 22:02:52 +00004481bool
4482EmulateInstructionARM::ReadInstruction ()
4483{
4484 bool success = false;
4485 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4486 if (success)
4487 {
4488 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4489 if (success)
4490 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004491 Context read_inst_context;
4492 read_inst_context.type = eContextReadOpcode;
4493 read_inst_context.SetNoArgs ();
4494
Greg Clayton64c84432011-01-21 22:02:52 +00004495 if (m_inst_cpsr & MASK_CPSR_T)
4496 {
4497 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004498 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004499
4500 if (success)
4501 {
4502 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4503 {
4504 m_inst.opcode_type = eOpcode16;
4505 m_inst.opcode.inst16 = thumb_opcode;
4506 }
4507 else
4508 {
4509 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004510 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004511 }
4512 }
4513 }
4514 else
4515 {
4516 m_inst_mode = eModeARM;
4517 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004518 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004519 }
4520 }
4521 }
4522 if (!success)
4523 {
4524 m_inst_mode = eModeInvalid;
4525 m_inst_pc = LLDB_INVALID_ADDRESS;
4526 }
4527 return success;
4528}
4529
Johnny Chenee9b1f72011-02-09 01:00:31 +00004530uint32_t
4531EmulateInstructionARM::ArchVersion ()
4532{
4533 return m_arm_isa;
4534}
4535
Greg Clayton64c84432011-01-21 22:02:52 +00004536bool
4537EmulateInstructionARM::ConditionPassed ()
4538{
4539 if (m_inst_cpsr == 0)
4540 return false;
4541
4542 const uint32_t cond = CurrentCond ();
4543
4544 if (cond == UINT32_MAX)
4545 return false;
4546
4547 bool result = false;
4548 switch (UnsignedBits(cond, 3, 1))
4549 {
4550 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4551 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4552 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4553 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4554 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4555 case 5:
4556 {
4557 bool n = (m_inst_cpsr & MASK_CPSR_N);
4558 bool v = (m_inst_cpsr & MASK_CPSR_V);
4559 result = n == v;
4560 }
4561 break;
4562 case 6:
4563 {
4564 bool n = (m_inst_cpsr & MASK_CPSR_N);
4565 bool v = (m_inst_cpsr & MASK_CPSR_V);
4566 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4567 }
4568 break;
4569 case 7:
4570 result = true;
4571 break;
4572 }
4573
4574 if (cond & 1)
4575 result = !result;
4576 return result;
4577}
4578
Johnny Chen9ee056b2011-02-08 00:06:35 +00004579uint32_t
4580EmulateInstructionARM::CurrentCond ()
4581{
4582 switch (m_inst_mode)
4583 {
4584 default:
4585 case eModeInvalid:
4586 break;
4587
4588 case eModeARM:
4589 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4590
4591 case eModeThumb:
4592 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4593 // 'cond' field of the encoding.
4594 if (m_inst.opcode_type == eOpcode16 &&
4595 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4596 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4597 {
4598 return Bits32(m_inst.opcode.inst16, 11, 7);
4599 }
4600 else if (m_inst.opcode_type == eOpcode32 &&
4601 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4602 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4603 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4604 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4605 {
4606 return Bits32(m_inst.opcode.inst32, 25, 22);
4607 }
4608
4609 return m_it_session.GetCond();
4610 }
4611 return UINT32_MAX; // Return invalid value
4612}
4613
Johnny Chen9ee056b2011-02-08 00:06:35 +00004614bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004615EmulateInstructionARM::InITBlock()
4616{
4617 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4618}
4619
4620bool
4621EmulateInstructionARM::LastInITBlock()
4622{
4623 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4624}
4625
4626bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004627EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4628{
4629 addr_t target;
4630
Johnny Chenee9b1f72011-02-09 01:00:31 +00004631 // Check the current instruction set.
4632 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004633 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004634 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004635 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004636
Johnny Chen9ee056b2011-02-08 00:06:35 +00004637 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004638 return false;
4639
4640 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004641}
4642
4643// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4644bool
Johnny Chen668b4512011-02-15 21:08:58 +00004645EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004646{
4647 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004648 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4649 // we want to record it and issue a WriteRegister callback so the clients
4650 // can track the mode changes accordingly.
4651 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004652
4653 if (BitIsSet(addr, 0))
4654 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004655 if (CurrentInstrSet() != eModeThumb)
4656 {
4657 SelectInstrSet(eModeThumb);
4658 cpsr_changed = true;
4659 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004660 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004661 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004662 }
4663 else if (BitIsClear(addr, 1))
4664 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004665 if (CurrentInstrSet() != eModeARM)
4666 {
4667 SelectInstrSet(eModeARM);
4668 cpsr_changed = true;
4669 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004670 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004671 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004672 }
4673 else
4674 return false; // address<1:0> == '10' => UNPREDICTABLE
4675
Johnny Chen0f309db2011-02-09 19:11:32 +00004676 if (cpsr_changed)
4677 {
Johnny Chen558133b2011-02-09 23:59:17 +00004678 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004679 return false;
4680 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004681 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004682 return false;
4683
4684 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004685}
Greg Clayton64c84432011-01-21 22:02:52 +00004686
Johnny Chenee9b1f72011-02-09 01:00:31 +00004687// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4688bool
Johnny Chen668b4512011-02-15 21:08:58 +00004689EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004690{
4691 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004692 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004693 else
4694 return BranchWritePC((const Context)context, addr);
4695}
4696
Johnny Chen26863dc2011-02-09 23:43:29 +00004697// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4698bool
Johnny Chen668b4512011-02-15 21:08:58 +00004699EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004700{
4701 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004702 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004703 else
4704 return BranchWritePC((const Context)context, addr);
4705}
4706
Johnny Chenee9b1f72011-02-09 01:00:31 +00004707EmulateInstructionARM::Mode
4708EmulateInstructionARM::CurrentInstrSet ()
4709{
4710 return m_inst_mode;
4711}
4712
4713// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004714// ReadInstruction() is performed. This function has a side effect of updating
4715// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004716bool
4717EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4718{
Johnny Chen558133b2011-02-09 23:59:17 +00004719 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004720 switch (arm_or_thumb)
4721 {
4722 default:
4723 return false;
4724 eModeARM:
4725 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004726 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004727 break;
4728 eModeThumb:
4729 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004730 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004731 break;
4732 }
4733 return true;
4734}
4735
Johnny Chenef21b592011-02-10 01:52:38 +00004736// This function returns TRUE if the processor currently provides support for
4737// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4738// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4739bool
4740EmulateInstructionARM::UnalignedSupport()
4741{
4742 return (ArchVersion() >= ARMv7);
4743}
4744
Johnny Chenbf6ad172011-02-11 01:29:53 +00004745// The main addition and subtraction instructions can produce status information
4746// about both unsigned carry and signed overflow conditions. This status
4747// information can be used to synthesize multi-word additions and subtractions.
4748EmulateInstructionARM::AddWithCarryResult
4749EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4750{
4751 uint32_t result;
4752 uint8_t carry_out;
4753 uint8_t overflow;
4754
4755 uint64_t unsigned_sum = x + y + carry_in;
4756 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4757
4758 result = UnsignedBits(unsigned_sum, 31, 0);
4759 carry_out = (result == unsigned_sum ? 0 : 1);
4760 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4761
4762 AddWithCarryResult res = { result, carry_out, overflow };
4763 return res;
4764}
4765
Johnny Chenca67d1c2011-02-17 01:35:27 +00004766// Write the result to the ARM core register Rd, and optionally update the
4767// condition flags based on the result.
4768//
4769// This helper method tries to encapsulate the following pseudocode from the
4770// ARM Architecture Reference Manual:
4771//
4772// if d == 15 then // Can only occur for encoding A1
4773// ALUWritePC(result); // setflags is always FALSE here
4774// else
4775// R[d] = result;
4776// if setflags then
4777// APSR.N = result<31>;
4778// APSR.Z = IsZeroBit(result);
4779// APSR.C = carry;
4780// // APSR.V unchanged
4781//
4782// In the above case, the API client does not pass in the overflow arg, which
4783// defaults to ~0u.
4784bool
Johnny Chen10530c22011-02-17 22:37:12 +00004785EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
4786 const uint32_t result,
4787 const uint32_t Rd,
4788 bool setflags,
4789 const uint32_t carry,
4790 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00004791{
4792 if (Rd == 15)
4793 {
4794 if (!ALUWritePC (context, result))
4795 return false;
4796 }
4797 else
4798 {
4799 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
4800 return false;
4801 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00004802 return WriteFlags (context, result, carry, overflow);
4803 }
4804 return true;
4805}
4806
4807// This helper method tries to encapsulate the following pseudocode from the
4808// ARM Architecture Reference Manual:
4809//
4810// APSR.N = result<31>;
4811// APSR.Z = IsZeroBit(result);
4812// APSR.C = carry;
4813// APSR.V = overflow
4814//
4815// Default arguments can be specified for carry and overflow parameters, which means
4816// not to update the respective flags.
4817bool
4818EmulateInstructionARM::WriteFlags (Context &context,
4819 const uint32_t result,
4820 const uint32_t carry,
4821 const uint32_t overflow)
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;
Johnny Chenca67d1c2011-02-17 01:35:27 +00004834 }
4835 return true;
4836}
4837
Greg Clayton64c84432011-01-21 22:02:52 +00004838bool
4839EmulateInstructionARM::EvaluateInstruction ()
4840{
Johnny Chenc315f862011-02-05 00:46:10 +00004841 // Advance the ITSTATE bits to their values for the next instruction.
4842 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
4843 m_it_session.ITAdvance();
4844
Greg Clayton64c84432011-01-21 22:02:52 +00004845 return false;
4846}