blob: ff32926690def8d5d56b3642d8b3410d7e5d399b [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 Chen8fa20592011-02-18 01:22:22 +00001915// This instruction adds an immediate value to a register value, and writes the result to the destination
1916// register. It can optionally update the condition flags based on the result.
1917bool
1918EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
1919{
1920#if 0
1921 // ARM pseudo code...
1922 if ConditionPassed() then
1923 EncodingSpecificOperations();
1924 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1925 if d == 15 then
1926 ALUWritePC(result); // setflags is always FALSE here
1927 else
1928 R[d] = result;
1929 if setflags then
1930 APSR.N = result<31>;
1931 APSR.Z = IsZeroBit(result);
1932 APSR.C = carry;
1933 APSR.V = overflow;
1934#endif
1935
1936 bool success = false;
1937 const uint32_t opcode = OpcodeAsUnsigned (&success);
1938 if (!success)
1939 return false;
1940
1941 if (ConditionPassed())
1942 {
1943 uint32_t Rd, Rn;
1944 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
1945 bool setflags;
1946 switch (encoding)
1947 {
1948 case eEncodingA1:
1949 Rd = Bits32(opcode, 15, 12);
1950 Rn = Bits32(opcode, 19, 16);
1951 setflags = BitIsSet(opcode, 20);
1952 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1953 break;
1954 default:
1955 return false;
1956 }
1957
1958 int32_t val1;
1959 // Read the first operand.
1960 if (Rn == 15)
1961 {
1962 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1963 if (encoding == eEncodingT1 || encoding == eEncodingT2)
1964 val1 += 4;
1965 else
1966 val1 += 8;
1967 }
1968 else
1969 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1970 if (!success)
1971 return false;
1972
1973 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1974
1975 EmulateInstruction::Context context;
1976 context.type = EmulateInstruction::eContextImmediate;
1977 context.SetNoArgs ();
1978
1979 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1980 return false;
1981 }
1982 return true;
1983}
1984
Johnny Chend761dcf2011-02-17 22:03:29 +00001985// This instruction adds a register value and an optionally-shifted register value, and writes the result
1986// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001987bool
Johnny Chen9f687722011-02-18 00:02:28 +00001988EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001989{
1990#if 0
1991 // ARM pseudo code...
1992 if ConditionPassed() then
1993 EncodingSpecificOperations();
1994 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1995 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1996 if d == 15 then
1997 ALUWritePC(result); // setflags is always FALSE here
1998 else
1999 R[d] = result;
2000 if setflags then
2001 APSR.N = result<31>;
2002 APSR.Z = IsZeroBit(result);
2003 APSR.C = carry;
2004 APSR.V = overflow;
2005#endif
2006
2007 bool success = false;
2008 const uint32_t opcode = OpcodeAsUnsigned (&success);
2009 if (!success)
2010 return false;
2011
2012 if (ConditionPassed())
2013 {
2014 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002015 ARM_ShifterType shift_t;
2016 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002017 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002018 switch (encoding)
2019 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002020 case eEncodingT1:
2021 Rd = Bits32(opcode, 2, 0);
2022 Rn = Bits32(opcode, 5, 3);
2023 Rm = Bits32(opcode, 8, 6);
2024 setflags = !InITBlock();
2025 shift_t = SRType_LSL;
2026 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002027 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002028 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002029 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002030 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002031 shift_t = SRType_LSL;
2032 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002033 if (Rn == 15 && Rm == 15)
2034 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002035 if (Rd == 15 && InITBlock() && !LastInITBlock())
2036 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002037 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002038 case eEncodingA1:
2039 Rd = Bits32(opcode, 15, 12);
2040 Rn = Bits32(opcode, 19, 16);
2041 Rm = Bits32(opcode, 3, 0);
2042 setflags = BitIsSet(opcode, 20);
2043 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2044 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002045 default:
2046 return false;
2047 }
2048
Johnny Chen8fa20592011-02-18 01:22:22 +00002049 int32_t val1, val2;
Johnny Chen26863dc2011-02-09 23:43:29 +00002050 // Read the first operand.
2051 if (Rn == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00002052 {
Johnny Chen26863dc2011-02-09 23:43:29 +00002053 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00002054 if (encoding == eEncodingT1 || encoding == eEncodingT2)
2055 val1 += 4;
2056 else
2057 val1 += 8;
2058 }
Johnny Chen26863dc2011-02-09 23:43:29 +00002059 else
2060 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2061 if (!success)
2062 return false;
2063
2064 // Read the second operand.
2065 if (Rm == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00002066 {
Johnny Chen26863dc2011-02-09 23:43:29 +00002067 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00002068 if (encoding == eEncodingT1 || encoding == eEncodingT2)
2069 val1 += 4;
2070 else
2071 val1 += 8;
2072 }
Johnny Chen26863dc2011-02-09 23:43:29 +00002073 else
2074 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2075 if (!success)
2076 return false;
2077
Johnny Chen8fa20592011-02-18 01:22:22 +00002078 uint32_t shifted = Shift(val2, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
2079 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002080
2081 EmulateInstruction::Context context;
2082 context.type = EmulateInstruction::eContextImmediate;
2083 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002084
Johnny Chen10530c22011-02-17 22:37:12 +00002085 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002086 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002087 }
2088 return true;
2089}
2090
Johnny Chene4a4d302011-02-11 21:53:58 +00002091// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002092bool
Johnny Chen9f687722011-02-18 00:02:28 +00002093EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002094{
2095#if 0
2096 // ARM pseudo code...
2097 if ConditionPassed() then
2098 EncodingSpecificOperations();
2099 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2100 APSR.N = result<31>;
2101 APSR.Z = IsZeroBit(result);
2102 APSR.C = carry;
2103 APSR.V = overflow;
2104#endif
2105
2106 bool success = false;
2107 const uint32_t opcode = OpcodeAsUnsigned (&success);
2108 if (!success)
2109 return false;
2110
2111 uint32_t Rn; // the first operand
2112 uint32_t imm32; // the immediate value to be compared with
2113 switch (encoding) {
2114 case eEncodingT1:
2115 Rn = Bits32(opcode, 10, 8);
2116 imm32 = Bits32(opcode, 7, 0);
2117 break;
2118 default:
2119 return false;
2120 }
2121 // Read the register value from the operand register Rn.
2122 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2123 if (!success)
2124 return false;
2125
Johnny Chen10530c22011-02-17 22:37:12 +00002126 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2127
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002128 EmulateInstruction::Context context;
2129 context.type = EmulateInstruction::eContextImmediate;
2130 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002131 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2132 return false;
2133
Johnny Chend4dc4442011-02-11 02:02:56 +00002134 return true;
2135}
2136
Johnny Chene4a4d302011-02-11 21:53:58 +00002137// CMP (register)
2138bool
Johnny Chen9f687722011-02-18 00:02:28 +00002139EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002140{
2141#if 0
2142 // ARM pseudo code...
2143 if ConditionPassed() then
2144 EncodingSpecificOperations();
2145 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2146 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2147 APSR.N = result<31>;
2148 APSR.Z = IsZeroBit(result);
2149 APSR.C = carry;
2150 APSR.V = overflow;
2151#endif
2152
2153 bool success = false;
2154 const uint32_t opcode = OpcodeAsUnsigned (&success);
2155 if (!success)
2156 return false;
2157
2158 uint32_t Rn; // the first operand
2159 uint32_t Rm; // the second operand
2160 switch (encoding) {
2161 case eEncodingT1:
2162 Rn = Bits32(opcode, 2, 0);
2163 Rm = Bits32(opcode, 5, 3);
2164 break;
2165 case eEncodingT2:
2166 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2167 Rm = Bits32(opcode, 6, 3);
2168 if (Rn < 8 && Rm < 8)
2169 return false;
2170 if (Rn == 15 || Rm == 15)
2171 return false;
2172 break;
2173 default:
2174 return false;
2175 }
2176 // Read the register value from register Rn.
2177 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2178 if (!success)
2179 return false;
2180 // Read the register value from register Rm.
2181 // The register value is not being shifted since we don't handle ARM for now.
2182 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2183 if (!success)
2184 return false;
2185
Johnny Chen10530c22011-02-17 22:37:12 +00002186 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2187
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002188 EmulateInstruction::Context context;
2189 context.type = EmulateInstruction::eContextImmediate;
2190 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002191 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2192 return false;
2193
Johnny Chene4a4d302011-02-11 21:53:58 +00002194 return true;
2195}
2196
Johnny Chen82f16aa2011-02-15 20:10:55 +00002197// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2198// shifting in copies of its sign bit, and writes the result to the destination register. It can
2199// optionally update the condition flags based on the result.
2200bool
2201EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2202{
2203#if 0
2204 // ARM pseudo code...
2205 if ConditionPassed() then
2206 EncodingSpecificOperations();
2207 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2208 if d == 15 then // Can only occur for ARM encoding
2209 ALUWritePC(result); // setflags is always FALSE here
2210 else
2211 R[d] = result;
2212 if setflags then
2213 APSR.N = result<31>;
2214 APSR.Z = IsZeroBit(result);
2215 APSR.C = carry;
2216 // APSR.V unchanged
2217#endif
2218
Johnny Chen41a0a152011-02-16 01:27:54 +00002219 return EmulateShiftImm(encoding, SRType_ASR);
2220}
2221
2222// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2223// shifting in copies of its sign bit, and writes the result to the destination register.
2224// The variable number of bits is read from the bottom byte of a register. It can optionally update
2225// the condition flags based on the result.
2226bool
2227EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2228{
2229#if 0
2230 // ARM pseudo code...
2231 if ConditionPassed() then
2232 EncodingSpecificOperations();
2233 shift_n = UInt(R[m]<7:0>);
2234 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2235 R[d] = result;
2236 if setflags then
2237 APSR.N = result<31>;
2238 APSR.Z = IsZeroBit(result);
2239 APSR.C = carry;
2240 // APSR.V unchanged
2241#endif
2242
2243 return EmulateShiftReg(encoding, SRType_ASR);
2244}
2245
2246// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2247// shifting in zeros, and writes the result to the destination register. It can optionally
2248// update the condition flags based on the result.
2249bool
2250EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2251{
2252#if 0
2253 // ARM pseudo code...
2254 if ConditionPassed() then
2255 EncodingSpecificOperations();
2256 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2257 if d == 15 then // Can only occur for ARM encoding
2258 ALUWritePC(result); // setflags is always FALSE here
2259 else
2260 R[d] = result;
2261 if setflags then
2262 APSR.N = result<31>;
2263 APSR.Z = IsZeroBit(result);
2264 APSR.C = carry;
2265 // APSR.V unchanged
2266#endif
2267
2268 return EmulateShiftImm(encoding, SRType_LSL);
2269}
2270
2271// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2272// shifting in zeros, and writes the result to the destination register. The variable number
2273// of bits is read from the bottom byte of a register. It can optionally update the condition
2274// flags based on the result.
2275bool
2276EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2277{
2278#if 0
2279 // ARM pseudo code...
2280 if ConditionPassed() then
2281 EncodingSpecificOperations();
2282 shift_n = UInt(R[m]<7:0>);
2283 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2284 R[d] = result;
2285 if setflags then
2286 APSR.N = result<31>;
2287 APSR.Z = IsZeroBit(result);
2288 APSR.C = carry;
2289 // APSR.V unchanged
2290#endif
2291
2292 return EmulateShiftReg(encoding, SRType_LSL);
2293}
2294
2295// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2296// shifting in zeros, and writes the result to the destination register. It can optionally
2297// update the condition flags based on the result.
2298bool
2299EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2300{
2301#if 0
2302 // ARM pseudo code...
2303 if ConditionPassed() then
2304 EncodingSpecificOperations();
2305 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2306 if d == 15 then // Can only occur for ARM encoding
2307 ALUWritePC(result); // setflags is always FALSE here
2308 else
2309 R[d] = result;
2310 if setflags then
2311 APSR.N = result<31>;
2312 APSR.Z = IsZeroBit(result);
2313 APSR.C = carry;
2314 // APSR.V unchanged
2315#endif
2316
2317 return EmulateShiftImm(encoding, SRType_LSR);
2318}
2319
2320// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2321// shifting in zeros, and writes the result to the destination register. The variable number
2322// of bits is read from the bottom byte of a register. It can optionally update the condition
2323// flags based on the result.
2324bool
2325EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2326{
2327#if 0
2328 // ARM pseudo code...
2329 if ConditionPassed() then
2330 EncodingSpecificOperations();
2331 shift_n = UInt(R[m]<7:0>);
2332 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
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 EmulateShiftReg(encoding, SRType_LSR);
2342}
2343
Johnny Cheneeab4852011-02-16 22:14:44 +00002344// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2345// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2346// It can optionally update the condition flags based on the result.
2347bool
2348EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2349{
2350#if 0
2351 // ARM pseudo code...
2352 if ConditionPassed() then
2353 EncodingSpecificOperations();
2354 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2355 if d == 15 then // Can only occur for ARM encoding
2356 ALUWritePC(result); // setflags is always FALSE here
2357 else
2358 R[d] = result;
2359 if setflags then
2360 APSR.N = result<31>;
2361 APSR.Z = IsZeroBit(result);
2362 APSR.C = carry;
2363 // APSR.V unchanged
2364#endif
2365
2366 return EmulateShiftImm(encoding, SRType_ROR);
2367}
2368
2369// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2370// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2371// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2372// flags based on the result.
2373bool
2374EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2375{
2376#if 0
2377 // ARM pseudo code...
2378 if ConditionPassed() then
2379 EncodingSpecificOperations();
2380 shift_n = UInt(R[m]<7:0>);
2381 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2382 R[d] = result;
2383 if setflags then
2384 APSR.N = result<31>;
2385 APSR.Z = IsZeroBit(result);
2386 APSR.C = carry;
2387 // APSR.V unchanged
2388#endif
2389
2390 return EmulateShiftReg(encoding, SRType_ROR);
2391}
2392
2393// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2394// with the carry flag shifted into bit [31].
2395//
2396// RRX can optionally update the condition flags based on the result.
2397// In that case, bit [0] is shifted into the carry flag.
2398bool
2399EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2400{
2401#if 0
2402 // ARM pseudo code...
2403 if ConditionPassed() then
2404 EncodingSpecificOperations();
2405 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2406 if d == 15 then // Can only occur for ARM encoding
2407 ALUWritePC(result); // setflags is always FALSE here
2408 else
2409 R[d] = result;
2410 if setflags then
2411 APSR.N = result<31>;
2412 APSR.Z = IsZeroBit(result);
2413 APSR.C = carry;
2414 // APSR.V unchanged
2415#endif
2416
2417 return EmulateShiftImm(encoding, SRType_RRX);
2418}
2419
Johnny Chen41a0a152011-02-16 01:27:54 +00002420bool
2421EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2422{
2423 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2424
Johnny Chen82f16aa2011-02-15 20:10:55 +00002425 bool success = false;
2426 const uint32_t opcode = OpcodeAsUnsigned (&success);
2427 if (!success)
2428 return false;
2429
2430 if (ConditionPassed())
2431 {
Johnny Chene7f89532011-02-15 23:22:46 +00002432 uint32_t Rd; // the destination register
2433 uint32_t Rm; // the first operand register
2434 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002435 uint32_t carry; // the carry bit after the shift operation
2436 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002437
2438 // Special case handling!
2439 // A8.6.139 ROR (immediate) -- Encoding T1
2440 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2441 {
2442 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2443 // have the same decoding of bit fields as the other Thumb2 shift operations.
2444 encoding = eEncodingT2;
2445 }
2446
Johnny Chen82f16aa2011-02-15 20:10:55 +00002447 switch (encoding) {
2448 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002449 // Due to the above special case handling!
2450 assert(shift_type != SRType_ROR);
2451
Johnny Chen82f16aa2011-02-15 20:10:55 +00002452 Rd = Bits32(opcode, 2, 0);
2453 Rm = Bits32(opcode, 5, 3);
2454 setflags = !InITBlock();
2455 imm5 = Bits32(opcode, 10, 6);
2456 break;
2457 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002458 // A8.6.141 RRX
2459 assert(shift_type != SRType_RRX);
2460
Johnny Chen82f16aa2011-02-15 20:10:55 +00002461 Rd = Bits32(opcode, 11, 8);
2462 Rm = Bits32(opcode, 3, 0);
2463 setflags = BitIsSet(opcode, 20);
2464 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2465 if (BadReg(Rd) || BadReg(Rm))
2466 return false;
2467 break;
2468 case eEncodingA1:
2469 Rd = Bits32(opcode, 15, 12);
2470 Rm = Bits32(opcode, 3, 0);
2471 setflags = BitIsSet(opcode, 20);
2472 imm5 = Bits32(opcode, 11, 7);
2473 break;
2474 default:
2475 return false;
2476 }
2477
Johnny Cheneeab4852011-02-16 22:14:44 +00002478 // A8.6.139 ROR (immediate)
2479 if (shift_type == SRType_ROR && imm5 == 0)
2480 shift_type = SRType_RRX;
2481
Johnny Chen82f16aa2011-02-15 20:10:55 +00002482 // Get the first operand.
2483 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2484 if (!success)
2485 return false;
2486
Johnny Cheneeab4852011-02-16 22:14:44 +00002487 // Decode the shift amount if not RRX.
2488 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002489
Johnny Chen41a0a152011-02-16 01:27:54 +00002490 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002491
2492 // The context specifies that an immediate is to be moved into Rd.
2493 EmulateInstruction::Context context;
2494 context.type = EmulateInstruction::eContextImmediate;
2495 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002496
Johnny Chen10530c22011-02-17 22:37:12 +00002497 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002498 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002499 }
2500 return true;
2501}
2502
Johnny Chene7f89532011-02-15 23:22:46 +00002503bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002504EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002505{
Johnny Chen41a0a152011-02-16 01:27:54 +00002506 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002507
2508 bool success = false;
2509 const uint32_t opcode = OpcodeAsUnsigned (&success);
2510 if (!success)
2511 return false;
2512
2513 if (ConditionPassed())
2514 {
2515 uint32_t Rd; // the destination register
2516 uint32_t Rn; // the first operand register
2517 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2518 uint32_t carry; // the carry bit after the shift operation
2519 bool setflags;
2520 switch (encoding) {
2521 case eEncodingT1:
2522 Rd = Bits32(opcode, 2, 0);
2523 Rn = Rd;
2524 Rm = Bits32(opcode, 5, 3);
2525 setflags = !InITBlock();
2526 break;
2527 case eEncodingT2:
2528 Rd = Bits32(opcode, 11, 8);
2529 Rn = Bits32(opcode, 19, 16);
2530 Rm = Bits32(opcode, 3, 0);
2531 setflags = BitIsSet(opcode, 20);
2532 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2533 return false;
2534 break;
2535 case eEncodingA1:
2536 Rd = Bits32(opcode, 15, 12);
2537 Rn = Bits32(opcode, 3, 0);
2538 Rm = Bits32(opcode, 11, 8);
2539 setflags = BitIsSet(opcode, 20);
2540 if (Rd == 15 || Rn == 15 || Rm == 15)
2541 return false;
2542 break;
2543 default:
2544 return false;
2545 }
2546
2547 // Get the first operand.
2548 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2549 if (!success)
2550 return false;
2551 // Get the Rm register content.
2552 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2553 if (!success)
2554 return false;
2555
2556 // Get the shift amount.
2557 uint32_t amt = Bits32(val, 7, 0);
2558
Johnny Chen41a0a152011-02-16 01:27:54 +00002559 uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002560
2561 // The context specifies that an immediate is to be moved into Rd.
2562 EmulateInstruction::Context context;
2563 context.type = EmulateInstruction::eContextImmediate;
2564 context.SetNoArgs ();
2565
Johnny Chen10530c22011-02-17 22:37:12 +00002566 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002567 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002568 }
2569 return true;
2570}
2571
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002572// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002573// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002574// can be written back to the base register.
2575bool
2576EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2577{
2578#if 0
2579 // ARM pseudo code...
2580 if ConditionPassed()
2581 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2582 address = R[n];
2583
2584 for i = 0 to 14
2585 if registers<i> == '1' then
2586 R[i] = MemA[address, 4]; address = address + 4;
2587 if registers<15> == '1' then
2588 LoadWritePC (MemA[address, 4]);
2589
2590 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2591 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2592
2593#endif
2594
2595 bool success = false;
2596 const uint32_t opcode = OpcodeAsUnsigned (&success);
2597 if (!success)
2598 return false;
2599
2600 if (ConditionPassed())
2601 {
2602 uint32_t n;
2603 uint32_t registers = 0;
2604 bool wback;
2605 const uint32_t addr_byte_size = GetAddressByteSize();
2606 switch (encoding)
2607 {
2608 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002609 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002610 n = Bits32 (opcode, 10, 8);
2611 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002612 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002613 wback = BitIsClear (registers, n);
2614 // if BitCount(registers) < 1 then UNPREDICTABLE;
2615 if (BitCount(registers) < 1)
2616 return false;
2617 break;
2618 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002619 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2620 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002621 n = Bits32 (opcode, 19, 16);
2622 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002623 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002624 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002625
2626 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002627 if ((n == 15)
2628 || (BitCount (registers) < 2)
2629 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2630 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002631
2632 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002633 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002634 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002635
2636 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002637 if (wback
2638 && BitIsSet (registers, n))
2639 return false;
2640 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002641
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002642 case eEncodingA1:
2643 n = Bits32 (opcode, 19, 16);
2644 registers = Bits32 (opcode, 15, 0);
2645 wback = BitIsSet (opcode, 21);
2646 if ((n == 15)
2647 || (BitCount (registers) < 1))
2648 return false;
2649 break;
2650 default:
2651 return false;
2652 }
2653
2654 int32_t offset = 0;
2655 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2656 if (!success)
2657 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002658
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002659 EmulateInstruction::Context context;
2660 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2661 Register dwarf_reg;
2662 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2663 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002664
2665 for (int i = 0; i < 14; ++i)
2666 {
2667 if (BitIsSet (registers, i))
2668 {
Caroline Tice85aab332011-02-08 23:56:10 +00002669 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002670 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002671 if (wback && (n == 13)) // Pop Instruction
2672 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2673
2674 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002675 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002676 if (!success)
2677 return false;
2678
2679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2680 return false;
2681
2682 offset += addr_byte_size;
2683 }
2684 }
2685
2686 if (BitIsSet (registers, 15))
2687 {
2688 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002689 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002690 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002691 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002692 if (!success)
2693 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002694 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002695 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002696 return false;
2697 }
2698
2699 if (wback && BitIsClear (registers, n))
2700 {
Caroline Ticefa172202011-02-11 22:49:54 +00002701 // R[n] = R[n] + 4 * BitCount (registers)
2702 int32_t offset = addr_byte_size * BitCount (registers);
2703 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002704 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002705
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002706 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2707 return false;
2708 }
2709 if (wback && BitIsSet (registers, n))
2710 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002711 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002712 }
2713 return true;
2714}
Caroline Tice713c2662011-02-11 17:59:55 +00002715
2716// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2717// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2718// can optionally be written back tot he base registers.
2719bool
2720EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2721{
2722#if 0
2723 // ARM pseudo code...
2724 if ConditionPassed() then
2725 EncodingSpecificOperations();
2726 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002727
Caroline Tice713c2662011-02-11 17:59:55 +00002728 for i = 0 to 14
2729 if registers<i> == ’1’ then
2730 R[i] = MemA[address,4]; address = address + 4;
2731
2732 if registers<15> == ’1’ then
2733 LoadWritePC(MemA[address,4]);
2734
2735 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2736 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2737#endif
2738
2739 bool success = false;
2740 const uint32_t opcode = OpcodeAsUnsigned (&success);
2741 if (!success)
2742 return false;
2743
2744 if (ConditionPassed())
2745 {
2746 uint32_t n;
2747 uint32_t registers = 0;
2748 bool wback;
2749 const uint32_t addr_byte_size = GetAddressByteSize();
2750
2751 // EncodingSpecificOperations();
2752 switch (encoding)
2753 {
2754 case eEncodingA1:
2755 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2756 n = Bits32 (opcode, 19, 16);
2757 registers = Bits32 (opcode, 15, 0);
2758 wback = BitIsSet (opcode, 21);
2759
2760 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2761 if ((n == 15) || (BitCount (registers) < 1))
2762 return false;
2763
2764 break;
2765
2766 default:
2767 return false;
2768 }
2769 // address = R[n] - 4*BitCount(registers) + 4;
2770
2771 int32_t offset = 0;
2772 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2773
2774 if (!success)
2775 return false;
2776
2777 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2778
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002779 EmulateInstruction::Context context;
2780 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2781 Register dwarf_reg;
2782 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2783 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002784
2785 // for i = 0 to 14
2786 for (int i = 0; i < 14; ++i)
2787 {
2788 // if registers<i> == ’1’ then
2789 if (BitIsSet (registers, i))
2790 {
2791 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002792 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002793 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002794 if (!success)
2795 return false;
2796 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2797 return false;
2798 offset += addr_byte_size;
2799 }
2800 }
2801
2802 // if registers<15> == ’1’ then
2803 // LoadWritePC(MemA[address,4]);
2804 if (BitIsSet (registers, 15))
2805 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002806 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002807 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002808 if (!success)
2809 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002810 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002811 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002812 return false;
2813 }
2814
2815 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2816 if (wback && BitIsClear (registers, n))
2817 {
Caroline Tice713c2662011-02-11 17:59:55 +00002818 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2819 if (!success)
2820 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002821
2822 offset = (addr_byte_size * BitCount (registers)) * -1;
2823 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002824 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002825 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002826 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2827 return false;
2828 }
2829
2830 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2831 if (wback && BitIsSet (registers, n))
2832 return WriteBits32Unknown (n);
2833 }
2834 return true;
2835}
2836
2837// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2838// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2839// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002840bool
2841EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2842{
2843#if 0
2844 // ARM pseudo code...
2845 if ConditionPassed() then
2846 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2847 address = R[n] - 4*BitCount(registers);
2848
2849 for i = 0 to 14
2850 if registers<i> == ’1’ then
2851 R[i] = MemA[address,4]; address = address + 4;
2852 if registers<15> == ’1’ then
2853 LoadWritePC(MemA[address,4]);
2854
2855 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2856 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2857#endif
2858
2859 bool success = false;
2860 const uint32_t opcode = OpcodeAsUnsigned (&success);
2861 if (!success)
2862 return false;
2863
2864 if (ConditionPassed())
2865 {
2866 uint32_t n;
2867 uint32_t registers = 0;
2868 bool wback;
2869 const uint32_t addr_byte_size = GetAddressByteSize();
2870 switch (encoding)
2871 {
2872 case eEncodingT1:
2873 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2874 n = Bits32 (opcode, 19, 16);
2875 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002876 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002877 wback = BitIsSet (opcode, 21);
2878
2879 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2880 if ((n == 15)
2881 || (BitCount (registers) < 2)
2882 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2883 return false;
2884
2885 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002886 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002887 return false;
2888
2889 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2890 if (wback && BitIsSet (registers, n))
2891 return false;
2892
2893 break;
2894
2895 case eEncodingA1:
2896 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2897 n = Bits32 (opcode, 19, 16);
2898 registers = Bits32 (opcode, 15, 0);
2899 wback = BitIsSet (opcode, 21);
2900
2901 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2902 if ((n == 15) || (BitCount (registers) < 1))
2903 return false;
2904
2905 break;
2906
2907 default:
2908 return false;
2909 }
2910
Caroline Tice713c2662011-02-11 17:59:55 +00002911 // address = R[n] - 4*BitCount(registers);
2912
Caroline Tice0b29e242011-02-08 23:16:02 +00002913 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002914 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2915
2916 if (!success)
2917 return false;
2918
2919 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002920 EmulateInstruction::Context context;
2921 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2922 Register dwarf_reg;
2923 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2924 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002925
2926 for (int i = 0; i < 14; ++i)
2927 {
2928 if (BitIsSet (registers, i))
2929 {
2930 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002931 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002932 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002933 if (!success)
2934 return false;
2935
2936 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2937 return false;
2938
2939 offset += addr_byte_size;
2940 }
2941 }
2942
2943 // if registers<15> == ’1’ then
2944 // LoadWritePC(MemA[address,4]);
2945 if (BitIsSet (registers, 15))
2946 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002947 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002948 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002949 if (!success)
2950 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002951 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002952 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002953 return false;
2954 }
2955
2956 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2957 if (wback && BitIsClear (registers, n))
2958 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002959 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2960 if (!success)
2961 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002962
2963 offset = (addr_byte_size * BitCount (registers)) * -1;
2964 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002965 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002966 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002967 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2968 return false;
2969 }
2970
2971 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2972 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002973 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002974 }
2975 return true;
2976}
Caroline Tice85aab332011-02-08 23:56:10 +00002977
Caroline Tice713c2662011-02-11 17:59:55 +00002978// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2979// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2980// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002981bool
2982EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2983{
2984#if 0
2985 if ConditionPassed() then
2986 EncodingSpecificOperations();
2987 address = R[n] + 4;
2988
2989 for i = 0 to 14
2990 if registers<i> == ’1’ then
2991 R[i] = MemA[address,4]; address = address + 4;
2992 if registers<15> == ’1’ then
2993 LoadWritePC(MemA[address,4]);
2994
2995 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2996 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2997#endif
2998
2999 bool success = false;
3000 const uint32_t opcode = OpcodeAsUnsigned (&success);
3001 if (!success)
3002 return false;
3003
3004 if (ConditionPassed())
3005 {
3006 uint32_t n;
3007 uint32_t registers = 0;
3008 bool wback;
3009 const uint32_t addr_byte_size = GetAddressByteSize();
3010 switch (encoding)
3011 {
3012 case eEncodingA1:
3013 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3014 n = Bits32 (opcode, 19, 16);
3015 registers = Bits32 (opcode, 15, 0);
3016 wback = BitIsSet (opcode, 21);
3017
3018 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3019 if ((n == 15) || (BitCount (registers) < 1))
3020 return false;
3021
3022 break;
3023 default:
3024 return false;
3025 }
3026 // address = R[n] + 4;
3027
3028 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003029 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3030
3031 if (!success)
3032 return false;
3033
3034 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003035
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003036 EmulateInstruction::Context context;
3037 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3038 Register dwarf_reg;
3039 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3040 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003041
3042 for (int i = 0; i < 14; ++i)
3043 {
3044 if (BitIsSet (registers, i))
3045 {
3046 // R[i] = MemA[address,4]; address = address + 4;
3047
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003048 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003049 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003050 if (!success)
3051 return false;
3052
3053 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3054 return false;
3055
3056 offset += addr_byte_size;
3057 }
3058 }
3059
3060 // if registers<15> == ’1’ then
3061 // LoadWritePC(MemA[address,4]);
3062 if (BitIsSet (registers, 15))
3063 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003064 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003065 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003066 if (!success)
3067 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003068 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003069 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003070 return false;
3071 }
3072
3073 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3074 if (wback && BitIsClear (registers, n))
3075 {
Caroline Tice85aab332011-02-08 23:56:10 +00003076 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3077 if (!success)
3078 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003079
3080 offset = addr_byte_size * BitCount (registers);
3081 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003082 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003083 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003084 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3085 return false;
3086 }
3087
3088 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3089 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003090 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003091 }
3092 return true;
3093}
Caroline Tice0b29e242011-02-08 23:16:02 +00003094
Johnny Chenef21b592011-02-10 01:52:38 +00003095// Load Register (immediate) calculates an address from a base register value and
3096// an immediate offset, loads a word from memory, and writes to a register.
3097// LDR (immediate, Thumb)
3098bool
3099EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3100{
3101#if 0
3102 // ARM pseudo code...
3103 if (ConditionPassed())
3104 {
3105 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3106 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3107 address = if index then offset_addr else R[n];
3108 data = MemU[address,4];
3109 if wback then R[n] = offset_addr;
3110 if t == 15 then
3111 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3112 elsif UnalignedSupport() || address<1:0> = '00' then
3113 R[t] = data;
3114 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3115 }
3116#endif
3117
3118 bool success = false;
3119 const uint32_t opcode = OpcodeAsUnsigned (&success);
3120 if (!success)
3121 return false;
3122
3123 if (ConditionPassed())
3124 {
3125 uint32_t Rt; // the destination register
3126 uint32_t Rn; // the base register
3127 uint32_t imm32; // the immediate offset used to form the address
3128 addr_t offset_addr; // the offset address
3129 addr_t address; // the calculated address
3130 uint32_t data; // the literal data value from memory load
3131 bool add, index, wback;
3132 switch (encoding) {
3133 case eEncodingT1:
3134 Rt = Bits32(opcode, 5, 3);
3135 Rn = Bits32(opcode, 2, 0);
3136 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3137 // index = TRUE; add = TRUE; wback = FALSE
3138 add = true;
3139 index = true;
3140 wback = false;
3141 break;
3142 default:
3143 return false;
3144 }
3145 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3146 if (!success)
3147 return false;
3148 if (add)
3149 offset_addr = base + imm32;
3150 else
3151 offset_addr = base - imm32;
3152
3153 address = (index ? offset_addr : base);
3154
3155 if (wback)
3156 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003157 EmulateInstruction::Context ctx;
3158 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3159 Register dwarf_reg;
3160 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3161 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3162
Johnny Chenef21b592011-02-10 01:52:38 +00003163 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3164 return false;
3165 }
3166
3167 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003168 EmulateInstruction::Context context;
3169 context.type = EmulateInstruction::eContextImmediate;
3170 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003171
3172 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003173 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003174 if (!success)
3175 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003176
3177 if (Rt == 15)
3178 {
3179 if (Bits32(address, 1, 0) == 0)
3180 {
Johnny Chen668b4512011-02-15 21:08:58 +00003181 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003182 return false;
3183 }
3184 else
3185 return false;
3186 }
3187 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3188 {
3189 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3190 return false;
3191 }
3192 else
3193 return false;
3194 }
3195 return true;
3196}
3197
Caroline Ticeaf556562011-02-15 18:42:15 +00003198// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3199// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3200// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003201bool
3202EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3203{
3204#if 0
3205 if ConditionPassed() then
3206 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3207 address = R[n];
3208
3209 for i = 0 to 14
3210 if registers<i> == ’1’ then
3211 if i == n && wback && i != LowestSetBit(registers) then
3212 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3213 else
3214 MemA[address,4] = R[i];
3215 address = address + 4;
3216
3217 if registers<15> == ’1’ then // Only possible for encoding A1
3218 MemA[address,4] = PCStoreValue();
3219 if wback then R[n] = R[n] + 4*BitCount(registers);
3220#endif
3221
3222 bool success = false;
3223 const uint32_t opcode = OpcodeAsUnsigned (&success);
3224 if (!success)
3225 return false;
3226
3227 if (ConditionPassed ())
3228 {
3229 uint32_t n;
3230 uint32_t registers = 0;
3231 bool wback;
3232 const uint32_t addr_byte_size = GetAddressByteSize();
3233
3234 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3235 switch (encoding)
3236 {
3237 case eEncodingT1:
3238 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3239 n = Bits32 (opcode, 10, 8);
3240 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003241 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003242 wback = true;
3243
3244 // if BitCount(registers) < 1 then UNPREDICTABLE;
3245 if (BitCount (registers) < 1)
3246 return false;
3247
3248 break;
3249
3250 case eEncodingT2:
3251 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3252 n = Bits32 (opcode, 19, 16);
3253 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003254 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003255 wback = BitIsSet (opcode, 21);
3256
3257 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3258 if ((n == 15) || (BitCount (registers) < 2))
3259 return false;
3260
3261 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3262 if (wback && BitIsSet (registers, n))
3263 return false;
3264
3265 break;
3266
3267 case eEncodingA1:
3268 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3269 n = Bits32 (opcode, 19, 16);
3270 registers = Bits32 (opcode, 15, 0);
3271 wback = BitIsSet (opcode, 21);
3272
3273 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3274 if ((n == 15) || (BitCount (registers) < 1))
3275 return false;
3276
3277 break;
3278
3279 default:
3280 return false;
3281 }
3282
3283 // address = R[n];
3284 int32_t offset = 0;
3285 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3286 if (!success)
3287 return false;
3288
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003289 EmulateInstruction::Context context;
3290 context.type = EmulateInstruction::eContextRegisterStore;
3291 Register base_reg;
3292 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003293
3294 // for i = 0 to 14
3295 for (int i = 0; i < 14; ++i)
3296 {
3297 int lowest_set_bit = 14;
3298 // if registers<i> == ’1’ then
3299 if (BitIsSet (registers, i))
3300 {
3301 if (i < lowest_set_bit)
3302 lowest_set_bit = i;
3303 // if i == n && wback && i != LowestSetBit(registers) then
3304 if ((i == n) && wback && (i != lowest_set_bit))
3305 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3306 WriteBits32UnknownToMemory (address + offset);
3307 else
3308 {
3309 // MemA[address,4] = R[i];
3310 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3311 if (!success)
3312 return false;
3313
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003314 Register data_reg;
3315 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3316 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003317 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003318 return false;
3319 }
3320
3321 // address = address + 4;
3322 offset += addr_byte_size;
3323 }
3324 }
3325
3326 // if registers<15> == ’1’ then // Only possible for encoding A1
3327 // MemA[address,4] = PCStoreValue();
3328 if (BitIsSet (registers, 15))
3329 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003330 Register pc_reg;
3331 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3332 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003333 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3334 if (!success)
3335 return false;
3336
Caroline Ticecc96eb52011-02-17 19:20:40 +00003337 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003338 return false;
3339 }
3340
3341 // if wback then R[n] = R[n] + 4*BitCount(registers);
3342 if (wback)
3343 {
3344 offset = addr_byte_size * BitCount (registers);
3345 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003346 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003347 addr_t data = address + offset;
3348 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3349 return false;
3350 }
3351 }
3352 return true;
3353}
3354
Caroline Ticeaf556562011-02-15 18:42:15 +00003355// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3356// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3357// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003358bool
3359EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3360{
3361#if 0
3362 if ConditionPassed() then
3363 EncodingSpecificOperations();
3364 address = R[n] - 4*BitCount(registers) + 4;
3365
3366 for i = 0 to 14
3367 if registers<i> == ’1’ then
3368 if i == n && wback && i != LowestSetBit(registers) then
3369 MemA[address,4] = bits(32) UNKNOWN;
3370 else
3371 MemA[address,4] = R[i];
3372 address = address + 4;
3373
3374 if registers<15> == ’1’ then
3375 MemA[address,4] = PCStoreValue();
3376
3377 if wback then R[n] = R[n] - 4*BitCount(registers);
3378#endif
3379
3380 bool success = false;
3381 const uint32_t opcode = OpcodeAsUnsigned (&success);
3382 if (!success)
3383 return false;
3384
3385 if (ConditionPassed ())
3386 {
3387 uint32_t n;
3388 uint32_t registers = 0;
3389 bool wback;
3390 const uint32_t addr_byte_size = GetAddressByteSize();
3391
3392 // EncodingSpecificOperations();
3393 switch (encoding)
3394 {
3395 case eEncodingA1:
3396 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3397 n = Bits32 (opcode, 19, 16);
3398 registers = Bits32 (opcode, 15, 0);
3399 wback = BitIsSet (opcode, 21);
3400
3401 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3402 if ((n == 15) || (BitCount (registers) < 1))
3403 return false;
3404 break;
3405 default:
3406 return false;
3407 }
3408
3409 // address = R[n] - 4*BitCount(registers) + 4;
3410 int32_t offset = 0;
3411 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3412 if (!success)
3413 return false;
3414
3415 address = address - (addr_byte_size * BitCount (registers)) + 4;
3416
3417 EmulateInstruction::Context context;
3418 context.type = EmulateInstruction::eContextRegisterStore;
3419 Register base_reg;
3420 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3421
3422 // for i = 0 to 14
3423 for (int i = 0; i < 14; ++i)
3424 {
3425 int lowest_bit_set = 14;
3426 // if registers<i> == ’1’ then
3427 if (BitIsSet (registers, i))
3428 {
3429 if (i < lowest_bit_set)
3430 lowest_bit_set = i;
3431 //if i == n && wback && i != LowestSetBit(registers) then
3432 if ((i == n) && wback && (i != lowest_bit_set))
3433 // MemA[address,4] = bits(32) UNKNOWN;
3434 WriteBits32UnknownToMemory (address + offset);
3435 else
3436 {
3437 // MemA[address,4] = R[i];
3438 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3439 if (!success)
3440 return false;
3441
3442 Register data_reg;
3443 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3444 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003445 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003446 return false;
3447 }
3448
3449 // address = address + 4;
3450 offset += addr_byte_size;
3451 }
3452 }
3453
3454 // if registers<15> == ’1’ then
3455 // MemA[address,4] = PCStoreValue();
3456 if (BitIsSet (registers, 15))
3457 {
3458 Register pc_reg;
3459 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3460 context.SetRegisterPlusOffset (pc_reg, 8);
3461 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3462 if (!success)
3463 return false;
3464
Caroline Ticecc96eb52011-02-17 19:20:40 +00003465 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003466 return false;
3467 }
3468
3469 // if wback then R[n] = R[n] - 4*BitCount(registers);
3470 if (wback)
3471 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003472 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003473 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3474 context.SetImmediateSigned (offset);
3475 addr_t data = address + offset;
3476 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3477 return false;
3478 }
3479 }
3480 return true;
3481}
3482
Caroline Ticeaf556562011-02-15 18:42:15 +00003483// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3484// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3485// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003486bool
3487EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3488{
3489#if 0
3490 if ConditionPassed() then
3491 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3492 address = R[n] - 4*BitCount(registers);
3493
3494 for i = 0 to 14
3495 if registers<i> == ’1’ then
3496 if i == n && wback && i != LowestSetBit(registers) then
3497 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3498 else
3499 MemA[address,4] = R[i];
3500 address = address + 4;
3501
3502 if registers<15> == ’1’ then // Only possible for encoding A1
3503 MemA[address,4] = PCStoreValue();
3504
3505 if wback then R[n] = R[n] - 4*BitCount(registers);
3506#endif
3507
3508
3509 bool success = false;
3510 const uint32_t opcode = OpcodeAsUnsigned (&success);
3511 if (!success)
3512 return false;
3513
3514 if (ConditionPassed ())
3515 {
3516 uint32_t n;
3517 uint32_t registers = 0;
3518 bool wback;
3519 const uint32_t addr_byte_size = GetAddressByteSize();
3520
3521 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3522 switch (encoding)
3523 {
3524 case eEncodingT1:
3525 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3526 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3527 {
3528 // See PUSH
3529 }
3530 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3531 n = Bits32 (opcode, 19, 16);
3532 registers = Bits32 (opcode, 15, 0);
3533 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3534 wback = BitIsSet (opcode, 21);
3535 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3536 if ((n == 15) || BitCount (registers) < 2)
3537 return false;
3538 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3539 if (wback && BitIsSet (registers, n))
3540 return false;
3541 break;
3542
3543 case eEncodingA1:
3544 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3545 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3546 {
3547 // See Push
3548 }
3549 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3550 n = Bits32 (opcode, 19, 16);
3551 registers = Bits32 (opcode, 15, 0);
3552 wback = BitIsSet (opcode, 21);
3553 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3554 if ((n == 15) || BitCount (registers) < 1)
3555 return false;
3556 break;
3557
3558 default:
3559 return false;
3560 }
3561
3562 // address = R[n] - 4*BitCount(registers);
3563
3564 int32_t offset = 0;
3565 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3566 if (!success)
3567 return false;
3568
3569 address = address - (addr_byte_size * BitCount (registers));
3570
3571 EmulateInstruction::Context context;
3572 context.type = EmulateInstruction::eContextRegisterStore;
3573 Register base_reg;
3574 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3575
3576 // for i = 0 to 14
3577 for (int i = 0; i < 14; ++i)
3578 {
3579 uint32_t lowest_set_bit = 14;
3580 // if registers<i> == ’1’ then
3581 if (BitIsSet (registers, i))
3582 {
3583 if (i < lowest_set_bit)
3584 lowest_set_bit = i;
3585 // if i == n && wback && i != LowestSetBit(registers) then
3586 if ((i == n) && wback && (i != lowest_set_bit))
3587 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3588 WriteBits32UnknownToMemory (address + offset);
3589 else
3590 {
3591 // MemA[address,4] = R[i];
3592 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3593 if (!success)
3594 return false;
3595
3596 Register data_reg;
3597 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3598 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003599 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003600 return false;
3601 }
3602
3603 // address = address + 4;
3604 offset += addr_byte_size;
3605 }
3606 }
3607
3608 // if registers<15> == ’1’ then // Only possible for encoding A1
3609 // MemA[address,4] = PCStoreValue();
3610 if (BitIsSet (registers, 15))
3611 {
3612 Register pc_reg;
3613 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3614 context.SetRegisterPlusOffset (pc_reg, 8);
3615 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3616 if (!success)
3617 return false;
3618
Caroline Ticecc96eb52011-02-17 19:20:40 +00003619 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003620 return false;
3621 }
3622
3623 // if wback then R[n] = R[n] - 4*BitCount(registers);
3624 if (wback)
3625 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003626 offset = (addr_byte_size * BitCount (registers)) * -1;
3627 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3628 context.SetImmediateSigned (offset);
3629 addr_t data = address + offset;
3630 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3631 return false;
3632 }
3633 }
3634 return true;
3635}
3636
3637// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3638// from a base register. The consecutive memory locations start just above this address, and the address of the last
3639// of those locations can optionally be written back to the base register.
3640bool
3641EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3642{
3643#if 0
3644 if ConditionPassed() then
3645 EncodingSpecificOperations();
3646 address = R[n] + 4;
3647
3648 for i = 0 to 14
3649 if registers<i> == ’1’ then
3650 if i == n && wback && i != LowestSetBit(registers) then
3651 MemA[address,4] = bits(32) UNKNOWN;
3652 else
3653 MemA[address,4] = R[i];
3654 address = address + 4;
3655
3656 if registers<15> == ’1’ then
3657 MemA[address,4] = PCStoreValue();
3658
3659 if wback then R[n] = R[n] + 4*BitCount(registers);
3660#endif
3661
3662 bool success = false;
3663 const uint32_t opcode = OpcodeAsUnsigned (&success);
3664 if (!success)
3665 return false;
3666
3667 if (ConditionPassed())
3668 {
3669 uint32_t n;
3670 uint32_t registers = 0;
3671 bool wback;
3672 const uint32_t addr_byte_size = GetAddressByteSize();
3673
3674 // EncodingSpecificOperations();
3675 switch (encoding)
3676 {
3677 case eEncodingA1:
3678 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3679 n = Bits32 (opcode, 19, 16);
3680 registers = Bits32 (opcode, 15, 0);
3681 wback = BitIsSet (opcode, 21);
3682
3683 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3684 if ((n == 15) && (BitCount (registers) < 1))
3685 return false;
3686 break;
3687 default:
3688 return false;
3689 }
3690 // address = R[n] + 4;
3691
3692 int32_t offset = 0;
3693 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3694 if (!success)
3695 return false;
3696
3697 address = address + addr_byte_size;
3698
3699 EmulateInstruction::Context context;
3700 context.type = EmulateInstruction::eContextRegisterStore;
3701 Register base_reg;
3702 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3703
3704 uint32_t lowest_set_bit = 14;
3705 // for i = 0 to 14
3706 for (int i = 0; i < 14; ++i)
3707 {
3708 // if registers<i> == ’1’ then
3709 if (BitIsSet (registers, i))
3710 {
3711 if (i < lowest_set_bit)
3712 lowest_set_bit = i;
3713 // if i == n && wback && i != LowestSetBit(registers) then
3714 if ((i == n) && wback && (i != lowest_set_bit))
3715 // MemA[address,4] = bits(32) UNKNOWN;
3716 WriteBits32UnknownToMemory (address + offset);
3717 // else
3718 else
3719 {
3720 // MemA[address,4] = R[i];
3721 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3722 if (!success)
3723 return false;
3724
3725 Register data_reg;
3726 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3727 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003728 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003729 return false;
3730 }
3731
3732 // address = address + 4;
3733 offset += addr_byte_size;
3734 }
3735 }
3736
3737 // if registers<15> == ’1’ then
3738 // MemA[address,4] = PCStoreValue();
3739 if (BitIsSet (registers, 15))
3740 {
3741 Register pc_reg;
3742 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3743 context.SetRegisterPlusOffset (pc_reg, 8);
3744 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3745 if (!success)
3746 return false;
3747
Caroline Ticecc96eb52011-02-17 19:20:40 +00003748 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003749 return false;
3750 }
3751
3752 // if wback then R[n] = R[n] + 4*BitCount(registers);
3753 if (wback)
3754 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003755 offset = addr_byte_size * BitCount (registers);
3756 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3757 context.SetImmediateSigned (offset);
3758 addr_t data = address + offset;
3759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3760 return false;
3761 }
3762 }
3763 return true;
3764}
Caroline Tice7fac8572011-02-15 22:53:54 +00003765
3766// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3767// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3768bool
3769EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3770{
3771#if 0
3772 if ConditionPassed() then
3773 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3774 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3775 address = if index then offset_addr else R[n];
3776 if UnalignedSupport() || address<1:0> == ’00’ then
3777 MemU[address,4] = R[t];
3778 else // Can only occur before ARMv7
3779 MemU[address,4] = bits(32) UNKNOWN;
3780 if wback then R[n] = offset_addr;
3781#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003782
Caroline Tice7fac8572011-02-15 22:53:54 +00003783 bool success = false;
3784 const uint32_t opcode = OpcodeAsUnsigned (&success);
3785 if (!success)
3786 return false;
3787
3788 if (ConditionPassed())
3789 {
3790 const uint32_t addr_byte_size = GetAddressByteSize();
3791
3792 uint32_t t;
3793 uint32_t n;
3794 uint32_t imm32;
3795 bool index;
3796 bool add;
3797 bool wback;
3798 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3799 switch (encoding)
3800 {
3801 case eEncodingT1:
3802 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3803 t = Bits32 (opcode, 2, 0);
3804 n = Bits32 (opcode, 5, 3);
3805 imm32 = Bits32 (opcode, 10, 6) << 2;
3806
3807 // index = TRUE; add = TRUE; wback = FALSE;
3808 index = true;
3809 add = false;
3810 wback = false;
3811 break;
3812
3813 case eEncodingT2:
3814 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3815 t = Bits32 (opcode, 10, 8);
3816 n = 13;
3817 imm32 = Bits32 (opcode, 7, 0) << 2;
3818
3819 // index = TRUE; add = TRUE; wback = FALSE;
3820 index = true;
3821 add = true;
3822 wback = false;
3823 break;
3824
3825 case eEncodingT3:
3826 // if Rn == ’1111’ then UNDEFINED;
3827 if (Bits32 (opcode, 19, 16) == 15)
3828 return false;
3829
3830 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3831 t = Bits32 (opcode, 15, 12);
3832 n = Bits32 (opcode, 19, 16);
3833 imm32 = Bits32 (opcode, 11, 0);
3834
3835 // index = TRUE; add = TRUE; wback = FALSE;
3836 index = true;
3837 add = true;
3838 wback = false;
3839
3840 // if t == 15 then UNPREDICTABLE;
3841 if (t == 15)
3842 return false;
3843 break;
3844
3845 case eEncodingT4:
3846 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3847 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3848 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3849 if ((Bits32 (opcode, 19, 16) == 15)
3850 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3851 return false;
3852
3853 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3854 t = Bits32 (opcode, 15, 12);
3855 n = Bits32 (opcode, 19, 16);
3856 imm32 = Bits32 (opcode, 7, 0);
3857
3858 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3859 index = BitIsSet (opcode, 10);
3860 add = BitIsSet (opcode, 9);
3861 wback = BitIsSet (opcode, 8);
3862
3863 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3864 if ((t == 15) || (wback && (n == t)))
3865 return false;
3866 break;
3867
3868 default:
3869 return false;
3870 }
3871
3872 addr_t offset_addr;
3873 addr_t address;
3874
3875 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3876 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3877 if (!success)
3878 return false;
3879
3880 if (add)
3881 offset_addr = base_address + imm32;
3882 else
3883 offset_addr = base_address - imm32;
3884
3885 // address = if index then offset_addr else R[n];
3886 if (index)
3887 address = offset_addr;
3888 else
3889 address = base_address;
3890
3891 EmulateInstruction::Context context;
3892 context.type = eContextRegisterStore;
3893 Register base_reg;
3894 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3895
3896 // if UnalignedSupport() || address<1:0> == ’00’ then
3897 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3898 {
3899 // MemU[address,4] = R[t];
3900 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3901 if (!success)
3902 return false;
3903
3904 Register data_reg;
3905 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3906 int32_t offset = address - base_address;
3907 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003908 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003909 return false;
3910 }
3911 else
3912 {
3913 // MemU[address,4] = bits(32) UNKNOWN;
3914 WriteBits32UnknownToMemory (address);
3915 }
3916
3917 // if wback then R[n] = offset_addr;
3918 if (wback)
3919 {
3920 context.type = eContextRegisterLoad;
3921 context.SetAddress (offset_addr);
3922 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3923 return false;
3924 }
3925 }
3926 return true;
3927}
Caroline Ticeaf556562011-02-15 18:42:15 +00003928
Caroline Tice3fd63e92011-02-16 00:33:43 +00003929// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3930// word from a register to memory. The offset register value can optionally be shifted.
3931bool
3932EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3933{
3934#if 0
3935 if ConditionPassed() then
3936 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3937 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3938 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3939 address = if index then offset_addr else R[n];
3940 if t == 15 then // Only possible for encoding A1
3941 data = PCStoreValue();
3942 else
3943 data = R[t];
3944 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3945 MemU[address,4] = data;
3946 else // Can only occur before ARMv7
3947 MemU[address,4] = bits(32) UNKNOWN;
3948 if wback then R[n] = offset_addr;
3949#endif
3950
3951 bool success = false;
3952 const uint32_t opcode = OpcodeAsUnsigned (&success);
3953 if (!success)
3954 return false;
3955
3956 if (ConditionPassed())
3957 {
3958 const uint32_t addr_byte_size = GetAddressByteSize();
3959
3960 uint32_t t;
3961 uint32_t n;
3962 uint32_t m;
3963 ARM_ShifterType shift_t;
3964 uint32_t shift_n;
3965 bool index;
3966 bool add;
3967 bool wback;
3968
3969 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3970 switch (encoding)
3971 {
3972 case eEncodingT1:
3973 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3974 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3975 t = Bits32 (opcode, 2, 0);
3976 n = Bits32 (opcode, 5, 3);
3977 m = Bits32 (opcode, 8, 6);
3978
3979 // index = TRUE; add = TRUE; wback = FALSE;
3980 index = true;
3981 add = true;
3982 wback = false;
3983
3984 // (shift_t, shift_n) = (SRType_LSL, 0);
3985 shift_t = SRType_LSL;
3986 shift_n = 0;
3987 break;
3988
3989 case eEncodingT2:
3990 // if Rn == ’1111’ then UNDEFINED;
3991 if (Bits32 (opcode, 19, 16) == 15)
3992 return false;
3993
3994 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3995 t = Bits32 (opcode, 15, 12);
3996 n = Bits32 (opcode, 19, 16);
3997 m = Bits32 (opcode, 3, 0);
3998
3999 // index = TRUE; add = TRUE; wback = FALSE;
4000 index = true;
4001 add = true;
4002 wback = false;
4003
4004 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4005 shift_t = SRType_LSL;
4006 shift_n = Bits32 (opcode, 5, 4);
4007
4008 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4009 if ((t == 15) || (BadReg (m)))
4010 return false;
4011 break;
4012
4013 case eEncodingA1:
4014 {
4015 // if P == ’0’ && W == ’1’ then SEE STRT;
4016 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4017 t = Bits32 (opcode, 15, 12);
4018 n = Bits32 (opcode, 19, 16);
4019 m = Bits32 (opcode, 3, 0);
4020
4021 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4022 index = BitIsSet (opcode, 24);
4023 add = BitIsSet (opcode, 23);
4024 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4025
4026 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4027 uint32_t typ = Bits32 (opcode, 6, 5);
4028 uint32_t imm5 = Bits32 (opcode, 11, 7);
4029 shift_n = DecodeImmShift(typ, imm5, shift_t);
4030
4031 // if m == 15 then UNPREDICTABLE;
4032 if (m == 15)
4033 return false;
4034
4035 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4036 if (wback && ((n == 15) || (n == t)))
4037 return false;
4038
4039 break;
4040 }
4041 default:
4042 return false;
4043 }
4044
4045 addr_t offset_addr;
4046 addr_t address;
4047 int32_t offset = 0;
4048
4049 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4050 if (!success)
4051 return false;
4052
4053 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4054 if (!success)
4055 return false;
4056
4057 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4058 offset = Shift (Rm_data, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
4059
4060 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4061 if (add)
4062 offset_addr = base_address + offset;
4063 else
4064 offset_addr = base_address - offset;
4065
4066 // address = if index then offset_addr else R[n];
4067 if (index)
4068 address = offset_addr;
4069 else
4070 address = base_address;
4071
4072 uint32_t data;
4073 // if t == 15 then // Only possible for encoding A1
4074 if (t == 15)
4075 // data = PCStoreValue();
4076 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4077 else
4078 // data = R[t];
4079 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4080
4081 if (!success)
4082 return false;
4083
4084 EmulateInstruction::Context context;
4085 context.type = eContextRegisterStore;
4086
4087 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4088 if (UnalignedSupport ()
4089 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4090 || CurrentInstrSet() == eModeARM)
4091 {
4092 // MemU[address,4] = data;
4093
4094 Register base_reg;
4095 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4096
4097 Register data_reg;
4098 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4099
4100 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004101 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004102 return false;
4103
4104 }
4105 else
4106 // MemU[address,4] = bits(32) UNKNOWN;
4107 WriteBits32UnknownToMemory (address);
4108
4109 // if wback then R[n] = offset_addr;
4110 if (wback)
4111 {
4112 context.type = eContextRegisterLoad;
4113 context.SetAddress (offset_addr);
4114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4115 return false;
4116 }
4117
4118 }
4119 return true;
4120}
Caroline Tice73a29de2011-02-16 20:22:22 +00004121
4122bool
4123EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4124{
4125#if 0
4126 if ConditionPassed() then
4127 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4128 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4129 address = if index then offset_addr else R[n];
4130 MemU[address,1] = R[t]<7:0>;
4131 if wback then R[n] = offset_addr;
4132#endif
4133
4134
4135 bool success = false;
4136 const uint32_t opcode = OpcodeAsUnsigned (&success);
4137 if (!success)
4138 return false;
4139
4140 if (ConditionPassed ())
4141 {
4142 uint32_t t;
4143 uint32_t n;
4144 uint32_t imm32;
4145 bool index;
4146 bool add;
4147 bool wback;
4148 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4149 switch (encoding)
4150 {
4151 case eEncodingT1:
4152 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4153 t = Bits32 (opcode, 2, 0);
4154 n = Bits32 (opcode, 5, 3);
4155 imm32 = Bits32 (opcode, 10, 6);
4156
4157 // index = TRUE; add = TRUE; wback = FALSE;
4158 index = true;
4159 add = true;
4160 wback = false;
4161 break;
4162
4163 case eEncodingT2:
4164 // if Rn == ’1111’ then UNDEFINED;
4165 if (Bits32 (opcode, 19, 16) == 15)
4166 return false;
4167
4168 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4169 t = Bits32 (opcode, 15, 12);
4170 n = Bits32 (opcode, 19, 16);
4171 imm32 = Bits32 (opcode, 11, 0);
4172
4173 // index = TRUE; add = TRUE; wback = FALSE;
4174 index = true;
4175 add = true;
4176 wback = false;
4177
4178 // if BadReg(t) then UNPREDICTABLE;
4179 if (BadReg (t))
4180 return false;
4181 break;
4182
4183 case eEncodingT3:
4184 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4185 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4186 if (Bits32 (opcode, 19, 16) == 15)
4187 return false;
4188
4189 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4190 t = Bits32 (opcode, 15, 12);
4191 n = Bits32 (opcode, 19, 16);
4192 imm32 = Bits32 (opcode, 7, 0);
4193
4194 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4195 index = BitIsSet (opcode, 10);
4196 add = BitIsSet (opcode, 9);
4197 wback = BitIsSet (opcode, 8);
4198
4199 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4200 if ((BadReg (t)) || (wback && (n == t)))
4201 return false;
4202 break;
4203
4204 default:
4205 return false;
4206 }
4207
4208 addr_t offset_addr;
4209 addr_t address;
4210 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4211 if (!success)
4212 return false;
4213
4214 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4215 if (add)
4216 offset_addr = base_address + imm32;
4217 else
4218 offset_addr = base_address - imm32;
4219
4220 // address = if index then offset_addr else R[n];
4221 if (index)
4222 address = offset_addr;
4223 else
4224 address = base_address;
4225
Caroline Ticecc96eb52011-02-17 19:20:40 +00004226 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004227 Register base_reg;
4228 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4229
4230 Register data_reg;
4231 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4232
4233 EmulateInstruction::Context context;
4234 context.type = eContextRegisterStore;
4235 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4236
4237 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4238 if (!success)
4239 return false;
4240
4241 data = Bits32 (data, 7, 0);
4242
Caroline Ticecc96eb52011-02-17 19:20:40 +00004243 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004244 return false;
4245
4246 // if wback then R[n] = offset_addr;
4247 if (wback)
4248 {
4249 context.type = eContextRegisterLoad;
4250 context.SetAddress (offset_addr);
4251 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4252 return false;
4253 }
4254
4255 }
4256
4257 return true;
4258}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004259
Caroline Tice4d729c52011-02-18 00:55:53 +00004260// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
4261// from memory, and writes it to a register. It an use offset, post-indexed, or pre-indexed addressing.
4262bool
4263EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4264{
4265#if 0
4266 if ConditionPassed() then
4267 EncodingSpecificOperations();
4268 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4269 address = if index then offset_addr else R[n];
4270 data = MemU[address,4];
4271 if wback then R[n] = offset_addr;
4272 if t == 15 then
4273 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4274 elsif UnalignedSupport() || address<1:0> = ’00’ then
4275 R[t] = data;
4276 else // Can only apply before ARMv7
4277 R[t] = ROR(data, 8*UInt(address<1:0>));
4278#endif
4279
4280 bool success = false;
4281 const uint32_t opcode = OpcodeAsUnsigned (&success);
4282 if (!success)
4283 return false;
4284
4285 if (ConditionPassed ())
4286 {
4287 const uint32_t addr_byte_size = GetAddressByteSize();
4288
4289 uint32_t t;
4290 uint32_t n;
4291 uint32_t imm32;
4292 bool index;
4293 bool add;
4294 bool wback;
4295
4296 switch (encoding)
4297 {
4298 case eEncodingA1:
4299 // if Rn == ’1111’ then SEE LDR (literal);
4300 // if P == ’0’ && W == ’1’ then SEE LDRT;
4301 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4302 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4303 t = Bits32 (opcode, 15, 12);
4304 n = Bits32 (opcode, 19, 16);
4305 imm32 = Bits32 (opcode, 11, 0);
4306
4307 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4308 index = BitIsSet (opcode, 24);
4309 add = BitIsSet (opcode, 23);
4310 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4311
4312 // if wback && n == t then UNPREDICTABLE;
4313 if (wback && (n == t))
4314 return false;
4315
4316 break;
4317
4318 default:
4319 return false;
4320 }
4321
4322 addr_t address;
4323 addr_t offset_addr;
4324 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4325 if (!success)
4326 return false;
4327
4328 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4329 if (add)
4330 offset_addr = base_address + imm32;
4331 else
4332 offset_addr = base_address - imm32;
4333
4334 // address = if index then offset_addr else R[n];
4335 if (index)
4336 address = offset_addr;
4337 else
4338 address = base_address;
4339
4340 // data = MemU[address,4];
4341
4342 Register base_reg;
4343 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4344
4345 EmulateInstruction::Context context;
4346 context.type = eContextRegisterLoad;
4347 context.SetRegisterPlusOffset (base_reg, address - base_address);
4348
4349 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4350 if (!success)
4351 return false;
4352
4353 // if wback then R[n] = offset_addr;
4354 if (wback)
4355 {
4356 context.type = eContextAdjustBaseRegister;
4357 context.SetAddress (offset_addr);
4358 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4359 return false;
4360 }
4361
4362 // if t == 15 then
4363 if (t == 15)
4364 {
4365 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4366 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4367 {
4368 // LoadWritePC (data);
4369 context.type = eContextRegisterLoad;
4370 context.SetRegisterPlusOffset (base_reg, address - base_address);
4371 LoadWritePC (context, data);
4372 }
4373 else
4374 return false;
4375 }
4376 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4377 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4378 {
4379 // R[t] = data;
4380 context.type = eContextRegisterLoad;
4381 context.SetRegisterPlusOffset (base_reg, address - base_address);
4382 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4383 return false;
4384 }
4385 // else // Can only apply before ARMv7
4386 else
4387 {
4388 // R[t] = ROR(data, 8*UInt(address<1:0>));
4389 data = ROR (data, Bits32 (address, 1, 0));
4390 context.type = eContextRegisterLoad;
4391 context.SetImmediate (data);
4392 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4393 return false;
4394 }
4395
4396 }
4397 return true;
4398}
4399
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004400EmulateInstructionARM::ARMOpcode*
4401EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004402{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004403 static ARMOpcode
4404 g_arm_opcodes[] =
4405 {
4406 //----------------------------------------------------------------------
4407 // Prologue instructions
4408 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004409
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004410 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00004411 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
4412 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004413
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004414 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00004415 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004416 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004417 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00004418 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
4419 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004420 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004421
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004422 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00004423 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004424
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004425 // push one register
4426 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004427 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004428
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004429 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004430 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4431 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004432
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004433 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004434 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004435 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004436
Johnny Chen9f687722011-02-18 00:02:28 +00004437 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
4438 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004439 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004440 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4441
4442 //----------------------------------------------------------------------
4443 // Supervisor Call (previously Software Interrupt)
4444 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004445 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4446
4447 //----------------------------------------------------------------------
4448 // Branch instructions
4449 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004450 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00004451 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
4452 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4453 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4454 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004455 // for example, "bx lr"
4456 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004457
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004458 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00004459 // Data-processing instructions
4460 //----------------------------------------------------------------------
Johnny Chen8fa20592011-02-18 01:22:22 +00004461 // add (immediate)
4462 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s} <Rd>, <Rn>, #const"},
4463 // add (register)
4464 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s} <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen28070c32011-02-12 01:27:26 +00004465 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00004466 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004467 // asr (immediate)
4468 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004469 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00004470 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004471 // lsl (immediate)
4472 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
4473 // lsl (register)
4474 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
4475 // lsr (immediate)
4476 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
4477 // lsr (register)
4478 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004479 // rrx is a special case encoding of ror (immediate)
4480 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
4481 // ror (immediate)
4482 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
4483 // ror (register)
4484 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004485
4486 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004487 // Load instructions
4488 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00004489 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00004490 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00004491 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00004492 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00004493 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00004494
4495 //----------------------------------------------------------------------
4496 // Store instructions
4497 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00004498 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004499 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00004500 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004501 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
4502 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00004503
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004504
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004505 };
4506 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
4507
4508 for (size_t i=0; i<k_num_arm_opcodes; ++i)
4509 {
4510 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
4511 return &g_arm_opcodes[i];
4512 }
4513 return NULL;
4514}
Greg Clayton64c84432011-01-21 22:02:52 +00004515
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004516
4517EmulateInstructionARM::ARMOpcode*
4518EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00004519{
Johnny Chenfdd179e2011-01-31 20:09:28 +00004520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004521 static ARMOpcode
4522 g_thumb_opcodes[] =
4523 {
4524 //----------------------------------------------------------------------
4525 // Prologue instructions
4526 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00004527
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004528 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00004529 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
4530 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
4531 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00004532
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004533 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00004534 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004535 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00004536 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00004537 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00004538 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00004539
Johnny Chen864a8e82011-02-18 00:07:39 +00004540 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00004541 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00004542
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004543 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00004544 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
4545 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
4546 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
4547 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004548
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004549 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00004550 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4551 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00004552
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004553 //----------------------------------------------------------------------
4554 // Epilogue instructions
4555 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00004556
Johnny Chen864a8e82011-02-18 00:07:39 +00004557 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00004558 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
4559 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
4560 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00004561 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
4562 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004563
4564 //----------------------------------------------------------------------
4565 // Supervisor Call (previously Software Interrupt)
4566 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00004567 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
4568
4569 //----------------------------------------------------------------------
4570 // If Then makes up to four following instructions conditional.
4571 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004572 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
4573
4574 //----------------------------------------------------------------------
4575 // Branch instructions
4576 //----------------------------------------------------------------------
4577 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
4578 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
4579 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00004580 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004581 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00004582 // J1 == J2 == 1
4583 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
4584 // J1 == J2 == 1
4585 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
4586 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00004587 // for example, "bx lr"
4588 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00004589 // compare and branch
4590 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00004591 // table branch byte
4592 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
4593 // table branch halfword
4594 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004595
4596 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00004597 // Data-processing instructions
4598 //----------------------------------------------------------------------
Johnny Chen9f687722011-02-18 00:02:28 +00004599 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004600 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chend761dcf2011-02-17 22:03:29 +00004601 // Can update PC!
Johnny Chen9f687722011-02-18 00:02:28 +00004602 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004603 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00004604 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00004605 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00004606 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00004607 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00004608 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
4609 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00004610 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00004611 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00004612 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00004613 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004614 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00004615 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00004616 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00004617 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00004618 // asr (immediate)
4619 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00004620 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00004621 // asr (register)
4622 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
4623 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004624 // lsl (immediate)
4625 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
4626 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
4627 // lsl (register)
4628 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
4629 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
4630 // lsr (immediate)
4631 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
4632 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
4633 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00004634 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00004635 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00004636 // rrx is a special case encoding of ror (immediate)
4637 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
4638 // ror (immediate)
4639 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
4640 // ror (register)
4641 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
4642 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00004643
4644 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00004645 // Load instructions
4646 //----------------------------------------------------------------------
4647 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00004648 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00004649 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00004650 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
4651 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00004652 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
4653
4654 //----------------------------------------------------------------------
4655 // Store instructions
4656 //----------------------------------------------------------------------
4657 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004658 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00004659 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
4660 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>{,#<imm>}]" },
4661 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [SP,#<imm>]" },
4662 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt [<Rn>,#<imm12>]" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00004663 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt> [<Rn>,#+/-<imm8>]" },
4664 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> {<Rn> <Rm>]" },
Caroline Tice73a29de2011-02-16 20:22:22 +00004665 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt> [<Rn> <Rm> {lsl #imm2>}]" },
4666 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn> #<imm5>]" },
4667 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt> [<Rn> #<imm12>]" },
4668 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> [<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004669 };
4670
4671 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
4672 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
4673 {
4674 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
4675 return &g_thumb_opcodes[i];
4676 }
4677 return NULL;
4678}
Greg Clayton64c84432011-01-21 22:02:52 +00004679
Greg Clayton31e2a382011-01-30 20:03:56 +00004680bool
Greg Clayton395fc332011-02-15 21:59:32 +00004681EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00004682{
4683 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00004684 const char *arch_cstr = arch.AsCString ();
4685 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00004686 {
Greg Clayton395fc332011-02-15 21:59:32 +00004687 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
4688 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
4689 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
4690 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
4691 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
4692 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
4693 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
4694 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
4695 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
4696 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00004697 }
4698 return m_arm_isa != 0;
4699}
4700
4701
Greg Clayton64c84432011-01-21 22:02:52 +00004702bool
4703EmulateInstructionARM::ReadInstruction ()
4704{
4705 bool success = false;
4706 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
4707 if (success)
4708 {
4709 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
4710 if (success)
4711 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004712 Context read_inst_context;
4713 read_inst_context.type = eContextReadOpcode;
4714 read_inst_context.SetNoArgs ();
4715
Greg Clayton64c84432011-01-21 22:02:52 +00004716 if (m_inst_cpsr & MASK_CPSR_T)
4717 {
4718 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004719 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004720
4721 if (success)
4722 {
4723 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
4724 {
4725 m_inst.opcode_type = eOpcode16;
4726 m_inst.opcode.inst16 = thumb_opcode;
4727 }
4728 else
4729 {
4730 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004731 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004732 }
4733 }
4734 }
4735 else
4736 {
4737 m_inst_mode = eModeARM;
4738 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00004739 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00004740 }
4741 }
4742 }
4743 if (!success)
4744 {
4745 m_inst_mode = eModeInvalid;
4746 m_inst_pc = LLDB_INVALID_ADDRESS;
4747 }
4748 return success;
4749}
4750
Johnny Chenee9b1f72011-02-09 01:00:31 +00004751uint32_t
4752EmulateInstructionARM::ArchVersion ()
4753{
4754 return m_arm_isa;
4755}
4756
Greg Clayton64c84432011-01-21 22:02:52 +00004757bool
4758EmulateInstructionARM::ConditionPassed ()
4759{
4760 if (m_inst_cpsr == 0)
4761 return false;
4762
4763 const uint32_t cond = CurrentCond ();
4764
4765 if (cond == UINT32_MAX)
4766 return false;
4767
4768 bool result = false;
4769 switch (UnsignedBits(cond, 3, 1))
4770 {
4771 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
4772 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
4773 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
4774 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
4775 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
4776 case 5:
4777 {
4778 bool n = (m_inst_cpsr & MASK_CPSR_N);
4779 bool v = (m_inst_cpsr & MASK_CPSR_V);
4780 result = n == v;
4781 }
4782 break;
4783 case 6:
4784 {
4785 bool n = (m_inst_cpsr & MASK_CPSR_N);
4786 bool v = (m_inst_cpsr & MASK_CPSR_V);
4787 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
4788 }
4789 break;
4790 case 7:
4791 result = true;
4792 break;
4793 }
4794
4795 if (cond & 1)
4796 result = !result;
4797 return result;
4798}
4799
Johnny Chen9ee056b2011-02-08 00:06:35 +00004800uint32_t
4801EmulateInstructionARM::CurrentCond ()
4802{
4803 switch (m_inst_mode)
4804 {
4805 default:
4806 case eModeInvalid:
4807 break;
4808
4809 case eModeARM:
4810 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
4811
4812 case eModeThumb:
4813 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
4814 // 'cond' field of the encoding.
4815 if (m_inst.opcode_type == eOpcode16 &&
4816 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
4817 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
4818 {
4819 return Bits32(m_inst.opcode.inst16, 11, 7);
4820 }
4821 else if (m_inst.opcode_type == eOpcode32 &&
4822 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
4823 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
4824 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
4825 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
4826 {
4827 return Bits32(m_inst.opcode.inst32, 25, 22);
4828 }
4829
4830 return m_it_session.GetCond();
4831 }
4832 return UINT32_MAX; // Return invalid value
4833}
4834
Johnny Chen9ee056b2011-02-08 00:06:35 +00004835bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00004836EmulateInstructionARM::InITBlock()
4837{
4838 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
4839}
4840
4841bool
4842EmulateInstructionARM::LastInITBlock()
4843{
4844 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
4845}
4846
4847bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00004848EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
4849{
4850 addr_t target;
4851
Johnny Chenee9b1f72011-02-09 01:00:31 +00004852 // Check the current instruction set.
4853 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004854 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004855 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00004856 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004857
Johnny Chen9ee056b2011-02-08 00:06:35 +00004858 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004859 return false;
4860
4861 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004862}
4863
4864// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
4865bool
Johnny Chen668b4512011-02-15 21:08:58 +00004866EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00004867{
4868 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00004869 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
4870 // we want to record it and issue a WriteRegister callback so the clients
4871 // can track the mode changes accordingly.
4872 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004873
4874 if (BitIsSet(addr, 0))
4875 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004876 if (CurrentInstrSet() != eModeThumb)
4877 {
4878 SelectInstrSet(eModeThumb);
4879 cpsr_changed = true;
4880 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004881 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00004882 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004883 }
4884 else if (BitIsClear(addr, 1))
4885 {
Johnny Chen0f309db2011-02-09 19:11:32 +00004886 if (CurrentInstrSet() != eModeARM)
4887 {
4888 SelectInstrSet(eModeARM);
4889 cpsr_changed = true;
4890 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004891 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00004892 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00004893 }
4894 else
4895 return false; // address<1:0> == '10' => UNPREDICTABLE
4896
Johnny Chen0f309db2011-02-09 19:11:32 +00004897 if (cpsr_changed)
4898 {
Johnny Chen558133b2011-02-09 23:59:17 +00004899 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00004900 return false;
4901 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00004902 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00004903 return false;
4904
4905 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00004906}
Greg Clayton64c84432011-01-21 22:02:52 +00004907
Johnny Chenee9b1f72011-02-09 01:00:31 +00004908// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
4909bool
Johnny Chen668b4512011-02-15 21:08:58 +00004910EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00004911{
4912 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00004913 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00004914 else
4915 return BranchWritePC((const Context)context, addr);
4916}
4917
Johnny Chen26863dc2011-02-09 23:43:29 +00004918// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
4919bool
Johnny Chen668b4512011-02-15 21:08:58 +00004920EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00004921{
4922 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00004923 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00004924 else
4925 return BranchWritePC((const Context)context, addr);
4926}
4927
Johnny Chenee9b1f72011-02-09 01:00:31 +00004928EmulateInstructionARM::Mode
4929EmulateInstructionARM::CurrentInstrSet ()
4930{
4931 return m_inst_mode;
4932}
4933
4934// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00004935// ReadInstruction() is performed. This function has a side effect of updating
4936// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00004937bool
4938EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
4939{
Johnny Chen558133b2011-02-09 23:59:17 +00004940 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004941 switch (arm_or_thumb)
4942 {
4943 default:
4944 return false;
4945 eModeARM:
4946 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004947 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004948 break;
4949 eModeThumb:
4950 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00004951 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00004952 break;
4953 }
4954 return true;
4955}
4956
Johnny Chenef21b592011-02-10 01:52:38 +00004957// This function returns TRUE if the processor currently provides support for
4958// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
4959// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
4960bool
4961EmulateInstructionARM::UnalignedSupport()
4962{
4963 return (ArchVersion() >= ARMv7);
4964}
4965
Johnny Chenbf6ad172011-02-11 01:29:53 +00004966// The main addition and subtraction instructions can produce status information
4967// about both unsigned carry and signed overflow conditions. This status
4968// information can be used to synthesize multi-word additions and subtractions.
4969EmulateInstructionARM::AddWithCarryResult
4970EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
4971{
4972 uint32_t result;
4973 uint8_t carry_out;
4974 uint8_t overflow;
4975
4976 uint64_t unsigned_sum = x + y + carry_in;
4977 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
4978
4979 result = UnsignedBits(unsigned_sum, 31, 0);
4980 carry_out = (result == unsigned_sum ? 0 : 1);
4981 overflow = ((int32_t)result == signed_sum ? 0 : 1);
4982
4983 AddWithCarryResult res = { result, carry_out, overflow };
4984 return res;
4985}
4986
Johnny Chenca67d1c2011-02-17 01:35:27 +00004987// Write the result to the ARM core register Rd, and optionally update the
4988// condition flags based on the result.
4989//
4990// This helper method tries to encapsulate the following pseudocode from the
4991// ARM Architecture Reference Manual:
4992//
4993// if d == 15 then // Can only occur for encoding A1
4994// ALUWritePC(result); // setflags is always FALSE here
4995// else
4996// R[d] = result;
4997// if setflags then
4998// APSR.N = result<31>;
4999// APSR.Z = IsZeroBit(result);
5000// APSR.C = carry;
5001// // APSR.V unchanged
5002//
5003// In the above case, the API client does not pass in the overflow arg, which
5004// defaults to ~0u.
5005bool
Johnny Chen10530c22011-02-17 22:37:12 +00005006EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
5007 const uint32_t result,
5008 const uint32_t Rd,
5009 bool setflags,
5010 const uint32_t carry,
5011 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00005012{
5013 if (Rd == 15)
5014 {
5015 if (!ALUWritePC (context, result))
5016 return false;
5017 }
5018 else
5019 {
5020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
5021 return false;
5022 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00005023 return WriteFlags (context, result, carry, overflow);
5024 }
5025 return true;
5026}
5027
5028// This helper method tries to encapsulate the following pseudocode from the
5029// ARM Architecture Reference Manual:
5030//
5031// APSR.N = result<31>;
5032// APSR.Z = IsZeroBit(result);
5033// APSR.C = carry;
5034// APSR.V = overflow
5035//
5036// Default arguments can be specified for carry and overflow parameters, which means
5037// not to update the respective flags.
5038bool
5039EmulateInstructionARM::WriteFlags (Context &context,
5040 const uint32_t result,
5041 const uint32_t carry,
5042 const uint32_t overflow)
5043{
5044 m_new_inst_cpsr = m_inst_cpsr;
5045 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
5046 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
5047 if (carry != ~0u)
5048 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
5049 if (overflow != ~0u)
5050 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
5051 if (m_new_inst_cpsr != m_inst_cpsr)
5052 {
5053 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
5054 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00005055 }
5056 return true;
5057}
5058
Greg Clayton64c84432011-01-21 22:02:52 +00005059bool
5060EmulateInstructionARM::EvaluateInstruction ()
5061{
Johnny Chenc315f862011-02-05 00:46:10 +00005062 // Advance the ITSTATE bits to their values for the next instruction.
5063 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
5064 m_it_session.ITAdvance();
5065
Greg Clayton64c84432011-01-21 22:02:52 +00005066 return false;
5067}