blob: 06087ea296a0d2f6e8f1f52d8c7c1e6a89b446b1 [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 Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
27#define APSR_C Bit32(m_inst_cpsr, CPSR_C)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V)
29
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
113#define PC_REG 15
114#define PC_REGLIST_BIT 0x8000
115
Johnny Chen251af6a2011-01-21 22:47:25 +0000116#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000117#define ARMv4T (1u << 1)
118#define ARMv5T (1u << 2)
119#define ARMv5TE (1u << 3)
120#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000121#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000122#define ARMv6K (1u << 6)
123#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000124#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000125#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000126#define ARMvAll (0xffffffffu)
127
Johnny Chen9b8d7832011-02-02 01:13:56 +0000128#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
129#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
130#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000131
Johnny Chen0e00af22011-02-10 19:40:42 +0000132//----------------------------------------------------------------------
133//
134// EmulateInstructionARM implementation
135//
136//----------------------------------------------------------------------
137
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000138void
139EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143void
144EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000145{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000146}
147
Caroline Ticefa172202011-02-11 22:49:54 +0000148// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
149bool
150EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
151{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000152 EmulateInstruction::Context context;
153 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
154 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000155
156 uint32_t random_data = rand ();
157 const uint32_t addr_byte_size = GetAddressByteSize();
158
Caroline Ticecc96eb52011-02-17 19:20:40 +0000159 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000160 return false;
161
162 return true;
163}
164
Caroline Tice713c2662011-02-11 17:59:55 +0000165// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
166bool
167EmulateInstructionARM::WriteBits32Unknown (int n)
168{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000169 EmulateInstruction::Context context;
170 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
171 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000172
Johnny Chen62ff6f52011-02-11 18:11:22 +0000173 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000174 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
175
176 if (!success)
177 return false;
178
179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
180 return false;
181
182 return true;
183}
184
Johnny Chen08c25e82011-01-31 18:02:28 +0000185// Push Multiple Registers stores multiple registers to the stack, storing to
186// consecutive memory locations ending just below the address in SP, and updates
187// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000188bool
Johnny Chen9f687722011-02-18 00:02:28 +0000189EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000190{
191#if 0
192 // ARM pseudo code...
193 if (ConditionPassed())
194 {
195 EncodingSpecificOperations();
196 NullCheckIfThumbEE(13);
197 address = SP - 4*BitCount(registers);
198
199 for (i = 0 to 14)
200 {
201 if (registers<i> == ’1’)
202 {
203 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
204 MemA[address,4] = bits(32) UNKNOWN;
205 else
206 MemA[address,4] = R[i];
207 address = address + 4;
208 }
209 }
210
211 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
212 MemA[address,4] = PCStoreValue();
213
214 SP = SP - 4*BitCount(registers);
215 }
216#endif
217
218 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000219 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000220 if (!success)
221 return false;
222
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000224 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 const uint32_t addr_byte_size = GetAddressByteSize();
226 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000227 if (!success)
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000230 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000235 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000236 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // if BitCount(registers) < 1 then UNPREDICTABLE;
238 if (BitCount(registers) < 1)
239 return false;
240 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000241 case eEncodingT2:
242 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BitCount(registers) < 2 then UNPREDICTABLE;
245 if (BitCount(registers) < 2)
246 return false;
247 break;
248 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000249 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000255 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000257 // Instead of return false, let's handle the following case as well,
258 // which amounts to pushing one reg onto the full descending stacks.
259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000260 break;
261 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000262 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000268 default:
269 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 }
Johnny Chence1ca772011-01-25 01:13:00 +0000271 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000272 addr_t addr = sp - sp_offset;
273 uint32_t i;
274
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000275 EmulateInstruction::Context context;
276 context.type = EmulateInstruction::eContextPushRegisterOnStack;
277 Register dwarf_reg;
278 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000279 for (i=0; i<15; ++i)
280 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000281 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000282 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000283 dwarf_reg.num = dwarf_r0 + i;
284 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
285 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000286 if (!success)
287 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000288 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000289 return false;
290 addr += addr_byte_size;
291 }
292 }
293
Johnny Chen7c1bf922011-02-08 23:49:37 +0000294 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000296 dwarf_reg.num = dwarf_pc;
297 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000299 if (!success)
300 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000301 if (!MemAWrite (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000302 return false;
303 }
304
305 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000306 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000307
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000308 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000309 return false;
310 }
311 return true;
312}
313
Johnny Chenef85e912011-01-31 23:07:40 +0000314// Pop Multiple Registers loads multiple registers from the stack, loading from
315// consecutive memory locations staring at the address in SP, and updates
316// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000317bool
Johnny Chen9f687722011-02-18 00:02:28 +0000318EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000319{
320#if 0
321 // ARM pseudo code...
322 if (ConditionPassed())
323 {
324 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
325 address = SP;
326 for i = 0 to 14
327 if registers<i> == ‘1’ then
328 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
329 if registers<15> == ‘1’ then
330 if UnalignedAllowed then
331 LoadWritePC(MemU[address,4]);
332 else
333 LoadWritePC(MemA[address,4]);
334 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
335 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
336 }
337#endif
338
339 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000340 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000341 if (!success)
342 return false;
343
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000345 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t addr_byte_size = GetAddressByteSize();
347 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000348 if (!success)
349 return false;
350 uint32_t registers = 0;
351 uint32_t Rt; // the destination register
352 switch (encoding) {
353 case eEncodingT1:
354 registers = Bits32(opcode, 7, 0);
355 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000356 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000357 registers |= (1u << 15);
358 // if BitCount(registers) < 1 then UNPREDICTABLE;
359 if (BitCount(registers) < 1)
360 return false;
361 break;
362 case eEncodingT2:
363 // Ignore bit 13.
364 registers = Bits32(opcode, 15, 0) & ~0x2000;
365 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000366 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000367 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000368 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
369 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
370 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000371 break;
372 case eEncodingT3:
373 Rt = Bits32(opcode, 15, 12);
374 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000375 if (Rt == 13)
376 return false;
377 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000378 return false;
379 registers = (1u << Rt);
380 break;
381 case eEncodingA1:
382 registers = Bits32(opcode, 15, 0);
383 // Instead of return false, let's handle the following case as well,
384 // which amounts to popping one reg from the full descending stacks.
385 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
386
387 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000388 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000389 return false;
390 break;
391 case eEncodingA2:
392 Rt = Bits32(opcode, 15, 12);
393 // if t == 13 then UNPREDICTABLE;
394 if (Rt == dwarf_sp)
395 return false;
396 registers = (1u << Rt);
397 break;
398 default:
399 return false;
400 }
401 addr_t sp_offset = addr_byte_size * BitCount (registers);
402 addr_t addr = sp;
403 uint32_t i, data;
404
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000405 EmulateInstruction::Context context;
406 context.type = EmulateInstruction::eContextPopRegisterOffStack;
407 Register dwarf_reg;
408 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000409 for (i=0; i<15; ++i)
410 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000411 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000412 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000413 dwarf_reg.num = dwarf_r0 + i;
414 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000415 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000416 if (!success)
417 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000418 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000419 return false;
420 addr += addr_byte_size;
421 }
422 }
423
Johnny Chen7c1bf922011-02-08 23:49:37 +0000424 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000425 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000426 dwarf_reg.num = dwarf_pc;
427 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000428 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000429 if (!success)
430 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000431 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000432 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000433 return false;
434 addr += addr_byte_size;
435 }
436
437 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000438 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000439
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000440 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000441 return false;
442 }
443 return true;
444}
445
Johnny Chen5b442b72011-01-27 19:34:30 +0000446// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000447// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448bool
Johnny Chen9f687722011-02-18 00:02:28 +0000449EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000450{
451#if 0
452 // ARM pseudo code...
453 if (ConditionPassed())
454 {
455 EncodingSpecificOperations();
456 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
457 if d == 15 then
458 ALUWritePC(result); // setflags is always FALSE here
459 else
460 R[d] = result;
461 if setflags then
462 APSR.N = result<31>;
463 APSR.Z = IsZeroBit(result);
464 APSR.C = carry;
465 APSR.V = overflow;
466 }
467#endif
468
469 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000470 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000471 if (!success)
472 return false;
473
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 if (!success)
478 return false;
479 uint32_t Rd; // the destination register
480 uint32_t imm32;
481 switch (encoding) {
482 case eEncodingT1:
483 Rd = 7;
484 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
485 break;
486 case eEncodingA1:
487 Rd = Bits32(opcode, 15, 12);
488 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
489 break;
490 default:
491 return false;
492 }
493 addr_t sp_offset = imm32;
494 addr_t addr = sp + sp_offset; // a pointer to the stack area
495
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000496 EmulateInstruction::Context context;
497 context.type = EmulateInstruction::eContextRegisterPlusOffset;
498 Register sp_reg;
499 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
500 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503 return false;
504 }
505 return true;
506}
507
Johnny Chen2ccad832011-01-28 19:57:25 +0000508// Set r7 or ip to the current stack pointer.
509// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510bool
Johnny Chen9f687722011-02-18 00:02:28 +0000511EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000512{
513#if 0
514 // ARM pseudo code...
515 if (ConditionPassed())
516 {
517 EncodingSpecificOperations();
518 result = R[m];
519 if d == 15 then
520 ALUWritePC(result); // setflags is always FALSE here
521 else
522 R[d] = result;
523 if setflags then
524 APSR.N = result<31>;
525 APSR.Z = IsZeroBit(result);
526 // APSR.C unchanged
527 // APSR.V unchanged
528 }
529#endif
530
531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000532 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000533 //if (!success)
534 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000535
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000537 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 if (!success)
540 return false;
541 uint32_t Rd; // the destination register
542 switch (encoding) {
543 case eEncodingT1:
544 Rd = 7;
545 break;
546 case eEncodingA1:
547 Rd = 12;
548 break;
549 default:
550 return false;
551 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000552
553 EmulateInstruction::Context context;
554 context.type = EmulateInstruction::eContextRegisterPlusOffset;
555 Register sp_reg;
556 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
557 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000558
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000559 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000560 return false;
561 }
562 return true;
563}
564
Johnny Chen1c13b622011-01-29 00:11:15 +0000565// Move from high register (r8-r15) to low register (r0-r7).
566// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567bool
Johnny Chen9f687722011-02-18 00:02:28 +0000568EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000569{
Johnny Chen9f687722011-02-18 00:02:28 +0000570 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000571}
572
573// Move from register to register.
574// MOV (register)
575bool
Johnny Chen9f687722011-02-18 00:02:28 +0000576EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000577{
Johnny Chen1c13b622011-01-29 00:11:15 +0000578#if 0
579 // ARM pseudo code...
580 if (ConditionPassed())
581 {
582 EncodingSpecificOperations();
583 result = R[m];
584 if d == 15 then
585 ALUWritePC(result); // setflags is always FALSE here
586 else
587 R[d] = result;
588 if setflags then
589 APSR.N = result<31>;
590 APSR.Z = IsZeroBit(result);
591 // APSR.C unchanged
592 // APSR.V unchanged
593 }
594#endif
595
596 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000597 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000598 if (!success)
599 return false;
600
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000601 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000602 {
603 uint32_t Rm; // the source register
604 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000605 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 switch (encoding) {
607 case eEncodingT1:
608 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000609 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000610 setflags = false;
611 break;
612 case eEncodingT2:
613 Rm = Bits32(opcode, 5, 3);
614 Rd = Bits32(opcode, 2, 1);
615 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000616 break;
617 default:
618 return false;
619 }
Johnny Chenca67d1c2011-02-17 01:35:27 +0000620 uint32_t result = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000621 if (!success)
622 return false;
623
624 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000625 EmulateInstruction::Context context;
626 context.type = EmulateInstruction::eContextRegisterPlusOffset;
627 Register dwarf_reg;
628 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
629 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000630
Johnny Chen10530c22011-02-17 22:37:12 +0000631 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000632 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000633 }
634 return true;
635}
636
Johnny Chen357c30f2011-02-14 22:04:25 +0000637// Move (immediate) writes an immediate value to the destination register. It
638// can optionally update the condition flags based on the value.
639// MOV (immediate)
640bool
Johnny Chen9f687722011-02-18 00:02:28 +0000641EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000642{
643#if 0
644 // ARM pseudo code...
645 if (ConditionPassed())
646 {
647 EncodingSpecificOperations();
648 result = imm32;
649 if d == 15 then // Can only occur for ARM encoding
650 ALUWritePC(result); // setflags is always FALSE here
651 else
652 R[d] = result;
653 if setflags then
654 APSR.N = result<31>;
655 APSR.Z = IsZeroBit(result);
656 APSR.C = carry;
657 // APSR.V unchanged
658 }
659#endif
660 bool success = false;
661 const uint32_t opcode = OpcodeAsUnsigned (&success);
662 if (!success)
663 return false;
664
665 if (ConditionPassed())
666 {
667 uint32_t Rd; // the destination register
668 uint32_t imm12; // some intermediate result
669 uint32_t imm32; // the immediate value to be written to Rd
670 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
671 bool setflags;
672 switch (encoding) {
673 case eEncodingT1:
674 Rd = Bits32(opcode, 11, 8);
675 setflags = !InITBlock();
676 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000677 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000678 break;
679 case eEncodingT2:
680 Rd = Bits32(opcode, 15, 12);
681 setflags = BitIsSet(opcode, 20);
682 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000683 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000684 if (BadReg(Rd))
685 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000686 break;
687 default:
688 return false;
689 }
690 uint32_t result = imm32;
691
692 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000693 EmulateInstruction::Context context;
694 context.type = EmulateInstruction::eContextImmediate;
695 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000696
Johnny Chen10530c22011-02-17 22:37:12 +0000697 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000698 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000699 }
700 return true;
701}
702
Johnny Chen28070c32011-02-12 01:27:26 +0000703// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
704// the destination register. It can optionally update the condition flags based
705// on the value.
706// MVN (immediate)
707bool
Johnny Chen9f687722011-02-18 00:02:28 +0000708EmulateInstructionARM::EmulateMVNRdImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000709{
710#if 0
711 // ARM pseudo code...
712 if (ConditionPassed())
713 {
714 EncodingSpecificOperations();
715 result = NOT(imm32);
716 if d == 15 then // Can only occur for ARM encoding
717 ALUWritePC(result); // setflags is always FALSE here
718 else
719 R[d] = result;
720 if setflags then
721 APSR.N = result<31>;
722 APSR.Z = IsZeroBit(result);
723 APSR.C = carry;
724 // APSR.V unchanged
725 }
726#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000727 bool success = false;
728 const uint32_t opcode = OpcodeAsUnsigned (&success);
729 if (!success)
730 return false;
731
732 if (ConditionPassed())
733 {
734 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000735 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
736 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
737 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000738 bool setflags;
739 switch (encoding) {
740 case eEncodingT1:
741 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000742 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000743 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000744 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000745 break;
746 case eEncodingA1:
747 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000748 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000749 imm12 = Bits32(opcode, 11, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000750 imm32 = ARMExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000751 break;
752 default:
753 return false;
754 }
755 uint32_t result = ~imm32;
756
757 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000758 EmulateInstruction::Context context;
759 context.type = EmulateInstruction::eContextImmediate;
760 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000761
Johnny Chen10530c22011-02-17 22:37:12 +0000762 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000763 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000764 }
765 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000766}
767
Johnny Chen788e0552011-01-27 22:52:23 +0000768// PC relative immediate load into register, possibly followed by ADD (SP plus register).
769// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000770bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000771EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000772{
773#if 0
774 // ARM pseudo code...
775 if (ConditionPassed())
776 {
777 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
778 base = Align(PC,4);
779 address = if add then (base + imm32) else (base - imm32);
780 data = MemU[address,4];
781 if t == 15 then
782 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
783 elsif UnalignedSupport() || address<1:0> = ‘00’ then
784 R[t] = data;
785 else // Can only apply before ARMv7
786 if CurrentInstrSet() == InstrSet_ARM then
787 R[t] = ROR(data, 8*UInt(address<1:0>));
788 else
789 R[t] = bits(32) UNKNOWN;
790 }
791#endif
792
793 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000794 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000795 if (!success)
796 return false;
797
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000798 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000799 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000800 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000801 if (!success)
802 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000803
804 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000805 EmulateInstruction::Context context;
806 context.type = EmulateInstruction::eContextRegisterPlusOffset;
807 Register pc_reg;
808 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
809 context.SetRegisterPlusOffset (pc_reg, 0);
810
Johnny Chenc9de9102011-02-11 19:12:30 +0000811 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000812 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000813 bool add; // +imm32 or -imm32?
814 addr_t base; // the base address
815 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000816 uint32_t data; // the literal data value from the PC relative load
817 switch (encoding) {
818 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000819 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000820 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000821 add = true;
822 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000823 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000824 break;
825 case eEncodingT2:
826 Rt = Bits32(opcode, 15, 12);
827 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
828 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000829 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000830 return false;
831 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000832 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000833 break;
834 default:
835 return false;
836 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000837
838 if (add)
839 address = base + imm32;
840 else
841 address = base - imm32;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000842 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000843 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000844 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000845
846 if (Rt == 15)
847 {
848 if (Bits32(address, 1, 0) == 0)
849 {
850 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000851 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000852 return false;
853 }
854 else
855 return false;
856 }
857 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
858 {
859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
860 return false;
861 }
862 else // We don't handle ARM for now.
863 return false;
864
865 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000866 return false;
867 }
868 return true;
869}
870
Johnny Chen5b442b72011-01-27 19:34:30 +0000871// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000872// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000873bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000874EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000875{
876#if 0
877 // ARM pseudo code...
878 if (ConditionPassed())
879 {
880 EncodingSpecificOperations();
881 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
882 if d == 15 then // Can only occur for ARM encoding
883 ALUWritePC(result); // setflags is always FALSE here
884 else
885 R[d] = result;
886 if setflags then
887 APSR.N = result<31>;
888 APSR.Z = IsZeroBit(result);
889 APSR.C = carry;
890 APSR.V = overflow;
891 }
892#endif
893
894 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000895 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000896 if (!success)
897 return false;
898
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000899 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000900 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000901 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000902 if (!success)
903 return false;
904 uint32_t imm32; // the immediate operand
905 switch (encoding) {
906 case eEncodingT2:
907 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
908 break;
909 default:
910 return false;
911 }
912 addr_t sp_offset = imm32;
913 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
914
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000915 EmulateInstruction::Context context;
916 context.type = EmulateInstruction::eContextAdjustStackPointer;
917 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000918
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000919 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000920 return false;
921 }
922 return true;
923}
924
925// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000926// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000928EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000929{
930#if 0
931 // ARM pseudo code...
932 if (ConditionPassed())
933 {
934 EncodingSpecificOperations();
935 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
936 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
937 if d == 15 then
938 ALUWritePC(result); // setflags is always FALSE here
939 else
940 R[d] = result;
941 if setflags then
942 APSR.N = result<31>;
943 APSR.Z = IsZeroBit(result);
944 APSR.C = carry;
945 APSR.V = overflow;
946 }
947#endif
948
949 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000950 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000951 if (!success)
952 return false;
953
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000954 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000955 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000957 if (!success)
958 return false;
959 uint32_t Rm; // the second operand
960 switch (encoding) {
961 case eEncodingT2:
962 Rm = Bits32(opcode, 6, 3);
963 break;
964 default:
965 return false;
966 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000967 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000968 if (!success)
969 return false;
970
971 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
972
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000973 EmulateInstruction::Context context;
974 context.type = EmulateInstruction::eContextAdjustStackPointer;
975 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000976
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000977 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000978 return false;
979 }
980 return true;
981}
982
Johnny Chen9b8d7832011-02-02 01:13:56 +0000983// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
984// at a PC-relative address, and changes instruction set from ARM to Thumb, or
985// from Thumb to ARM.
986// BLX (immediate)
987bool
988EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
989{
990#if 0
991 // ARM pseudo code...
992 if (ConditionPassed())
993 {
994 EncodingSpecificOperations();
995 if CurrentInstrSet() == InstrSet_ARM then
996 LR = PC - 4;
997 else
998 LR = PC<31:1> : '1';
999 if targetInstrSet == InstrSet_ARM then
1000 targetAddress = Align(PC,4) + imm32;
1001 else
1002 targetAddress = PC + imm32;
1003 SelectInstrSet(targetInstrSet);
1004 BranchWritePC(targetAddress);
1005 }
1006#endif
1007
1008 bool success = false;
1009 const uint32_t opcode = OpcodeAsUnsigned (&success);
1010 if (!success)
1011 return false;
1012
1013 if (ConditionPassed())
1014 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001015 EmulateInstruction::Context context;
1016 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001017 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001018 if (!success)
1019 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001020 addr_t lr; // next instruction address
1021 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001022 int32_t imm32; // PC-relative offset
1023 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001024 case eEncodingT1:
1025 {
1026 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001027 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001028 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001029 uint32_t J1 = Bit32(opcode, 13);
1030 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001031 uint32_t imm11 = Bits32(opcode, 10, 0);
1032 uint32_t I1 = !(J1 ^ S);
1033 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001034 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001035 imm32 = llvm::SignExtend32<25>(imm25);
1036 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001037 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001038 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001039 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001040 break;
1041 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001042 case eEncodingT2:
1043 {
1044 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001045 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001046 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001047 uint32_t J1 = Bit32(opcode, 13);
1048 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001049 uint32_t imm10L = Bits32(opcode, 10, 1);
1050 uint32_t I1 = !(J1 ^ S);
1051 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001052 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001053 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001054 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001055 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001056 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001057 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001058 break;
1059 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001060 case eEncodingA1:
1061 lr = pc + 4; // return address
1062 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001063 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001064 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001065 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001066 case eEncodingA2:
1067 lr = pc + 4; // return address
1068 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1069 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001070 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001071 break;
1072 default:
1073 return false;
1074 }
1075 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1076 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001077 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001078 return false;
1079 }
1080 return true;
1081}
1082
1083// Branch with Link and Exchange (register) calls a subroutine at an address and
1084// instruction set specified by a register.
1085// BLX (register)
1086bool
1087EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1088{
1089#if 0
1090 // ARM pseudo code...
1091 if (ConditionPassed())
1092 {
1093 EncodingSpecificOperations();
1094 target = R[m];
1095 if CurrentInstrSet() == InstrSet_ARM then
1096 next_instr_addr = PC - 4;
1097 LR = next_instr_addr;
1098 else
1099 next_instr_addr = PC - 2;
1100 LR = next_instr_addr<31:1> : ‘1’;
1101 BXWritePC(target);
1102 }
1103#endif
1104
1105 bool success = false;
1106 const uint32_t opcode = OpcodeAsUnsigned (&success);
1107 if (!success)
1108 return false;
1109
1110 if (ConditionPassed())
1111 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001112 EmulateInstruction::Context context;
1113 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1115 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001116 if (!success)
1117 return false;
1118 uint32_t Rm; // the register with the target address
1119 switch (encoding) {
1120 case eEncodingT1:
1121 lr = (pc + 2) | 1u; // return address
1122 Rm = Bits32(opcode, 6, 3);
1123 // if m == 15 then UNPREDICTABLE;
1124 if (Rm == 15)
1125 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001126 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001127 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001128 break;
1129 case eEncodingA1:
1130 lr = pc + 4; // return address
1131 Rm = Bits32(opcode, 3, 0);
1132 // if m == 15 then UNPREDICTABLE;
1133 if (Rm == 15)
1134 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001135 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001136 default:
1137 return false;
1138 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001139 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1140 if (!success)
1141 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001142 Register dwarf_reg;
1143 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1144 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001145 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1146 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001147 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001148 return false;
1149 }
1150 return true;
1151}
1152
Johnny Chenab3b3512011-02-12 00:10:51 +00001153// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1154// BX
1155bool
1156EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1157{
1158#if 0
1159 // ARM pseudo code...
1160 if (ConditionPassed())
1161 {
1162 EncodingSpecificOperations();
1163 BXWritePC(R[m]);
1164 }
1165#endif
1166
1167 bool success = false;
1168 const uint32_t opcode = OpcodeAsUnsigned (&success);
1169 if (!success)
1170 return false;
1171
1172 if (ConditionPassed())
1173 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001174 EmulateInstruction::Context context;
1175 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001176 uint32_t Rm; // the register with the target address
1177 switch (encoding) {
1178 case eEncodingT1:
1179 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001180 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001181 return false;
1182 break;
1183 case eEncodingA1:
1184 Rm = Bits32(opcode, 3, 0);
1185 break;
1186 default:
1187 return false;
1188 }
1189 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1190 if (!success)
1191 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001192
1193 Register dwarf_reg;
1194 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001195 context.SetRegister (dwarf_reg);
1196 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001197 return false;
1198 }
1199 return true;
1200}
1201
Johnny Chen0d0148e2011-01-28 02:26:08 +00001202// Set r7 to point to some ip offset.
1203// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001204bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001205EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001206{
1207#if 0
1208 // ARM pseudo code...
1209 if (ConditionPassed())
1210 {
1211 EncodingSpecificOperations();
1212 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1213 if d == 15 then // Can only occur for ARM encoding
1214 ALUWritePC(result); // setflags is always FALSE here
1215 else
1216 R[d] = result;
1217 if setflags then
1218 APSR.N = result<31>;
1219 APSR.Z = IsZeroBit(result);
1220 APSR.C = carry;
1221 APSR.V = overflow;
1222 }
1223#endif
1224
1225 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001226 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001227 if (!success)
1228 return false;
1229
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001230 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001231 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001232 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001233 if (!success)
1234 return false;
1235 uint32_t imm32;
1236 switch (encoding) {
1237 case eEncodingA1:
1238 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1239 break;
1240 default:
1241 return false;
1242 }
1243 addr_t ip_offset = imm32;
1244 addr_t addr = ip - ip_offset; // the adjusted ip value
1245
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001246 EmulateInstruction::Context context;
1247 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1248 Register dwarf_reg;
1249 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1250 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001251
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001253 return false;
1254 }
1255 return true;
1256}
1257
1258// Set ip to point to some stack offset.
1259// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001260bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001261EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001262{
1263#if 0
1264 // ARM pseudo code...
1265 if (ConditionPassed())
1266 {
1267 EncodingSpecificOperations();
1268 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1269 if d == 15 then // Can only occur for ARM encoding
1270 ALUWritePC(result); // setflags is always FALSE here
1271 else
1272 R[d] = result;
1273 if setflags then
1274 APSR.N = result<31>;
1275 APSR.Z = IsZeroBit(result);
1276 APSR.C = carry;
1277 APSR.V = overflow;
1278 }
1279#endif
1280
1281 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001282 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001283 if (!success)
1284 return false;
1285
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001286 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001287 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001288 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001289 if (!success)
1290 return false;
1291 uint32_t imm32;
1292 switch (encoding) {
1293 case eEncodingA1:
1294 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1295 break;
1296 default:
1297 return false;
1298 }
1299 addr_t sp_offset = imm32;
1300 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1301
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001302 EmulateInstruction::Context context;
1303 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1304 Register dwarf_reg;
1305 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1306 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001307
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001308 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001309 return false;
1310 }
1311 return true;
1312}
1313
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001314// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001315bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001316EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001317{
1318#if 0
1319 // ARM pseudo code...
1320 if (ConditionPassed())
1321 {
1322 EncodingSpecificOperations();
1323 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1324 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001325 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001326 else
1327 R[d] = result;
1328 if setflags then
1329 APSR.N = result<31>;
1330 APSR.Z = IsZeroBit(result);
1331 APSR.C = carry;
1332 APSR.V = overflow;
1333 }
1334#endif
1335
1336 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001337 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001338 if (!success)
1339 return false;
1340
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001341 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001342 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001343 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001344 if (!success)
1345 return false;
1346 uint32_t imm32;
1347 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001348 case eEncodingT1:
1349 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001350 case eEncodingT2:
1351 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1352 break;
1353 case eEncodingT3:
1354 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1355 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001356 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001357 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001358 break;
1359 default:
1360 return false;
1361 }
1362 addr_t sp_offset = imm32;
1363 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1364
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001365 EmulateInstruction::Context context;
1366 context.type = EmulateInstruction::eContextAdjustStackPointer;
1367 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001368
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001369 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001370 return false;
1371 }
1372 return true;
1373}
1374
Johnny Chen08c25e82011-01-31 18:02:28 +00001375// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001376bool
1377EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001378{
1379#if 0
1380 // ARM pseudo code...
1381 if (ConditionPassed())
1382 {
1383 EncodingSpecificOperations();
1384 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1385 address = if index then offset_addr else R[n];
1386 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1387 if wback then R[n] = offset_addr;
1388 }
1389#endif
1390
1391 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001392 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001393 if (!success)
1394 return false;
1395
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001396 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001397 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001398 const uint32_t addr_byte_size = GetAddressByteSize();
1399 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001400 if (!success)
1401 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001402 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001403 uint32_t imm12;
1404 switch (encoding) {
1405 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001406 Rt = Bits32(opcode, 15, 12);
1407 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001408 break;
1409 default:
1410 return false;
1411 }
1412 addr_t sp_offset = imm12;
1413 addr_t addr = sp - sp_offset;
1414
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001415 EmulateInstruction::Context context;
1416 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1417 Register dwarf_reg;
1418 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001419 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001420 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001421 dwarf_reg.num = dwarf_r0 + Rt;
1422 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1423 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001424 if (!success)
1425 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001426 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001427 return false;
1428 }
1429 else
1430 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001431 dwarf_reg.num = dwarf_pc;
1432 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001433 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001434 if (!success)
1435 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001436 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001437 return false;
1438 }
1439
1440 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001441 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001442
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001443 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001444 return false;
1445 }
1446 return true;
1447}
1448
Johnny Chen08c25e82011-01-31 18:02:28 +00001449// Vector Push stores multiple extension registers to the stack.
1450// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001451bool
1452EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001453{
1454#if 0
1455 // ARM pseudo code...
1456 if (ConditionPassed())
1457 {
1458 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1459 address = SP - imm32;
1460 SP = SP - imm32;
1461 if single_regs then
1462 for r = 0 to regs-1
1463 MemA[address,4] = S[d+r]; address = address+4;
1464 else
1465 for r = 0 to regs-1
1466 // Store as two word-aligned words in the correct order for current endianness.
1467 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1468 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1469 address = address+8;
1470 }
1471#endif
1472
1473 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001474 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001475 if (!success)
1476 return false;
1477
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001478 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001479 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001480 const uint32_t addr_byte_size = GetAddressByteSize();
1481 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001482 if (!success)
1483 return false;
1484 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001485 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001486 uint32_t imm32; // stack offset
1487 uint32_t regs; // number of registers
1488 switch (encoding) {
1489 case eEncodingT1:
1490 case eEncodingA1:
1491 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001492 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001493 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1494 // If UInt(imm8) is odd, see "FSTMX".
1495 regs = Bits32(opcode, 7, 0) / 2;
1496 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1497 if (regs == 0 || regs > 16 || (d + regs) > 32)
1498 return false;
1499 break;
1500 case eEncodingT2:
1501 case eEncodingA2:
1502 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001503 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001504 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1505 regs = Bits32(opcode, 7, 0);
1506 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1507 if (regs == 0 || regs > 16 || (d + regs) > 32)
1508 return false;
1509 break;
1510 default:
1511 return false;
1512 }
1513 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1514 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1515 addr_t sp_offset = imm32;
1516 addr_t addr = sp - sp_offset;
1517 uint32_t i;
1518
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001519 EmulateInstruction::Context context;
1520 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1521 Register dwarf_reg;
1522 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001523 for (i=d; i<regs; ++i)
1524 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001525 dwarf_reg.num = start_reg + i;
1526 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001527 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001528 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001529 if (!success)
1530 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001531 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001532 return false;
1533 addr += reg_byte_size;
1534 }
1535
1536 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001537 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001538
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001539 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001540 return false;
1541 }
1542 return true;
1543}
1544
Johnny Chen587a0a42011-02-01 18:35:28 +00001545// Vector Pop loads multiple extension registers from the stack.
1546// It also updates SP to point just above the loaded data.
1547bool
1548EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1549{
1550#if 0
1551 // ARM pseudo code...
1552 if (ConditionPassed())
1553 {
1554 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1555 address = SP;
1556 SP = SP + imm32;
1557 if single_regs then
1558 for r = 0 to regs-1
1559 S[d+r] = MemA[address,4]; address = address+4;
1560 else
1561 for r = 0 to regs-1
1562 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1563 // Combine the word-aligned words in the correct order for current endianness.
1564 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1565 }
1566#endif
1567
1568 bool success = false;
1569 const uint32_t opcode = OpcodeAsUnsigned (&success);
1570 if (!success)
1571 return false;
1572
1573 if (ConditionPassed())
1574 {
1575 const uint32_t addr_byte_size = GetAddressByteSize();
1576 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1577 if (!success)
1578 return false;
1579 bool single_regs;
1580 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1581 uint32_t imm32; // stack offset
1582 uint32_t regs; // number of registers
1583 switch (encoding) {
1584 case eEncodingT1:
1585 case eEncodingA1:
1586 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001587 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001588 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1589 // If UInt(imm8) is odd, see "FLDMX".
1590 regs = Bits32(opcode, 7, 0) / 2;
1591 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1592 if (regs == 0 || regs > 16 || (d + regs) > 32)
1593 return false;
1594 break;
1595 case eEncodingT2:
1596 case eEncodingA2:
1597 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001598 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001599 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1600 regs = Bits32(opcode, 7, 0);
1601 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1602 if (regs == 0 || regs > 16 || (d + regs) > 32)
1603 return false;
1604 break;
1605 default:
1606 return false;
1607 }
1608 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1609 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1610 addr_t sp_offset = imm32;
1611 addr_t addr = sp;
1612 uint32_t i;
1613 uint64_t data; // uint64_t to accomodate 64-bit registers.
1614
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001615 EmulateInstruction::Context context;
1616 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1617 Register dwarf_reg;
1618 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001619 for (i=d; i<regs; ++i)
1620 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001621 dwarf_reg.num = start_reg + i;
1622 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001623 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001624 if (!success)
1625 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001626 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001627 return false;
1628 addr += reg_byte_size;
1629 }
1630
1631 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001632 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001633
1634 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1635 return false;
1636 }
1637 return true;
1638}
1639
Johnny Chenb77be412011-02-04 00:40:18 +00001640// SVC (previously SWI)
1641bool
1642EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations();
1649 CallSupervisor();
1650 }
1651#endif
1652
1653 bool success = false;
1654 const uint32_t opcode = OpcodeAsUnsigned (&success);
1655 if (!success)
1656 return false;
1657
1658 if (ConditionPassed())
1659 {
1660 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1661 addr_t lr; // next instruction address
1662 if (!success)
1663 return false;
1664 uint32_t imm32; // the immediate constant
1665 uint32_t mode; // ARM or Thumb mode
1666 switch (encoding) {
1667 case eEncodingT1:
1668 lr = (pc + 2) | 1u; // return address
1669 imm32 = Bits32(opcode, 7, 0);
1670 mode = eModeThumb;
1671 break;
1672 case eEncodingA1:
1673 lr = pc + 4; // return address
1674 imm32 = Bits32(opcode, 23, 0);
1675 mode = eModeARM;
1676 break;
1677 default:
1678 return false;
1679 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001680
1681 EmulateInstruction::Context context;
1682 context.type = EmulateInstruction::eContextSupervisorCall;
1683 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001684 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1685 return false;
1686 }
1687 return true;
1688}
1689
Johnny Chenc315f862011-02-05 00:46:10 +00001690// If Then makes up to four following instructions (the IT block) conditional.
1691bool
1692EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1693{
1694#if 0
1695 // ARM pseudo code...
1696 EncodingSpecificOperations();
1697 ITSTATE.IT<7:0> = firstcond:mask;
1698#endif
1699
1700 bool success = false;
1701 const uint32_t opcode = OpcodeAsUnsigned (&success);
1702 if (!success)
1703 return false;
1704
1705 m_it_session.InitIT(Bits32(opcode, 7, 0));
1706 return true;
1707}
1708
Johnny Chen3b620b32011-02-07 20:11:47 +00001709// Branch causes a branch to a target address.
1710bool
1711EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1712{
1713#if 0
1714 // ARM pseudo code...
1715 if (ConditionPassed())
1716 {
1717 EncodingSpecificOperations();
1718 BranchWritePC(PC + imm32);
1719 }
1720#endif
1721
1722 bool success = false;
1723 const uint32_t opcode = OpcodeAsUnsigned (&success);
1724 if (!success)
1725 return false;
1726
Johnny Chen9ee056b2011-02-08 00:06:35 +00001727 if (ConditionPassed())
1728 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001729 EmulateInstruction::Context context;
1730 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001731 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001732 if (!success)
1733 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001734 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001735 int32_t imm32; // PC-relative offset
1736 switch (encoding) {
1737 case eEncodingT1:
1738 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1739 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1740 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001741 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001742 break;
1743 case eEncodingT2:
1744 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1745 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001746 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001747 break;
1748 case eEncodingT3:
1749 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1750 {
Johnny Chenbd599902011-02-10 21:39:01 +00001751 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001752 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001753 uint32_t J1 = Bit32(opcode, 13);
1754 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001755 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001756 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001757 imm32 = llvm::SignExtend32<21>(imm21);
1758 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001759 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001760 break;
1761 }
1762 case eEncodingT4:
1763 {
Johnny Chenbd599902011-02-10 21:39:01 +00001764 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001765 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001766 uint32_t J1 = Bit32(opcode, 13);
1767 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001768 uint32_t imm11 = Bits32(opcode, 10, 0);
1769 uint32_t I1 = !(J1 ^ S);
1770 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001771 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001772 imm32 = llvm::SignExtend32<25>(imm25);
1773 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001774 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001775 break;
1776 }
1777 case eEncodingA1:
1778 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1779 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001780 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001781 break;
1782 default:
1783 return false;
1784 }
1785 if (!BranchWritePC(context, target))
1786 return false;
1787 }
1788 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001789}
1790
Johnny Chen53ebab72011-02-08 23:21:57 +00001791// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1792// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1793// CBNZ, CBZ
1794bool
1795EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1796{
1797#if 0
1798 // ARM pseudo code...
1799 EncodingSpecificOperations();
1800 if nonzero ^ IsZero(R[n]) then
1801 BranchWritePC(PC + imm32);
1802#endif
1803
1804 bool success = false;
1805 const uint32_t opcode = OpcodeAsUnsigned (&success);
1806 if (!success)
1807 return false;
1808
1809 // Read the register value from the operand register Rn.
1810 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1811 if (!success)
1812 return false;
1813
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001814 EmulateInstruction::Context context;
1815 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001816 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1817 if (!success)
1818 return false;
1819
1820 addr_t target; // target address
1821 uint32_t imm32; // PC-relative offset to branch forward
1822 bool nonzero;
1823 switch (encoding) {
1824 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001825 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001826 nonzero = BitIsSet(opcode, 11);
1827 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001828 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001829 break;
1830 default:
1831 return false;
1832 }
1833 if (nonzero ^ (reg_val == 0))
1834 if (!BranchWritePC(context, target))
1835 return false;
1836
1837 return true;
1838}
1839
Johnny Chen60299ec2011-02-17 19:34:27 +00001840// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1841// A base register provides a pointer to the table, and a second register supplies an index into the table.
1842// The branch length is twice the value of the byte returned from the table.
1843//
1844// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1845// A base register provides a pointer to the table, and a second register supplies an index into the table.
1846// The branch length is twice the value of the halfword returned from the table.
1847// TBB, TBH
1848bool
1849EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1850{
1851#if 0
1852 // ARM pseudo code...
1853 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1854 if is_tbh then
1855 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1856 else
1857 halfwords = UInt(MemU[R[n]+R[m], 1]);
1858 BranchWritePC(PC + 2*halfwords);
1859#endif
1860
1861 bool success = false;
1862 const uint32_t opcode = OpcodeAsUnsigned (&success);
1863 if (!success)
1864 return false;
1865
1866 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1867 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1868 bool is_tbh; // true if table branch halfword
1869 switch (encoding) {
1870 case eEncodingT1:
1871 Rn = Bits32(opcode, 19, 16);
1872 Rm = Bits32(opcode, 3, 0);
1873 is_tbh = BitIsSet(opcode, 4);
1874 if (Rn == 13 || BadReg(Rm))
1875 return false;
1876 if (InITBlock() && !LastInITBlock())
1877 return false;
1878 break;
1879 default:
1880 return false;
1881 }
1882
1883 // Read the address of the table from the operand register Rn.
1884 // The PC can be used, in which case the table immediately follows this instruction.
1885 uint32_t base =
1886 Rn == 15 ? (ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success) + 4)
1887 : ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1888 if (!success)
1889 return false;
1890
1891 // the table index
1892 uint32_t index = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1893 if (!success)
1894 return false;
1895
1896 // the offsetted table address
1897 addr_t addr = base + (is_tbh ? index*2 : index);
1898
1899 // PC-relative offset to branch forward
1900 EmulateInstruction::Context context;
1901 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001902 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001903 if (!success)
1904 return false;
1905
1906 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1907 if (!success)
1908 return false;
1909
1910 // target address
1911 addr_t target = pc + 4 + offset;
1912 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1913 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
1914
1915 if (!BranchWritePC(context, target))
1916 return false;
1917
1918 return true;
1919}
1920
Johnny Chen8fa20592011-02-18 01:22:22 +00001921// This instruction adds an immediate value to a register value, and writes the result to the destination
1922// register. It can optionally update the condition flags based on the result.
1923bool
1924EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
1925{
1926#if 0
1927 // ARM pseudo code...
1928 if ConditionPassed() then
1929 EncodingSpecificOperations();
1930 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1931 if d == 15 then
1932 ALUWritePC(result); // setflags is always FALSE here
1933 else
1934 R[d] = result;
1935 if setflags then
1936 APSR.N = result<31>;
1937 APSR.Z = IsZeroBit(result);
1938 APSR.C = carry;
1939 APSR.V = overflow;
1940#endif
1941
1942 bool success = false;
1943 const uint32_t opcode = OpcodeAsUnsigned (&success);
1944 if (!success)
1945 return false;
1946
1947 if (ConditionPassed())
1948 {
1949 uint32_t Rd, Rn;
1950 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
1951 bool setflags;
1952 switch (encoding)
1953 {
1954 case eEncodingA1:
1955 Rd = Bits32(opcode, 15, 12);
1956 Rn = Bits32(opcode, 19, 16);
1957 setflags = BitIsSet(opcode, 20);
1958 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1959 break;
1960 default:
1961 return false;
1962 }
1963
Johnny Chen8fa20592011-02-18 01:22:22 +00001964 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00001965 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00001966 if (!success)
1967 return false;
1968
1969 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1970
1971 EmulateInstruction::Context context;
1972 context.type = EmulateInstruction::eContextImmediate;
1973 context.SetNoArgs ();
1974
1975 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1976 return false;
1977 }
1978 return true;
1979}
1980
Johnny Chend761dcf2011-02-17 22:03:29 +00001981// This instruction adds a register value and an optionally-shifted register value, and writes the result
1982// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001983bool
Johnny Chen9f687722011-02-18 00:02:28 +00001984EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001985{
1986#if 0
1987 // ARM pseudo code...
1988 if ConditionPassed() then
1989 EncodingSpecificOperations();
1990 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1991 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1992 if d == 15 then
1993 ALUWritePC(result); // setflags is always FALSE here
1994 else
1995 R[d] = result;
1996 if setflags then
1997 APSR.N = result<31>;
1998 APSR.Z = IsZeroBit(result);
1999 APSR.C = carry;
2000 APSR.V = overflow;
2001#endif
2002
2003 bool success = false;
2004 const uint32_t opcode = OpcodeAsUnsigned (&success);
2005 if (!success)
2006 return false;
2007
2008 if (ConditionPassed())
2009 {
2010 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002011 ARM_ShifterType shift_t;
2012 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002013 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002014 switch (encoding)
2015 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002016 case eEncodingT1:
2017 Rd = Bits32(opcode, 2, 0);
2018 Rn = Bits32(opcode, 5, 3);
2019 Rm = Bits32(opcode, 8, 6);
2020 setflags = !InITBlock();
2021 shift_t = SRType_LSL;
2022 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002023 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002024 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002025 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002026 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002027 shift_t = SRType_LSL;
2028 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002029 if (Rn == 15 && Rm == 15)
2030 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002031 if (Rd == 15 && InITBlock() && !LastInITBlock())
2032 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002033 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002034 case eEncodingA1:
2035 Rd = Bits32(opcode, 15, 12);
2036 Rn = Bits32(opcode, 19, 16);
2037 Rm = Bits32(opcode, 3, 0);
2038 setflags = BitIsSet(opcode, 20);
2039 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2040 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002041 default:
2042 return false;
2043 }
2044
Johnny Chen26863dc2011-02-09 23:43:29 +00002045 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002046 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002047 if (!success)
2048 return false;
2049
2050 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002051 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002052 if (!success)
2053 return false;
2054
Johnny Chene97c0d52011-02-18 19:32:20 +00002055 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002056 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002057
2058 EmulateInstruction::Context context;
2059 context.type = EmulateInstruction::eContextImmediate;
2060 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002061
Johnny Chen10530c22011-02-17 22:37:12 +00002062 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002063 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002064 }
2065 return true;
2066}
2067
Johnny Chene4a4d302011-02-11 21:53:58 +00002068// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002069bool
Johnny Chen9f687722011-02-18 00:02:28 +00002070EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002071{
2072#if 0
2073 // ARM pseudo code...
2074 if ConditionPassed() then
2075 EncodingSpecificOperations();
2076 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2077 APSR.N = result<31>;
2078 APSR.Z = IsZeroBit(result);
2079 APSR.C = carry;
2080 APSR.V = overflow;
2081#endif
2082
2083 bool success = false;
2084 const uint32_t opcode = OpcodeAsUnsigned (&success);
2085 if (!success)
2086 return false;
2087
2088 uint32_t Rn; // the first operand
2089 uint32_t imm32; // the immediate value to be compared with
2090 switch (encoding) {
2091 case eEncodingT1:
2092 Rn = Bits32(opcode, 10, 8);
2093 imm32 = Bits32(opcode, 7, 0);
2094 break;
2095 default:
2096 return false;
2097 }
2098 // Read the register value from the operand register Rn.
2099 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2100 if (!success)
2101 return false;
2102
Johnny Chen10530c22011-02-17 22:37:12 +00002103 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2104
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002105 EmulateInstruction::Context context;
2106 context.type = EmulateInstruction::eContextImmediate;
2107 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002108 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2109 return false;
2110
Johnny Chend4dc4442011-02-11 02:02:56 +00002111 return true;
2112}
2113
Johnny Chene4a4d302011-02-11 21:53:58 +00002114// CMP (register)
2115bool
Johnny Chen9f687722011-02-18 00:02:28 +00002116EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002117{
2118#if 0
2119 // ARM pseudo code...
2120 if ConditionPassed() then
2121 EncodingSpecificOperations();
2122 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2123 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2124 APSR.N = result<31>;
2125 APSR.Z = IsZeroBit(result);
2126 APSR.C = carry;
2127 APSR.V = overflow;
2128#endif
2129
2130 bool success = false;
2131 const uint32_t opcode = OpcodeAsUnsigned (&success);
2132 if (!success)
2133 return false;
2134
2135 uint32_t Rn; // the first operand
2136 uint32_t Rm; // the second operand
2137 switch (encoding) {
2138 case eEncodingT1:
2139 Rn = Bits32(opcode, 2, 0);
2140 Rm = Bits32(opcode, 5, 3);
2141 break;
2142 case eEncodingT2:
2143 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2144 Rm = Bits32(opcode, 6, 3);
2145 if (Rn < 8 && Rm < 8)
2146 return false;
2147 if (Rn == 15 || Rm == 15)
2148 return false;
2149 break;
2150 default:
2151 return false;
2152 }
2153 // Read the register value from register Rn.
2154 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2155 if (!success)
2156 return false;
2157 // Read the register value from register Rm.
2158 // The register value is not being shifted since we don't handle ARM for now.
2159 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2160 if (!success)
2161 return false;
2162
Johnny Chen10530c22011-02-17 22:37:12 +00002163 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2164
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002165 EmulateInstruction::Context context;
2166 context.type = EmulateInstruction::eContextImmediate;
2167 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002168 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2169 return false;
2170
Johnny Chene4a4d302011-02-11 21:53:58 +00002171 return true;
2172}
2173
Johnny Chen82f16aa2011-02-15 20:10:55 +00002174// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2175// shifting in copies of its sign bit, and writes the result to the destination register. It can
2176// optionally update the condition flags based on the result.
2177bool
2178EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2179{
2180#if 0
2181 // ARM pseudo code...
2182 if ConditionPassed() then
2183 EncodingSpecificOperations();
2184 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2185 if d == 15 then // Can only occur for ARM encoding
2186 ALUWritePC(result); // setflags is always FALSE here
2187 else
2188 R[d] = result;
2189 if setflags then
2190 APSR.N = result<31>;
2191 APSR.Z = IsZeroBit(result);
2192 APSR.C = carry;
2193 // APSR.V unchanged
2194#endif
2195
Johnny Chen41a0a152011-02-16 01:27:54 +00002196 return EmulateShiftImm(encoding, SRType_ASR);
2197}
2198
2199// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2200// shifting in copies of its sign bit, and writes the result to the destination register.
2201// The variable number of bits is read from the bottom byte of a register. It can optionally update
2202// the condition flags based on the result.
2203bool
2204EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2205{
2206#if 0
2207 // ARM pseudo code...
2208 if ConditionPassed() then
2209 EncodingSpecificOperations();
2210 shift_n = UInt(R[m]<7:0>);
2211 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2212 R[d] = result;
2213 if setflags then
2214 APSR.N = result<31>;
2215 APSR.Z = IsZeroBit(result);
2216 APSR.C = carry;
2217 // APSR.V unchanged
2218#endif
2219
2220 return EmulateShiftReg(encoding, SRType_ASR);
2221}
2222
2223// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2224// shifting in zeros, and writes the result to the destination register. It can optionally
2225// update the condition flags based on the result.
2226bool
2227EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2228{
2229#if 0
2230 // ARM pseudo code...
2231 if ConditionPassed() then
2232 EncodingSpecificOperations();
2233 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2234 if d == 15 then // Can only occur for ARM encoding
2235 ALUWritePC(result); // setflags is always FALSE here
2236 else
2237 R[d] = result;
2238 if setflags then
2239 APSR.N = result<31>;
2240 APSR.Z = IsZeroBit(result);
2241 APSR.C = carry;
2242 // APSR.V unchanged
2243#endif
2244
2245 return EmulateShiftImm(encoding, SRType_LSL);
2246}
2247
2248// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2249// shifting in zeros, and writes the result to the destination register. The variable number
2250// of bits is read from the bottom byte of a register. It can optionally update the condition
2251// flags based on the result.
2252bool
2253EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2254{
2255#if 0
2256 // ARM pseudo code...
2257 if ConditionPassed() then
2258 EncodingSpecificOperations();
2259 shift_n = UInt(R[m]<7:0>);
2260 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2261 R[d] = result;
2262 if setflags then
2263 APSR.N = result<31>;
2264 APSR.Z = IsZeroBit(result);
2265 APSR.C = carry;
2266 // APSR.V unchanged
2267#endif
2268
2269 return EmulateShiftReg(encoding, SRType_LSL);
2270}
2271
2272// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2273// shifting in zeros, and writes the result to the destination register. It can optionally
2274// update the condition flags based on the result.
2275bool
2276EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2277{
2278#if 0
2279 // ARM pseudo code...
2280 if ConditionPassed() then
2281 EncodingSpecificOperations();
2282 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2283 if d == 15 then // Can only occur for ARM encoding
2284 ALUWritePC(result); // setflags is always FALSE here
2285 else
2286 R[d] = result;
2287 if setflags then
2288 APSR.N = result<31>;
2289 APSR.Z = IsZeroBit(result);
2290 APSR.C = carry;
2291 // APSR.V unchanged
2292#endif
2293
2294 return EmulateShiftImm(encoding, SRType_LSR);
2295}
2296
2297// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2298// shifting in zeros, and writes the result to the destination register. The variable number
2299// of bits is read from the bottom byte of a register. It can optionally update the condition
2300// flags based on the result.
2301bool
2302EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2303{
2304#if 0
2305 // ARM pseudo code...
2306 if ConditionPassed() then
2307 EncodingSpecificOperations();
2308 shift_n = UInt(R[m]<7:0>);
2309 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2310 R[d] = result;
2311 if setflags then
2312 APSR.N = result<31>;
2313 APSR.Z = IsZeroBit(result);
2314 APSR.C = carry;
2315 // APSR.V unchanged
2316#endif
2317
2318 return EmulateShiftReg(encoding, SRType_LSR);
2319}
2320
Johnny Cheneeab4852011-02-16 22:14:44 +00002321// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2322// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2323// It can optionally update the condition flags based on the result.
2324bool
2325EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2326{
2327#if 0
2328 // ARM pseudo code...
2329 if ConditionPassed() then
2330 EncodingSpecificOperations();
2331 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2332 if d == 15 then // Can only occur for ARM encoding
2333 ALUWritePC(result); // setflags is always FALSE here
2334 else
2335 R[d] = result;
2336 if setflags then
2337 APSR.N = result<31>;
2338 APSR.Z = IsZeroBit(result);
2339 APSR.C = carry;
2340 // APSR.V unchanged
2341#endif
2342
2343 return EmulateShiftImm(encoding, SRType_ROR);
2344}
2345
2346// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2347// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2348// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2349// flags based on the result.
2350bool
2351EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2352{
2353#if 0
2354 // ARM pseudo code...
2355 if ConditionPassed() then
2356 EncodingSpecificOperations();
2357 shift_n = UInt(R[m]<7:0>);
2358 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2359 R[d] = result;
2360 if setflags then
2361 APSR.N = result<31>;
2362 APSR.Z = IsZeroBit(result);
2363 APSR.C = carry;
2364 // APSR.V unchanged
2365#endif
2366
2367 return EmulateShiftReg(encoding, SRType_ROR);
2368}
2369
2370// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2371// with the carry flag shifted into bit [31].
2372//
2373// RRX can optionally update the condition flags based on the result.
2374// In that case, bit [0] is shifted into the carry flag.
2375bool
2376EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2377{
2378#if 0
2379 // ARM pseudo code...
2380 if ConditionPassed() then
2381 EncodingSpecificOperations();
2382 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2383 if d == 15 then // Can only occur for ARM encoding
2384 ALUWritePC(result); // setflags is always FALSE here
2385 else
2386 R[d] = result;
2387 if setflags then
2388 APSR.N = result<31>;
2389 APSR.Z = IsZeroBit(result);
2390 APSR.C = carry;
2391 // APSR.V unchanged
2392#endif
2393
2394 return EmulateShiftImm(encoding, SRType_RRX);
2395}
2396
Johnny Chen41a0a152011-02-16 01:27:54 +00002397bool
2398EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2399{
2400 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2401
Johnny Chen82f16aa2011-02-15 20:10:55 +00002402 bool success = false;
2403 const uint32_t opcode = OpcodeAsUnsigned (&success);
2404 if (!success)
2405 return false;
2406
2407 if (ConditionPassed())
2408 {
Johnny Chene7f89532011-02-15 23:22:46 +00002409 uint32_t Rd; // the destination register
2410 uint32_t Rm; // the first operand register
2411 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002412 uint32_t carry; // the carry bit after the shift operation
2413 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002414
2415 // Special case handling!
2416 // A8.6.139 ROR (immediate) -- Encoding T1
2417 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2418 {
2419 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2420 // have the same decoding of bit fields as the other Thumb2 shift operations.
2421 encoding = eEncodingT2;
2422 }
2423
Johnny Chen82f16aa2011-02-15 20:10:55 +00002424 switch (encoding) {
2425 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002426 // Due to the above special case handling!
2427 assert(shift_type != SRType_ROR);
2428
Johnny Chen82f16aa2011-02-15 20:10:55 +00002429 Rd = Bits32(opcode, 2, 0);
2430 Rm = Bits32(opcode, 5, 3);
2431 setflags = !InITBlock();
2432 imm5 = Bits32(opcode, 10, 6);
2433 break;
2434 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002435 // A8.6.141 RRX
2436 assert(shift_type != SRType_RRX);
2437
Johnny Chen82f16aa2011-02-15 20:10:55 +00002438 Rd = Bits32(opcode, 11, 8);
2439 Rm = Bits32(opcode, 3, 0);
2440 setflags = BitIsSet(opcode, 20);
2441 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2442 if (BadReg(Rd) || BadReg(Rm))
2443 return false;
2444 break;
2445 case eEncodingA1:
2446 Rd = Bits32(opcode, 15, 12);
2447 Rm = Bits32(opcode, 3, 0);
2448 setflags = BitIsSet(opcode, 20);
2449 imm5 = Bits32(opcode, 11, 7);
2450 break;
2451 default:
2452 return false;
2453 }
2454
Johnny Cheneeab4852011-02-16 22:14:44 +00002455 // A8.6.139 ROR (immediate)
2456 if (shift_type == SRType_ROR && imm5 == 0)
2457 shift_type = SRType_RRX;
2458
Johnny Chen82f16aa2011-02-15 20:10:55 +00002459 // Get the first operand.
2460 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2461 if (!success)
2462 return false;
2463
Johnny Cheneeab4852011-02-16 22:14:44 +00002464 // Decode the shift amount if not RRX.
2465 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002466
Johnny Chene97c0d52011-02-18 19:32:20 +00002467 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002468
2469 // The context specifies that an immediate is to be moved into Rd.
2470 EmulateInstruction::Context context;
2471 context.type = EmulateInstruction::eContextImmediate;
2472 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002473
Johnny Chen10530c22011-02-17 22:37:12 +00002474 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002475 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002476 }
2477 return true;
2478}
2479
Johnny Chene7f89532011-02-15 23:22:46 +00002480bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002481EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002482{
Johnny Chen41a0a152011-02-16 01:27:54 +00002483 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002484
2485 bool success = false;
2486 const uint32_t opcode = OpcodeAsUnsigned (&success);
2487 if (!success)
2488 return false;
2489
2490 if (ConditionPassed())
2491 {
2492 uint32_t Rd; // the destination register
2493 uint32_t Rn; // the first operand register
2494 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2495 uint32_t carry; // the carry bit after the shift operation
2496 bool setflags;
2497 switch (encoding) {
2498 case eEncodingT1:
2499 Rd = Bits32(opcode, 2, 0);
2500 Rn = Rd;
2501 Rm = Bits32(opcode, 5, 3);
2502 setflags = !InITBlock();
2503 break;
2504 case eEncodingT2:
2505 Rd = Bits32(opcode, 11, 8);
2506 Rn = Bits32(opcode, 19, 16);
2507 Rm = Bits32(opcode, 3, 0);
2508 setflags = BitIsSet(opcode, 20);
2509 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2510 return false;
2511 break;
2512 case eEncodingA1:
2513 Rd = Bits32(opcode, 15, 12);
2514 Rn = Bits32(opcode, 3, 0);
2515 Rm = Bits32(opcode, 11, 8);
2516 setflags = BitIsSet(opcode, 20);
2517 if (Rd == 15 || Rn == 15 || Rm == 15)
2518 return false;
2519 break;
2520 default:
2521 return false;
2522 }
2523
2524 // Get the first operand.
2525 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2526 if (!success)
2527 return false;
2528 // Get the Rm register content.
2529 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2530 if (!success)
2531 return false;
2532
2533 // Get the shift amount.
2534 uint32_t amt = Bits32(val, 7, 0);
2535
Johnny Chene97c0d52011-02-18 19:32:20 +00002536 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002537
2538 // The context specifies that an immediate is to be moved into Rd.
2539 EmulateInstruction::Context context;
2540 context.type = EmulateInstruction::eContextImmediate;
2541 context.SetNoArgs ();
2542
Johnny Chen10530c22011-02-17 22:37:12 +00002543 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002544 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002545 }
2546 return true;
2547}
2548
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002549// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002550// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002551// can be written back to the base register.
2552bool
2553EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2554{
2555#if 0
2556 // ARM pseudo code...
2557 if ConditionPassed()
2558 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2559 address = R[n];
2560
2561 for i = 0 to 14
2562 if registers<i> == '1' then
2563 R[i] = MemA[address, 4]; address = address + 4;
2564 if registers<15> == '1' then
2565 LoadWritePC (MemA[address, 4]);
2566
2567 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2568 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2569
2570#endif
2571
2572 bool success = false;
2573 const uint32_t opcode = OpcodeAsUnsigned (&success);
2574 if (!success)
2575 return false;
2576
2577 if (ConditionPassed())
2578 {
2579 uint32_t n;
2580 uint32_t registers = 0;
2581 bool wback;
2582 const uint32_t addr_byte_size = GetAddressByteSize();
2583 switch (encoding)
2584 {
2585 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002586 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002587 n = Bits32 (opcode, 10, 8);
2588 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002589 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002590 wback = BitIsClear (registers, n);
2591 // if BitCount(registers) < 1 then UNPREDICTABLE;
2592 if (BitCount(registers) < 1)
2593 return false;
2594 break;
2595 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002596 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2597 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002598 n = Bits32 (opcode, 19, 16);
2599 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002600 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002601 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002602
2603 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002604 if ((n == 15)
2605 || (BitCount (registers) < 2)
2606 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2607 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002608
2609 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002610 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002611 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002612
2613 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002614 if (wback
2615 && BitIsSet (registers, n))
2616 return false;
2617 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002618
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002619 case eEncodingA1:
2620 n = Bits32 (opcode, 19, 16);
2621 registers = Bits32 (opcode, 15, 0);
2622 wback = BitIsSet (opcode, 21);
2623 if ((n == 15)
2624 || (BitCount (registers) < 1))
2625 return false;
2626 break;
2627 default:
2628 return false;
2629 }
2630
2631 int32_t offset = 0;
2632 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2633 if (!success)
2634 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002635
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002636 EmulateInstruction::Context context;
2637 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2638 Register dwarf_reg;
2639 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2640 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002641
2642 for (int i = 0; i < 14; ++i)
2643 {
2644 if (BitIsSet (registers, i))
2645 {
Caroline Tice85aab332011-02-08 23:56:10 +00002646 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002647 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002648 if (wback && (n == 13)) // Pop Instruction
2649 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2650
2651 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002652 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002653 if (!success)
2654 return false;
2655
2656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2657 return false;
2658
2659 offset += addr_byte_size;
2660 }
2661 }
2662
2663 if (BitIsSet (registers, 15))
2664 {
2665 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002666 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002667 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002668 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002669 if (!success)
2670 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002671 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002672 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002673 return false;
2674 }
2675
2676 if (wback && BitIsClear (registers, n))
2677 {
Caroline Ticefa172202011-02-11 22:49:54 +00002678 // R[n] = R[n] + 4 * BitCount (registers)
2679 int32_t offset = addr_byte_size * BitCount (registers);
2680 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002681 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002682
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2684 return false;
2685 }
2686 if (wback && BitIsSet (registers, n))
2687 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002688 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002689 }
2690 return true;
2691}
Caroline Tice713c2662011-02-11 17:59:55 +00002692
2693// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2694// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2695// can optionally be written back tot he base registers.
2696bool
2697EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2698{
2699#if 0
2700 // ARM pseudo code...
2701 if ConditionPassed() then
2702 EncodingSpecificOperations();
2703 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002704
Caroline Tice713c2662011-02-11 17:59:55 +00002705 for i = 0 to 14
2706 if registers<i> == ’1’ then
2707 R[i] = MemA[address,4]; address = address + 4;
2708
2709 if registers<15> == ’1’ then
2710 LoadWritePC(MemA[address,4]);
2711
2712 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2713 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2714#endif
2715
2716 bool success = false;
2717 const uint32_t opcode = OpcodeAsUnsigned (&success);
2718 if (!success)
2719 return false;
2720
2721 if (ConditionPassed())
2722 {
2723 uint32_t n;
2724 uint32_t registers = 0;
2725 bool wback;
2726 const uint32_t addr_byte_size = GetAddressByteSize();
2727
2728 // EncodingSpecificOperations();
2729 switch (encoding)
2730 {
2731 case eEncodingA1:
2732 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2733 n = Bits32 (opcode, 19, 16);
2734 registers = Bits32 (opcode, 15, 0);
2735 wback = BitIsSet (opcode, 21);
2736
2737 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2738 if ((n == 15) || (BitCount (registers) < 1))
2739 return false;
2740
2741 break;
2742
2743 default:
2744 return false;
2745 }
2746 // address = R[n] - 4*BitCount(registers) + 4;
2747
2748 int32_t offset = 0;
2749 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2750
2751 if (!success)
2752 return false;
2753
2754 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2755
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002756 EmulateInstruction::Context context;
2757 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2758 Register dwarf_reg;
2759 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2760 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002761
2762 // for i = 0 to 14
2763 for (int i = 0; i < 14; ++i)
2764 {
2765 // if registers<i> == ’1’ then
2766 if (BitIsSet (registers, i))
2767 {
2768 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002769 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002770 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002771 if (!success)
2772 return false;
2773 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2774 return false;
2775 offset += addr_byte_size;
2776 }
2777 }
2778
2779 // if registers<15> == ’1’ then
2780 // LoadWritePC(MemA[address,4]);
2781 if (BitIsSet (registers, 15))
2782 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002783 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002784 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002785 if (!success)
2786 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002787 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002788 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002789 return false;
2790 }
2791
2792 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2793 if (wback && BitIsClear (registers, n))
2794 {
Caroline Tice713c2662011-02-11 17:59:55 +00002795 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2796 if (!success)
2797 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002798
2799 offset = (addr_byte_size * BitCount (registers)) * -1;
2800 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002801 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002802 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002803 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2804 return false;
2805 }
2806
2807 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2808 if (wback && BitIsSet (registers, n))
2809 return WriteBits32Unknown (n);
2810 }
2811 return true;
2812}
2813
2814// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2815// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2816// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002817bool
2818EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2819{
2820#if 0
2821 // ARM pseudo code...
2822 if ConditionPassed() then
2823 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2824 address = R[n] - 4*BitCount(registers);
2825
2826 for i = 0 to 14
2827 if registers<i> == ’1’ then
2828 R[i] = MemA[address,4]; address = address + 4;
2829 if registers<15> == ’1’ then
2830 LoadWritePC(MemA[address,4]);
2831
2832 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2833 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2834#endif
2835
2836 bool success = false;
2837 const uint32_t opcode = OpcodeAsUnsigned (&success);
2838 if (!success)
2839 return false;
2840
2841 if (ConditionPassed())
2842 {
2843 uint32_t n;
2844 uint32_t registers = 0;
2845 bool wback;
2846 const uint32_t addr_byte_size = GetAddressByteSize();
2847 switch (encoding)
2848 {
2849 case eEncodingT1:
2850 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2851 n = Bits32 (opcode, 19, 16);
2852 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002853 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002854 wback = BitIsSet (opcode, 21);
2855
2856 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2857 if ((n == 15)
2858 || (BitCount (registers) < 2)
2859 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2860 return false;
2861
2862 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002863 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002864 return false;
2865
2866 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2867 if (wback && BitIsSet (registers, n))
2868 return false;
2869
2870 break;
2871
2872 case eEncodingA1:
2873 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2874 n = Bits32 (opcode, 19, 16);
2875 registers = Bits32 (opcode, 15, 0);
2876 wback = BitIsSet (opcode, 21);
2877
2878 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2879 if ((n == 15) || (BitCount (registers) < 1))
2880 return false;
2881
2882 break;
2883
2884 default:
2885 return false;
2886 }
2887
Caroline Tice713c2662011-02-11 17:59:55 +00002888 // address = R[n] - 4*BitCount(registers);
2889
Caroline Tice0b29e242011-02-08 23:16:02 +00002890 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002891 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2892
2893 if (!success)
2894 return false;
2895
2896 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002897 EmulateInstruction::Context context;
2898 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2899 Register dwarf_reg;
2900 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2901 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002902
2903 for (int i = 0; i < 14; ++i)
2904 {
2905 if (BitIsSet (registers, i))
2906 {
2907 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002908 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002909 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002910 if (!success)
2911 return false;
2912
2913 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2914 return false;
2915
2916 offset += addr_byte_size;
2917 }
2918 }
2919
2920 // if registers<15> == ’1’ then
2921 // LoadWritePC(MemA[address,4]);
2922 if (BitIsSet (registers, 15))
2923 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002924 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002925 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002926 if (!success)
2927 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002928 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002929 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002930 return false;
2931 }
2932
2933 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2934 if (wback && BitIsClear (registers, n))
2935 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002936 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2937 if (!success)
2938 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002939
2940 offset = (addr_byte_size * BitCount (registers)) * -1;
2941 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002942 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002943 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2945 return false;
2946 }
2947
2948 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2949 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002950 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002951 }
2952 return true;
2953}
Caroline Tice85aab332011-02-08 23:56:10 +00002954
Caroline Tice713c2662011-02-11 17:59:55 +00002955// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2956// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2957// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002958bool
2959EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2960{
2961#if 0
2962 if ConditionPassed() then
2963 EncodingSpecificOperations();
2964 address = R[n] + 4;
2965
2966 for i = 0 to 14
2967 if registers<i> == ’1’ then
2968 R[i] = MemA[address,4]; address = address + 4;
2969 if registers<15> == ’1’ then
2970 LoadWritePC(MemA[address,4]);
2971
2972 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2973 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2974#endif
2975
2976 bool success = false;
2977 const uint32_t opcode = OpcodeAsUnsigned (&success);
2978 if (!success)
2979 return false;
2980
2981 if (ConditionPassed())
2982 {
2983 uint32_t n;
2984 uint32_t registers = 0;
2985 bool wback;
2986 const uint32_t addr_byte_size = GetAddressByteSize();
2987 switch (encoding)
2988 {
2989 case eEncodingA1:
2990 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2991 n = Bits32 (opcode, 19, 16);
2992 registers = Bits32 (opcode, 15, 0);
2993 wback = BitIsSet (opcode, 21);
2994
2995 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2996 if ((n == 15) || (BitCount (registers) < 1))
2997 return false;
2998
2999 break;
3000 default:
3001 return false;
3002 }
3003 // address = R[n] + 4;
3004
3005 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003006 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3007
3008 if (!success)
3009 return false;
3010
3011 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003012
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003013 EmulateInstruction::Context context;
3014 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3015 Register dwarf_reg;
3016 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3017 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003018
3019 for (int i = 0; i < 14; ++i)
3020 {
3021 if (BitIsSet (registers, i))
3022 {
3023 // R[i] = MemA[address,4]; address = address + 4;
3024
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003025 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003026 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003027 if (!success)
3028 return false;
3029
3030 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3031 return false;
3032
3033 offset += addr_byte_size;
3034 }
3035 }
3036
3037 // if registers<15> == ’1’ then
3038 // LoadWritePC(MemA[address,4]);
3039 if (BitIsSet (registers, 15))
3040 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003041 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003042 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003043 if (!success)
3044 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003045 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003046 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003047 return false;
3048 }
3049
3050 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3051 if (wback && BitIsClear (registers, n))
3052 {
Caroline Tice85aab332011-02-08 23:56:10 +00003053 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3054 if (!success)
3055 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003056
3057 offset = addr_byte_size * BitCount (registers);
3058 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003059 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003060 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003061 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3062 return false;
3063 }
3064
3065 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3066 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003067 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003068 }
3069 return true;
3070}
Caroline Tice0b29e242011-02-08 23:16:02 +00003071
Johnny Chenef21b592011-02-10 01:52:38 +00003072// Load Register (immediate) calculates an address from a base register value and
3073// an immediate offset, loads a word from memory, and writes to a register.
3074// LDR (immediate, Thumb)
3075bool
3076EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3077{
3078#if 0
3079 // ARM pseudo code...
3080 if (ConditionPassed())
3081 {
3082 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3083 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3084 address = if index then offset_addr else R[n];
3085 data = MemU[address,4];
3086 if wback then R[n] = offset_addr;
3087 if t == 15 then
3088 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3089 elsif UnalignedSupport() || address<1:0> = '00' then
3090 R[t] = data;
3091 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3092 }
3093#endif
3094
3095 bool success = false;
3096 const uint32_t opcode = OpcodeAsUnsigned (&success);
3097 if (!success)
3098 return false;
3099
3100 if (ConditionPassed())
3101 {
3102 uint32_t Rt; // the destination register
3103 uint32_t Rn; // the base register
3104 uint32_t imm32; // the immediate offset used to form the address
3105 addr_t offset_addr; // the offset address
3106 addr_t address; // the calculated address
3107 uint32_t data; // the literal data value from memory load
3108 bool add, index, wback;
3109 switch (encoding) {
3110 case eEncodingT1:
3111 Rt = Bits32(opcode, 5, 3);
3112 Rn = Bits32(opcode, 2, 0);
3113 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3114 // index = TRUE; add = TRUE; wback = FALSE
3115 add = true;
3116 index = true;
3117 wback = false;
3118 break;
3119 default:
3120 return false;
3121 }
3122 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3123 if (!success)
3124 return false;
3125 if (add)
3126 offset_addr = base + imm32;
3127 else
3128 offset_addr = base - imm32;
3129
3130 address = (index ? offset_addr : base);
3131
3132 if (wback)
3133 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003134 EmulateInstruction::Context ctx;
3135 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3136 Register dwarf_reg;
3137 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3138 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3139
Johnny Chenef21b592011-02-10 01:52:38 +00003140 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3141 return false;
3142 }
3143
3144 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003145 EmulateInstruction::Context context;
3146 context.type = EmulateInstruction::eContextImmediate;
3147 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003148
3149 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003150 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003151 if (!success)
3152 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003153
3154 if (Rt == 15)
3155 {
3156 if (Bits32(address, 1, 0) == 0)
3157 {
Johnny Chen668b4512011-02-15 21:08:58 +00003158 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003159 return false;
3160 }
3161 else
3162 return false;
3163 }
3164 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3165 {
3166 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3167 return false;
3168 }
3169 else
3170 return false;
3171 }
3172 return true;
3173}
3174
Caroline Ticeaf556562011-02-15 18:42:15 +00003175// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3176// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3177// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003178bool
3179EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3180{
3181#if 0
3182 if ConditionPassed() then
3183 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3184 address = R[n];
3185
3186 for i = 0 to 14
3187 if registers<i> == ’1’ then
3188 if i == n && wback && i != LowestSetBit(registers) then
3189 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3190 else
3191 MemA[address,4] = R[i];
3192 address = address + 4;
3193
3194 if registers<15> == ’1’ then // Only possible for encoding A1
3195 MemA[address,4] = PCStoreValue();
3196 if wback then R[n] = R[n] + 4*BitCount(registers);
3197#endif
3198
3199 bool success = false;
3200 const uint32_t opcode = OpcodeAsUnsigned (&success);
3201 if (!success)
3202 return false;
3203
3204 if (ConditionPassed ())
3205 {
3206 uint32_t n;
3207 uint32_t registers = 0;
3208 bool wback;
3209 const uint32_t addr_byte_size = GetAddressByteSize();
3210
3211 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3212 switch (encoding)
3213 {
3214 case eEncodingT1:
3215 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3216 n = Bits32 (opcode, 10, 8);
3217 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003218 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003219 wback = true;
3220
3221 // if BitCount(registers) < 1 then UNPREDICTABLE;
3222 if (BitCount (registers) < 1)
3223 return false;
3224
3225 break;
3226
3227 case eEncodingT2:
3228 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3229 n = Bits32 (opcode, 19, 16);
3230 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003231 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003232 wback = BitIsSet (opcode, 21);
3233
3234 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3235 if ((n == 15) || (BitCount (registers) < 2))
3236 return false;
3237
3238 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3239 if (wback && BitIsSet (registers, n))
3240 return false;
3241
3242 break;
3243
3244 case eEncodingA1:
3245 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3246 n = Bits32 (opcode, 19, 16);
3247 registers = Bits32 (opcode, 15, 0);
3248 wback = BitIsSet (opcode, 21);
3249
3250 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3251 if ((n == 15) || (BitCount (registers) < 1))
3252 return false;
3253
3254 break;
3255
3256 default:
3257 return false;
3258 }
3259
3260 // address = R[n];
3261 int32_t offset = 0;
3262 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3263 if (!success)
3264 return false;
3265
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003266 EmulateInstruction::Context context;
3267 context.type = EmulateInstruction::eContextRegisterStore;
3268 Register base_reg;
3269 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003270
3271 // for i = 0 to 14
3272 for (int i = 0; i < 14; ++i)
3273 {
3274 int lowest_set_bit = 14;
3275 // if registers<i> == ’1’ then
3276 if (BitIsSet (registers, i))
3277 {
3278 if (i < lowest_set_bit)
3279 lowest_set_bit = i;
3280 // if i == n && wback && i != LowestSetBit(registers) then
3281 if ((i == n) && wback && (i != lowest_set_bit))
3282 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3283 WriteBits32UnknownToMemory (address + offset);
3284 else
3285 {
3286 // MemA[address,4] = R[i];
3287 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3288 if (!success)
3289 return false;
3290
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003291 Register data_reg;
3292 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3293 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003294 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003295 return false;
3296 }
3297
3298 // address = address + 4;
3299 offset += addr_byte_size;
3300 }
3301 }
3302
3303 // if registers<15> == ’1’ then // Only possible for encoding A1
3304 // MemA[address,4] = PCStoreValue();
3305 if (BitIsSet (registers, 15))
3306 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003307 Register pc_reg;
3308 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3309 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003310 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3311 if (!success)
3312 return false;
3313
Caroline Ticecc96eb52011-02-17 19:20:40 +00003314 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003315 return false;
3316 }
3317
3318 // if wback then R[n] = R[n] + 4*BitCount(registers);
3319 if (wback)
3320 {
3321 offset = addr_byte_size * BitCount (registers);
3322 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003323 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003324 addr_t data = address + offset;
3325 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3326 return false;
3327 }
3328 }
3329 return true;
3330}
3331
Caroline Ticeaf556562011-02-15 18:42:15 +00003332// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3333// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3334// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003335bool
3336EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3337{
3338#if 0
3339 if ConditionPassed() then
3340 EncodingSpecificOperations();
3341 address = R[n] - 4*BitCount(registers) + 4;
3342
3343 for i = 0 to 14
3344 if registers<i> == ’1’ then
3345 if i == n && wback && i != LowestSetBit(registers) then
3346 MemA[address,4] = bits(32) UNKNOWN;
3347 else
3348 MemA[address,4] = R[i];
3349 address = address + 4;
3350
3351 if registers<15> == ’1’ then
3352 MemA[address,4] = PCStoreValue();
3353
3354 if wback then R[n] = R[n] - 4*BitCount(registers);
3355#endif
3356
3357 bool success = false;
3358 const uint32_t opcode = OpcodeAsUnsigned (&success);
3359 if (!success)
3360 return false;
3361
3362 if (ConditionPassed ())
3363 {
3364 uint32_t n;
3365 uint32_t registers = 0;
3366 bool wback;
3367 const uint32_t addr_byte_size = GetAddressByteSize();
3368
3369 // EncodingSpecificOperations();
3370 switch (encoding)
3371 {
3372 case eEncodingA1:
3373 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3374 n = Bits32 (opcode, 19, 16);
3375 registers = Bits32 (opcode, 15, 0);
3376 wback = BitIsSet (opcode, 21);
3377
3378 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3379 if ((n == 15) || (BitCount (registers) < 1))
3380 return false;
3381 break;
3382 default:
3383 return false;
3384 }
3385
3386 // address = R[n] - 4*BitCount(registers) + 4;
3387 int32_t offset = 0;
3388 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3389 if (!success)
3390 return false;
3391
3392 address = address - (addr_byte_size * BitCount (registers)) + 4;
3393
3394 EmulateInstruction::Context context;
3395 context.type = EmulateInstruction::eContextRegisterStore;
3396 Register base_reg;
3397 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3398
3399 // for i = 0 to 14
3400 for (int i = 0; i < 14; ++i)
3401 {
3402 int lowest_bit_set = 14;
3403 // if registers<i> == ’1’ then
3404 if (BitIsSet (registers, i))
3405 {
3406 if (i < lowest_bit_set)
3407 lowest_bit_set = i;
3408 //if i == n && wback && i != LowestSetBit(registers) then
3409 if ((i == n) && wback && (i != lowest_bit_set))
3410 // MemA[address,4] = bits(32) UNKNOWN;
3411 WriteBits32UnknownToMemory (address + offset);
3412 else
3413 {
3414 // MemA[address,4] = R[i];
3415 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3416 if (!success)
3417 return false;
3418
3419 Register data_reg;
3420 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3421 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003422 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003423 return false;
3424 }
3425
3426 // address = address + 4;
3427 offset += addr_byte_size;
3428 }
3429 }
3430
3431 // if registers<15> == ’1’ then
3432 // MemA[address,4] = PCStoreValue();
3433 if (BitIsSet (registers, 15))
3434 {
3435 Register pc_reg;
3436 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3437 context.SetRegisterPlusOffset (pc_reg, 8);
3438 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3439 if (!success)
3440 return false;
3441
Caroline Ticecc96eb52011-02-17 19:20:40 +00003442 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003443 return false;
3444 }
3445
3446 // if wback then R[n] = R[n] - 4*BitCount(registers);
3447 if (wback)
3448 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003449 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003450 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3451 context.SetImmediateSigned (offset);
3452 addr_t data = address + offset;
3453 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3454 return false;
3455 }
3456 }
3457 return true;
3458}
3459
Caroline Ticeaf556562011-02-15 18:42:15 +00003460// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3461// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3462// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003463bool
3464EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3465{
3466#if 0
3467 if ConditionPassed() then
3468 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3469 address = R[n] - 4*BitCount(registers);
3470
3471 for i = 0 to 14
3472 if registers<i> == ’1’ then
3473 if i == n && wback && i != LowestSetBit(registers) then
3474 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3475 else
3476 MemA[address,4] = R[i];
3477 address = address + 4;
3478
3479 if registers<15> == ’1’ then // Only possible for encoding A1
3480 MemA[address,4] = PCStoreValue();
3481
3482 if wback then R[n] = R[n] - 4*BitCount(registers);
3483#endif
3484
3485
3486 bool success = false;
3487 const uint32_t opcode = OpcodeAsUnsigned (&success);
3488 if (!success)
3489 return false;
3490
3491 if (ConditionPassed ())
3492 {
3493 uint32_t n;
3494 uint32_t registers = 0;
3495 bool wback;
3496 const uint32_t addr_byte_size = GetAddressByteSize();
3497
3498 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3499 switch (encoding)
3500 {
3501 case eEncodingT1:
3502 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3503 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3504 {
3505 // See PUSH
3506 }
3507 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3508 n = Bits32 (opcode, 19, 16);
3509 registers = Bits32 (opcode, 15, 0);
3510 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3511 wback = BitIsSet (opcode, 21);
3512 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3513 if ((n == 15) || BitCount (registers) < 2)
3514 return false;
3515 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3516 if (wback && BitIsSet (registers, n))
3517 return false;
3518 break;
3519
3520 case eEncodingA1:
3521 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3522 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3523 {
3524 // See Push
3525 }
3526 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3527 n = Bits32 (opcode, 19, 16);
3528 registers = Bits32 (opcode, 15, 0);
3529 wback = BitIsSet (opcode, 21);
3530 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3531 if ((n == 15) || BitCount (registers) < 1)
3532 return false;
3533 break;
3534
3535 default:
3536 return false;
3537 }
3538
3539 // address = R[n] - 4*BitCount(registers);
3540
3541 int32_t offset = 0;
3542 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3543 if (!success)
3544 return false;
3545
3546 address = address - (addr_byte_size * BitCount (registers));
3547
3548 EmulateInstruction::Context context;
3549 context.type = EmulateInstruction::eContextRegisterStore;
3550 Register base_reg;
3551 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3552
3553 // for i = 0 to 14
3554 for (int i = 0; i < 14; ++i)
3555 {
3556 uint32_t lowest_set_bit = 14;
3557 // if registers<i> == ’1’ then
3558 if (BitIsSet (registers, i))
3559 {
3560 if (i < lowest_set_bit)
3561 lowest_set_bit = i;
3562 // if i == n && wback && i != LowestSetBit(registers) then
3563 if ((i == n) && wback && (i != lowest_set_bit))
3564 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3565 WriteBits32UnknownToMemory (address + offset);
3566 else
3567 {
3568 // MemA[address,4] = R[i];
3569 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3570 if (!success)
3571 return false;
3572
3573 Register data_reg;
3574 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3575 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003576 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003577 return false;
3578 }
3579
3580 // address = address + 4;
3581 offset += addr_byte_size;
3582 }
3583 }
3584
3585 // if registers<15> == ’1’ then // Only possible for encoding A1
3586 // MemA[address,4] = PCStoreValue();
3587 if (BitIsSet (registers, 15))
3588 {
3589 Register pc_reg;
3590 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3591 context.SetRegisterPlusOffset (pc_reg, 8);
3592 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3593 if (!success)
3594 return false;
3595
Caroline Ticecc96eb52011-02-17 19:20:40 +00003596 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003597 return false;
3598 }
3599
3600 // if wback then R[n] = R[n] - 4*BitCount(registers);
3601 if (wback)
3602 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003603 offset = (addr_byte_size * BitCount (registers)) * -1;
3604 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3605 context.SetImmediateSigned (offset);
3606 addr_t data = address + offset;
3607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3608 return false;
3609 }
3610 }
3611 return true;
3612}
3613
3614// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3615// from a base register. The consecutive memory locations start just above this address, and the address of the last
3616// of those locations can optionally be written back to the base register.
3617bool
3618EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3619{
3620#if 0
3621 if ConditionPassed() then
3622 EncodingSpecificOperations();
3623 address = R[n] + 4;
3624
3625 for i = 0 to 14
3626 if registers<i> == ’1’ then
3627 if i == n && wback && i != LowestSetBit(registers) then
3628 MemA[address,4] = bits(32) UNKNOWN;
3629 else
3630 MemA[address,4] = R[i];
3631 address = address + 4;
3632
3633 if registers<15> == ’1’ then
3634 MemA[address,4] = PCStoreValue();
3635
3636 if wback then R[n] = R[n] + 4*BitCount(registers);
3637#endif
3638
3639 bool success = false;
3640 const uint32_t opcode = OpcodeAsUnsigned (&success);
3641 if (!success)
3642 return false;
3643
3644 if (ConditionPassed())
3645 {
3646 uint32_t n;
3647 uint32_t registers = 0;
3648 bool wback;
3649 const uint32_t addr_byte_size = GetAddressByteSize();
3650
3651 // EncodingSpecificOperations();
3652 switch (encoding)
3653 {
3654 case eEncodingA1:
3655 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3656 n = Bits32 (opcode, 19, 16);
3657 registers = Bits32 (opcode, 15, 0);
3658 wback = BitIsSet (opcode, 21);
3659
3660 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3661 if ((n == 15) && (BitCount (registers) < 1))
3662 return false;
3663 break;
3664 default:
3665 return false;
3666 }
3667 // address = R[n] + 4;
3668
3669 int32_t offset = 0;
3670 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3671 if (!success)
3672 return false;
3673
3674 address = address + addr_byte_size;
3675
3676 EmulateInstruction::Context context;
3677 context.type = EmulateInstruction::eContextRegisterStore;
3678 Register base_reg;
3679 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3680
3681 uint32_t lowest_set_bit = 14;
3682 // for i = 0 to 14
3683 for (int i = 0; i < 14; ++i)
3684 {
3685 // if registers<i> == ’1’ then
3686 if (BitIsSet (registers, i))
3687 {
3688 if (i < lowest_set_bit)
3689 lowest_set_bit = i;
3690 // if i == n && wback && i != LowestSetBit(registers) then
3691 if ((i == n) && wback && (i != lowest_set_bit))
3692 // MemA[address,4] = bits(32) UNKNOWN;
3693 WriteBits32UnknownToMemory (address + offset);
3694 // else
3695 else
3696 {
3697 // MemA[address,4] = R[i];
3698 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3699 if (!success)
3700 return false;
3701
3702 Register data_reg;
3703 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3704 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003705 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003706 return false;
3707 }
3708
3709 // address = address + 4;
3710 offset += addr_byte_size;
3711 }
3712 }
3713
3714 // if registers<15> == ’1’ then
3715 // MemA[address,4] = PCStoreValue();
3716 if (BitIsSet (registers, 15))
3717 {
3718 Register pc_reg;
3719 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3720 context.SetRegisterPlusOffset (pc_reg, 8);
3721 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3722 if (!success)
3723 return false;
3724
Caroline Ticecc96eb52011-02-17 19:20:40 +00003725 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003726 return false;
3727 }
3728
3729 // if wback then R[n] = R[n] + 4*BitCount(registers);
3730 if (wback)
3731 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003732 offset = addr_byte_size * BitCount (registers);
3733 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3734 context.SetImmediateSigned (offset);
3735 addr_t data = address + offset;
3736 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3737 return false;
3738 }
3739 }
3740 return true;
3741}
Caroline Tice7fac8572011-02-15 22:53:54 +00003742
3743// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3744// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3745bool
3746EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3747{
3748#if 0
3749 if ConditionPassed() then
3750 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3751 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3752 address = if index then offset_addr else R[n];
3753 if UnalignedSupport() || address<1:0> == ’00’ then
3754 MemU[address,4] = R[t];
3755 else // Can only occur before ARMv7
3756 MemU[address,4] = bits(32) UNKNOWN;
3757 if wback then R[n] = offset_addr;
3758#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003759
Caroline Tice7fac8572011-02-15 22:53:54 +00003760 bool success = false;
3761 const uint32_t opcode = OpcodeAsUnsigned (&success);
3762 if (!success)
3763 return false;
3764
3765 if (ConditionPassed())
3766 {
3767 const uint32_t addr_byte_size = GetAddressByteSize();
3768
3769 uint32_t t;
3770 uint32_t n;
3771 uint32_t imm32;
3772 bool index;
3773 bool add;
3774 bool wback;
3775 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3776 switch (encoding)
3777 {
3778 case eEncodingT1:
3779 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3780 t = Bits32 (opcode, 2, 0);
3781 n = Bits32 (opcode, 5, 3);
3782 imm32 = Bits32 (opcode, 10, 6) << 2;
3783
3784 // index = TRUE; add = TRUE; wback = FALSE;
3785 index = true;
3786 add = false;
3787 wback = false;
3788 break;
3789
3790 case eEncodingT2:
3791 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3792 t = Bits32 (opcode, 10, 8);
3793 n = 13;
3794 imm32 = Bits32 (opcode, 7, 0) << 2;
3795
3796 // index = TRUE; add = TRUE; wback = FALSE;
3797 index = true;
3798 add = true;
3799 wback = false;
3800 break;
3801
3802 case eEncodingT3:
3803 // if Rn == ’1111’ then UNDEFINED;
3804 if (Bits32 (opcode, 19, 16) == 15)
3805 return false;
3806
3807 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3808 t = Bits32 (opcode, 15, 12);
3809 n = Bits32 (opcode, 19, 16);
3810 imm32 = Bits32 (opcode, 11, 0);
3811
3812 // index = TRUE; add = TRUE; wback = FALSE;
3813 index = true;
3814 add = true;
3815 wback = false;
3816
3817 // if t == 15 then UNPREDICTABLE;
3818 if (t == 15)
3819 return false;
3820 break;
3821
3822 case eEncodingT4:
3823 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3824 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3825 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3826 if ((Bits32 (opcode, 19, 16) == 15)
3827 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3828 return false;
3829
3830 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3831 t = Bits32 (opcode, 15, 12);
3832 n = Bits32 (opcode, 19, 16);
3833 imm32 = Bits32 (opcode, 7, 0);
3834
3835 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3836 index = BitIsSet (opcode, 10);
3837 add = BitIsSet (opcode, 9);
3838 wback = BitIsSet (opcode, 8);
3839
3840 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3841 if ((t == 15) || (wback && (n == t)))
3842 return false;
3843 break;
3844
3845 default:
3846 return false;
3847 }
3848
3849 addr_t offset_addr;
3850 addr_t address;
3851
3852 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3853 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3854 if (!success)
3855 return false;
3856
3857 if (add)
3858 offset_addr = base_address + imm32;
3859 else
3860 offset_addr = base_address - imm32;
3861
3862 // address = if index then offset_addr else R[n];
3863 if (index)
3864 address = offset_addr;
3865 else
3866 address = base_address;
3867
3868 EmulateInstruction::Context context;
3869 context.type = eContextRegisterStore;
3870 Register base_reg;
3871 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3872
3873 // if UnalignedSupport() || address<1:0> == ’00’ then
3874 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3875 {
3876 // MemU[address,4] = R[t];
3877 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3878 if (!success)
3879 return false;
3880
3881 Register data_reg;
3882 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3883 int32_t offset = address - base_address;
3884 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003885 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003886 return false;
3887 }
3888 else
3889 {
3890 // MemU[address,4] = bits(32) UNKNOWN;
3891 WriteBits32UnknownToMemory (address);
3892 }
3893
3894 // if wback then R[n] = offset_addr;
3895 if (wback)
3896 {
3897 context.type = eContextRegisterLoad;
3898 context.SetAddress (offset_addr);
3899 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3900 return false;
3901 }
3902 }
3903 return true;
3904}
Caroline Ticeaf556562011-02-15 18:42:15 +00003905
Caroline Tice3fd63e92011-02-16 00:33:43 +00003906// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3907// word from a register to memory. The offset register value can optionally be shifted.
3908bool
3909EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3910{
3911#if 0
3912 if ConditionPassed() then
3913 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3914 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3915 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3916 address = if index then offset_addr else R[n];
3917 if t == 15 then // Only possible for encoding A1
3918 data = PCStoreValue();
3919 else
3920 data = R[t];
3921 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3922 MemU[address,4] = data;
3923 else // Can only occur before ARMv7
3924 MemU[address,4] = bits(32) UNKNOWN;
3925 if wback then R[n] = offset_addr;
3926#endif
3927
3928 bool success = false;
3929 const uint32_t opcode = OpcodeAsUnsigned (&success);
3930 if (!success)
3931 return false;
3932
3933 if (ConditionPassed())
3934 {
3935 const uint32_t addr_byte_size = GetAddressByteSize();
3936
3937 uint32_t t;
3938 uint32_t n;
3939 uint32_t m;
3940 ARM_ShifterType shift_t;
3941 uint32_t shift_n;
3942 bool index;
3943 bool add;
3944 bool wback;
3945
3946 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3947 switch (encoding)
3948 {
3949 case eEncodingT1:
3950 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3951 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3952 t = Bits32 (opcode, 2, 0);
3953 n = Bits32 (opcode, 5, 3);
3954 m = Bits32 (opcode, 8, 6);
3955
3956 // index = TRUE; add = TRUE; wback = FALSE;
3957 index = true;
3958 add = true;
3959 wback = false;
3960
3961 // (shift_t, shift_n) = (SRType_LSL, 0);
3962 shift_t = SRType_LSL;
3963 shift_n = 0;
3964 break;
3965
3966 case eEncodingT2:
3967 // if Rn == ’1111’ then UNDEFINED;
3968 if (Bits32 (opcode, 19, 16) == 15)
3969 return false;
3970
3971 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3972 t = Bits32 (opcode, 15, 12);
3973 n = Bits32 (opcode, 19, 16);
3974 m = Bits32 (opcode, 3, 0);
3975
3976 // index = TRUE; add = TRUE; wback = FALSE;
3977 index = true;
3978 add = true;
3979 wback = false;
3980
3981 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3982 shift_t = SRType_LSL;
3983 shift_n = Bits32 (opcode, 5, 4);
3984
3985 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3986 if ((t == 15) || (BadReg (m)))
3987 return false;
3988 break;
3989
3990 case eEncodingA1:
3991 {
3992 // if P == ’0’ && W == ’1’ then SEE STRT;
3993 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3994 t = Bits32 (opcode, 15, 12);
3995 n = Bits32 (opcode, 19, 16);
3996 m = Bits32 (opcode, 3, 0);
3997
3998 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3999 index = BitIsSet (opcode, 24);
4000 add = BitIsSet (opcode, 23);
4001 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4002
4003 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4004 uint32_t typ = Bits32 (opcode, 6, 5);
4005 uint32_t imm5 = Bits32 (opcode, 11, 7);
4006 shift_n = DecodeImmShift(typ, imm5, shift_t);
4007
4008 // if m == 15 then UNPREDICTABLE;
4009 if (m == 15)
4010 return false;
4011
4012 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4013 if (wback && ((n == 15) || (n == t)))
4014 return false;
4015
4016 break;
4017 }
4018 default:
4019 return false;
4020 }
4021
4022 addr_t offset_addr;
4023 addr_t address;
4024 int32_t offset = 0;
4025
4026 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4027 if (!success)
4028 return false;
4029
4030 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4031 if (!success)
4032 return false;
4033
4034 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004035 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004036
4037 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4038 if (add)
4039 offset_addr = base_address + offset;
4040 else
4041 offset_addr = base_address - offset;
4042
4043 // address = if index then offset_addr else R[n];
4044 if (index)
4045 address = offset_addr;
4046 else
4047 address = base_address;
4048
4049 uint32_t data;
4050 // if t == 15 then // Only possible for encoding A1
4051 if (t == 15)
4052 // data = PCStoreValue();
4053 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4054 else
4055 // data = R[t];
4056 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4057
4058 if (!success)
4059 return false;
4060
4061 EmulateInstruction::Context context;
4062 context.type = eContextRegisterStore;
4063
4064 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4065 if (UnalignedSupport ()
4066 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4067 || CurrentInstrSet() == eModeARM)
4068 {
4069 // MemU[address,4] = data;
4070
4071 Register base_reg;
4072 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4073
4074 Register data_reg;
4075 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4076
4077 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004078 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004079 return false;
4080
4081 }
4082 else
4083 // MemU[address,4] = bits(32) UNKNOWN;
4084 WriteBits32UnknownToMemory (address);
4085
4086 // if wback then R[n] = offset_addr;
4087 if (wback)
4088 {
4089 context.type = eContextRegisterLoad;
4090 context.SetAddress (offset_addr);
4091 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4092 return false;
4093 }
4094
4095 }
4096 return true;
4097}
Caroline Tice73a29de2011-02-16 20:22:22 +00004098
4099bool
4100EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4101{
4102#if 0
4103 if ConditionPassed() then
4104 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4105 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4106 address = if index then offset_addr else R[n];
4107 MemU[address,1] = R[t]<7:0>;
4108 if wback then R[n] = offset_addr;
4109#endif
4110
4111
4112 bool success = false;
4113 const uint32_t opcode = OpcodeAsUnsigned (&success);
4114 if (!success)
4115 return false;
4116
4117 if (ConditionPassed ())
4118 {
4119 uint32_t t;
4120 uint32_t n;
4121 uint32_t imm32;
4122 bool index;
4123 bool add;
4124 bool wback;
4125 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4126 switch (encoding)
4127 {
4128 case eEncodingT1:
4129 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4130 t = Bits32 (opcode, 2, 0);
4131 n = Bits32 (opcode, 5, 3);
4132 imm32 = Bits32 (opcode, 10, 6);
4133
4134 // index = TRUE; add = TRUE; wback = FALSE;
4135 index = true;
4136 add = true;
4137 wback = false;
4138 break;
4139
4140 case eEncodingT2:
4141 // if Rn == ’1111’ then UNDEFINED;
4142 if (Bits32 (opcode, 19, 16) == 15)
4143 return false;
4144
4145 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4146 t = Bits32 (opcode, 15, 12);
4147 n = Bits32 (opcode, 19, 16);
4148 imm32 = Bits32 (opcode, 11, 0);
4149
4150 // index = TRUE; add = TRUE; wback = FALSE;
4151 index = true;
4152 add = true;
4153 wback = false;
4154
4155 // if BadReg(t) then UNPREDICTABLE;
4156 if (BadReg (t))
4157 return false;
4158 break;
4159
4160 case eEncodingT3:
4161 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4162 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4163 if (Bits32 (opcode, 19, 16) == 15)
4164 return false;
4165
4166 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4167 t = Bits32 (opcode, 15, 12);
4168 n = Bits32 (opcode, 19, 16);
4169 imm32 = Bits32 (opcode, 7, 0);
4170
4171 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4172 index = BitIsSet (opcode, 10);
4173 add = BitIsSet (opcode, 9);
4174 wback = BitIsSet (opcode, 8);
4175
4176 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4177 if ((BadReg (t)) || (wback && (n == t)))
4178 return false;
4179 break;
4180
4181 default:
4182 return false;
4183 }
4184
4185 addr_t offset_addr;
4186 addr_t address;
4187 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4188 if (!success)
4189 return false;
4190
4191 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4192 if (add)
4193 offset_addr = base_address + imm32;
4194 else
4195 offset_addr = base_address - imm32;
4196
4197 // address = if index then offset_addr else R[n];
4198 if (index)
4199 address = offset_addr;
4200 else
4201 address = base_address;
4202
Caroline Ticecc96eb52011-02-17 19:20:40 +00004203 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004204 Register base_reg;
4205 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4206
4207 Register data_reg;
4208 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4209
4210 EmulateInstruction::Context context;
4211 context.type = eContextRegisterStore;
4212 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4213
4214 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4215 if (!success)
4216 return false;
4217
4218 data = Bits32 (data, 7, 0);
4219
Caroline Ticecc96eb52011-02-17 19:20:40 +00004220 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004221 return false;
4222
4223 // if wback then R[n] = offset_addr;
4224 if (wback)
4225 {
4226 context.type = eContextRegisterLoad;
4227 context.SetAddress (offset_addr);
4228 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4229 return false;
4230 }
4231
4232 }
4233
4234 return true;
4235}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004236
Johnny Chen157b9592011-02-18 21:13:05 +00004237// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4238// and writes the result to the destination register. It can optionally update the condition flags
4239// based on the result.
4240bool
4241EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4242{
4243#if 0
4244 // ARM pseudo code...
4245 if ConditionPassed() then
4246 EncodingSpecificOperations();
4247 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4248 if d == 15 then // Can only occur for ARM encoding
4249 ALUWritePC(result); // setflags is always FALSE here
4250 else
4251 R[d] = result;
4252 if setflags then
4253 APSR.N = result<31>;
4254 APSR.Z = IsZeroBit(result);
4255 APSR.C = carry;
4256 APSR.V = overflow;
4257#endif
4258
4259 bool success = false;
4260 const uint32_t opcode = OpcodeAsUnsigned (&success);
4261 if (!success)
4262 return false;
4263
4264 if (ConditionPassed())
4265 {
4266 uint32_t Rd, Rn;
4267 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4268 bool setflags;
4269 switch (encoding)
4270 {
4271 case eEncodingT1:
4272 Rd = Bits32(opcode, 11, 8);
4273 Rn = Bits32(opcode, 19, 16);
4274 setflags = BitIsSet(opcode, 20);
4275 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4276 if (BadReg(Rd) || BadReg(Rn))
4277 return false;
4278 break;
4279 case eEncodingA1:
4280 Rd = Bits32(opcode, 15, 12);
4281 Rn = Bits32(opcode, 19, 16);
4282 setflags = BitIsSet(opcode, 20);
4283 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4284 // TODO: Emulate SUBS PC, LR and related instructions.
4285 if (Rd == 15 && setflags)
4286 return false;
4287 break;
4288 default:
4289 return false;
4290 }
4291
4292 // Read the first operand.
4293 int32_t val1 = ReadCoreReg(Rn, &success);
4294 if (!success)
4295 return false;
4296
4297 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4298
4299 EmulateInstruction::Context context;
4300 context.type = EmulateInstruction::eContextImmediate;
4301 context.SetNoArgs ();
4302
4303 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4304 return false;
4305 }
4306 return true;
4307}
4308
4309// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4310// register value, and writes the result to the destination register. It can optionally update the
4311// condition flags based on the result.
4312bool
4313EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4314{
4315#if 0
4316 // ARM pseudo code...
4317 if ConditionPassed() then
4318 EncodingSpecificOperations();
4319 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4320 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4321 if d == 15 then // Can only occur for ARM encoding
4322 ALUWritePC(result); // setflags is always FALSE here
4323 else
4324 R[d] = result;
4325 if setflags then
4326 APSR.N = result<31>;
4327 APSR.Z = IsZeroBit(result);
4328 APSR.C = carry;
4329 APSR.V = overflow;
4330#endif
4331
4332 bool success = false;
4333 const uint32_t opcode = OpcodeAsUnsigned (&success);
4334 if (!success)
4335 return false;
4336
4337 if (ConditionPassed())
4338 {
4339 uint32_t Rd, Rn, Rm;
4340 ARM_ShifterType shift_t;
4341 uint32_t shift_n; // the shift applied to the value read from Rm
4342 bool setflags;
4343 switch (encoding)
4344 {
4345 case eEncodingT1:
4346 Rd = Rn = Bits32(opcode, 2, 0);
4347 Rm = Bits32(opcode, 5, 3);
4348 setflags = !InITBlock();
4349 shift_t = SRType_LSL;
4350 shift_n = 0;
4351 case eEncodingT2:
4352 Rd = Bits32(opcode, 11, 8);
4353 Rn = Bits32(opcode, 19, 16);
4354 Rm = Bits32(opcode, 3, 0);
4355 setflags = BitIsSet(opcode, 20);
4356 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
4357 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4358 return false;
4359 break;
4360 case eEncodingA1:
4361 Rd = Bits32(opcode, 15, 12);
4362 Rn = Bits32(opcode, 19, 16);
4363 Rm = Bits32(opcode, 3, 0);
4364 setflags = BitIsSet(opcode, 20);
4365 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4366 // TODO: Emulate SUBS PC, LR and related instructions.
4367 if (Rd == 15 && setflags)
4368 return false;
4369 break;
4370 default:
4371 return false;
4372 }
4373
4374 // Read the first operand.
4375 int32_t val1 = ReadCoreReg(Rn, &success);
4376 if (!success)
4377 return false;
4378
4379 // Read the second operand.
4380 int32_t val2 = ReadCoreReg(Rm, &success);
4381 if (!success)
4382 return false;
4383
4384 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4385 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4386
4387 EmulateInstruction::Context context;
4388 context.type = EmulateInstruction::eContextImmediate;
4389 context.SetNoArgs ();
4390
4391 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4392 return false;
4393 }
4394 return true;
4395}
4396
Johnny Chene97c0d52011-02-18 19:32:20 +00004397// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4398// to the destination register. It can optionally update the condition flags based on the result.
4399bool
4400EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4401{
4402#if 0
4403 // ARM pseudo code...
4404 if ConditionPassed() then
4405 EncodingSpecificOperations();
4406 result = R[n] AND imm32;
4407 if d == 15 then // Can only occur for ARM encoding
4408 ALUWritePC(result); // setflags is always FALSE here
4409 else
4410 R[d] = result;
4411 if setflags then
4412 APSR.N = result<31>;
4413 APSR.Z = IsZeroBit(result);
4414 APSR.C = carry;
4415 // APSR.V unchanged
4416#endif
4417
4418 bool success = false;
4419 const uint32_t opcode = OpcodeAsUnsigned (&success);
4420 if (!success)
4421 return false;
4422
4423 if (ConditionPassed())
4424 {
4425 uint32_t Rd, Rn;
4426 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4427 bool setflags;
4428 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4429 switch (encoding)
4430 {
4431 case eEncodingT1:
4432 Rd = Bits32(opcode, 11, 8);
4433 Rn = Bits32(opcode, 19, 16);
4434 setflags = BitIsSet(opcode, 20);
4435 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
4436 // TODO: Emulate TST (immediate)
4437 if (Rd == 15 && setflags)
4438 return false;
4439 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4440 return false;
4441 break;
4442 case eEncodingA1:
4443 Rd = Bits32(opcode, 15, 12);
4444 Rn = Bits32(opcode, 19, 16);
4445 setflags = BitIsSet(opcode, 20);
4446 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4447 // TODO: Emulate SUBS PC, LR and related instructions.
4448 if (Rd == 15 && setflags)
4449 return false;
4450 break;
4451 default:
4452 return false;
4453 }
4454
Johnny Chene97c0d52011-02-18 19:32:20 +00004455 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004456 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004457 if (!success)
4458 return false;
4459
4460 uint32_t result = val1 & imm32;
4461
4462 EmulateInstruction::Context context;
4463 context.type = EmulateInstruction::eContextImmediate;
4464 context.SetNoArgs ();
4465
4466 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4467 return false;
4468 }
4469 return true;
4470}
4471
4472// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4473// and writes the result to the destination register. It can optionally update the condition flags
4474// based on the result.
4475bool
4476EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4477{
4478#if 0
4479 // ARM pseudo code...
4480 if ConditionPassed() then
4481 EncodingSpecificOperations();
4482 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4483 result = R[n] AND shifted;
4484 if d == 15 then // Can only occur for ARM encoding
4485 ALUWritePC(result); // setflags is always FALSE here
4486 else
4487 R[d] = result;
4488 if setflags then
4489 APSR.N = result<31>;
4490 APSR.Z = IsZeroBit(result);
4491 APSR.C = carry;
4492 // APSR.V unchanged
4493#endif
4494
4495 bool success = false;
4496 const uint32_t opcode = OpcodeAsUnsigned (&success);
4497 if (!success)
4498 return false;
4499
4500 if (ConditionPassed())
4501 {
4502 uint32_t Rd, Rn, Rm;
4503 ARM_ShifterType shift_t;
4504 uint32_t shift_n; // the shift applied to the value read from Rm
4505 bool setflags;
4506 uint32_t carry;
4507 switch (encoding)
4508 {
4509 case eEncodingT1:
4510 Rd = Rn = Bits32(opcode, 2, 0);
4511 Rm = Bits32(opcode, 5, 3);
4512 setflags = !InITBlock();
4513 shift_t = SRType_LSL;
4514 shift_n = 0;
4515 case eEncodingT2:
4516 Rd = Bits32(opcode, 11, 8);
4517 Rn = Bits32(opcode, 19, 16);
4518 Rm = Bits32(opcode, 3, 0);
4519 setflags = BitIsSet(opcode, 20);
Johnny Chen157b9592011-02-18 21:13:05 +00004520 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004521 // TODO: Emulate TST (register)
4522 if (Rd == 15 && setflags)
4523 return false;
4524 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4525 return false;
4526 break;
4527 case eEncodingA1:
4528 Rd = Bits32(opcode, 15, 12);
4529 Rn = Bits32(opcode, 19, 16);
4530 Rm = Bits32(opcode, 3, 0);
4531 setflags = BitIsSet(opcode, 20);
4532 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4533 // TODO: Emulate SUBS PC, LR and related instructions.
4534 if (Rd == 15 && setflags)
4535 return false;
4536 break;
4537 default:
4538 return false;
4539 }
4540
Johnny Chene97c0d52011-02-18 19:32:20 +00004541 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004542 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004543 if (!success)
4544 return false;
4545
4546 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004547 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004548 if (!success)
4549 return false;
4550
4551 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4552 uint32_t result = val1 & shifted;
4553
4554 EmulateInstruction::Context context;
4555 context.type = EmulateInstruction::eContextImmediate;
4556 context.SetNoArgs ();
4557
4558 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4559 return false;
4560 }
4561 return true;
4562}
4563
Caroline Tice4d729c52011-02-18 00:55:53 +00004564// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
Johnny Chene92b27c2011-02-18 01:26:39 +00004565// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Tice4d729c52011-02-18 00:55:53 +00004566bool
4567EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4568{
4569#if 0
4570 if ConditionPassed() then
4571 EncodingSpecificOperations();
4572 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4573 address = if index then offset_addr else R[n];
4574 data = MemU[address,4];
4575 if wback then R[n] = offset_addr;
4576 if t == 15 then
4577 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4578 elsif UnalignedSupport() || address<1:0> = ’00’ then
4579 R[t] = data;
4580 else // Can only apply before ARMv7
4581 R[t] = ROR(data, 8*UInt(address<1:0>));
4582#endif
4583
4584 bool success = false;
4585 const uint32_t opcode = OpcodeAsUnsigned (&success);
4586 if (!success)
4587 return false;
4588
4589 if (ConditionPassed ())
4590 {
4591 const uint32_t addr_byte_size = GetAddressByteSize();
4592
4593 uint32_t t;
4594 uint32_t n;
4595 uint32_t imm32;
4596 bool index;
4597 bool add;
4598 bool wback;
4599
4600 switch (encoding)
4601 {
4602 case eEncodingA1:
4603 // if Rn == ’1111’ then SEE LDR (literal);
4604 // if P == ’0’ && W == ’1’ then SEE LDRT;
4605 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4606 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4607 t = Bits32 (opcode, 15, 12);
4608 n = Bits32 (opcode, 19, 16);
4609 imm32 = Bits32 (opcode, 11, 0);
4610
4611 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4612 index = BitIsSet (opcode, 24);
4613 add = BitIsSet (opcode, 23);
4614 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4615
4616 // if wback && n == t then UNPREDICTABLE;
4617 if (wback && (n == t))
4618 return false;
4619
4620 break;
4621
4622 default:
4623 return false;
4624 }
4625
4626 addr_t address;
4627 addr_t offset_addr;
4628 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4629 if (!success)
4630 return false;
4631
4632 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4633 if (add)
4634 offset_addr = base_address + imm32;
4635 else
4636 offset_addr = base_address - imm32;
4637
4638 // address = if index then offset_addr else R[n];
4639 if (index)
4640 address = offset_addr;
4641 else
4642 address = base_address;
4643
4644 // data = MemU[address,4];
4645
4646 Register base_reg;
4647 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4648
4649 EmulateInstruction::Context context;
4650 context.type = eContextRegisterLoad;
4651 context.SetRegisterPlusOffset (base_reg, address - base_address);
4652
4653 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4654 if (!success)
4655 return false;
4656
4657 // if wback then R[n] = offset_addr;
4658 if (wback)
4659 {
4660 context.type = eContextAdjustBaseRegister;
4661 context.SetAddress (offset_addr);
4662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4663 return false;
4664 }
4665
4666 // if t == 15 then
4667 if (t == 15)
4668 {
4669 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4670 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4671 {
4672 // LoadWritePC (data);
4673 context.type = eContextRegisterLoad;
4674 context.SetRegisterPlusOffset (base_reg, address - base_address);
4675 LoadWritePC (context, data);
4676 }
4677 else
4678 return false;
4679 }
4680 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4681 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4682 {
4683 // R[t] = data;
4684 context.type = eContextRegisterLoad;
4685 context.SetRegisterPlusOffset (base_reg, address - base_address);
4686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4687 return false;
4688 }
4689 // else // Can only apply before ARMv7
4690 else
4691 {
4692 // R[t] = ROR(data, 8*UInt(address<1:0>));
4693 data = ROR (data, Bits32 (address, 1, 0));
4694 context.type = eContextRegisterLoad;
4695 context.SetImmediate (data);
4696 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4697 return false;
4698 }
4699
4700 }
4701 return true;
4702}
4703
Caroline Ticefe479112011-02-18 18:52:37 +00004704// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4705// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4706bool
4707EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4708{
4709#if 0
4710 if ConditionPassed() then
4711 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4712 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4713 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4714 address = if index then offset_addr else R[n];
4715 data = MemU[address,4];
4716 if wback then R[n] = offset_addr;
4717 if t == 15 then
4718 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4719 elsif UnalignedSupport() || address<1:0> = ’00’ then
4720 R[t] = data;
4721 else // Can only apply before ARMv7
4722 if CurrentInstrSet() == InstrSet_ARM then
4723 R[t] = ROR(data, 8*UInt(address<1:0>));
4724 else
4725 R[t] = bits(32) UNKNOWN;
4726#endif
4727
4728 bool success = false;
4729 const uint32_t opcode = OpcodeAsUnsigned (&success);
4730 if (!success)
4731 return false;
4732
4733 if (ConditionPassed ())
4734 {
4735 const uint32_t addr_byte_size = GetAddressByteSize();
4736
4737 uint32_t t;
4738 uint32_t n;
4739 uint32_t m;
4740 bool index;
4741 bool add;
4742 bool wback;
4743 ARM_ShifterType shift_t;
4744 uint32_t shift_n;
4745
4746 switch (encoding)
4747 {
4748 case eEncodingT1:
4749 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4750 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4751 t = Bits32 (opcode, 2, 0);
4752 n = Bits32 (opcode, 5, 3);
4753 m = Bits32 (opcode, 8, 6);
4754
4755 // index = TRUE; add = TRUE; wback = FALSE;
4756 index = true;
4757 add = true;
4758 wback = false;
4759
4760 // (shift_t, shift_n) = (SRType_LSL, 0);
4761 shift_t = SRType_LSL;
4762 shift_n = 0;
4763
4764 break;
4765
4766 case eEncodingT2:
4767 // if Rn == ’1111’ then SEE LDR (literal);
4768 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4769 t = Bits32 (opcode, 15, 12);
4770 n = Bits32 (opcode, 19, 16);
4771 m = Bits32 (opcode, 3, 0);
4772
4773 // index = TRUE; add = TRUE; wback = FALSE;
4774 index = true;
4775 add = true;
4776 wback = false;
4777
4778 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4779 shift_t = SRType_LSL;
4780 shift_n = Bits32 (opcode, 5, 4);
4781
4782 // if BadReg(m) then UNPREDICTABLE;
4783 if (BadReg (m))
4784 return false;
4785
4786 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4787 if ((t == 15) && InITBlock() && !LastInITBlock())
4788 return false;
4789
4790 break;
4791
4792 case eEncodingA1:
4793 {
4794 // if P == ’0’ && W == ’1’ then SEE LDRT;
4795 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4796 t = Bits32 (opcode, 15, 12);
4797 n = Bits32 (opcode, 19, 16);
4798 m = Bits32 (opcode, 3, 0);
4799
4800 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4801 index = BitIsSet (opcode, 24);
4802 add = BitIsSet (opcode, 23);
4803 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4804
4805 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4806 uint32_t type = Bits32 (opcode, 6, 5);
4807 uint32_t imm5 = Bits32 (opcode, 11, 7);
4808 shift_n = DecodeImmShift (type, imm5, shift_t);
4809
4810 // if m == 15 then UNPREDICTABLE;
4811 if (m == 15)
4812 return false;
4813
4814 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4815 if (wback && ((n == 15) || (n == t)))
4816 return false;
4817 }
4818 break;
4819
4820
4821 default:
4822 return false;
4823 }
4824
4825 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4826 if (!success)
4827 return false;
4828
4829 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4830 if (!success)
4831 return false;
4832
4833 addr_t offset_addr;
4834 addr_t address;
4835
4836 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
4837 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
4838
4839 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4840 if (add)
4841 offset_addr = Rn + offset;
4842 else
4843 offset_addr = Rn - offset;
4844
4845 // address = if index then offset_addr else R[n];
4846 if (index)
4847 address = offset_addr;
4848 else
4849 address = Rn;
4850
4851 // data = MemU[address,4];
4852 Register base_reg;
4853 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4854
4855 EmulateInstruction::Context context;
4856 context.type = eContextRegisterLoad;
4857 context.SetRegisterPlusOffset (base_reg, address - Rn);
4858
4859 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4860 if (!success)
4861 return false;
4862
4863 // if wback then R[n] = offset_addr;
4864 if (wback)
4865 {
4866 context.type = eContextAdjustBaseRegister;
4867 context.SetAddress (offset_addr);
4868 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4869 return false;
4870 }
4871
4872 // if t == 15 then
4873 if (t == 15)
4874 {
4875 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4876 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4877 {
4878 context.type = eContextRegisterLoad;
4879 context.SetRegisterPlusOffset (base_reg, address - Rn);
4880 LoadWritePC (context, data);
4881 }
4882 else
4883 return false;
4884 }
4885 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4886 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4887 {
4888 // R[t] = data;
4889 context.type = eContextRegisterLoad;
4890 context.SetRegisterPlusOffset (base_reg, address - Rn);
4891 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4892 return false;
4893 }
4894 else // Can only apply before ARMv7
4895 {
4896 // if CurrentInstrSet() == InstrSet_ARM then
4897 if (CurrentInstrSet () == eModeARM)
4898 {
4899 // R[t] = ROR(data, 8*UInt(address<1:0>));
4900 data = ROR (data, Bits32 (address, 1, 0));
4901 context.type = eContextRegisterLoad;
4902 context.SetImmediate (data);
4903 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4904 return false;
4905 }
4906 else
4907 {
4908 // R[t] = bits(32) UNKNOWN;
4909 WriteBits32Unknown (t);
4910 }
4911 }
4912 }
4913 return true;
4914}
Caroline Tice21b604b2011-02-18 21:06:04 +00004915
4916// LDRB (immediate, Thumb)
4917bool
4918EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
4919{
4920#if 0
4921 if ConditionPassed() then
4922 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4923 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4924 address = if index then offset_addr else R[n];
4925 R[t] = ZeroExtend(MemU[address,1], 32);
4926 if wback then R[n] = offset_addr;
4927#endif
4928
4929 bool success = false;
4930 const uint32_t opcode = OpcodeAsUnsigned (&success);
4931 if (!success)
4932 return false;
4933
4934 if (ConditionPassed ())
4935 {
4936 uint32_t t;
4937 uint32_t n;
4938 uint32_t imm32;
4939 bool index;
4940 bool add;
4941 bool wback;
4942
4943 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4944 switch (encoding)
4945 {
4946 case eEncodingT1:
4947 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4948 t = Bits32 (opcode, 2, 0);
4949 n = Bits32 (opcode, 5, 3);
4950 imm32 = Bits32 (opcode, 10, 6);
4951
4952 // index = TRUE; add = TRUE; wback = FALSE;
4953 index = true;
4954 add = true;
4955 wback= false;
4956
4957 break;
4958
4959 case eEncodingT2:
4960 // if Rt == ’1111’ then SEE PLD;
4961 // if Rn == ’1111’ then SEE LDRB (literal);
4962 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4963 t = Bits32 (opcode, 15, 12);
4964 n = Bits32 (opcode, 19, 16);
4965 imm32 = Bits32 (opcode, 11, 0);
4966
4967 // index = TRUE; add = TRUE; wback = FALSE;
4968 index = true;
4969 add = true;
4970 wback = false;
4971
4972 // if t == 13 then UNPREDICTABLE;
4973 if (t == 13)
4974 return false;
4975
4976 break;
4977
4978 case eEncodingT3:
4979 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
4980 // if Rn == ’1111’ then SEE LDRB (literal);
4981 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
4982 // if P == ’0’ && W == ’0’ then UNDEFINED;
4983 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
4984 return false;
4985
4986 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4987 t = Bits32 (opcode, 15, 12);
4988 n = Bits32 (opcode, 19, 16);
4989 imm32 = Bits32 (opcode, 7, 0);
4990
4991 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4992 index = BitIsSet (opcode, 10);
4993 add = BitIsSet (opcode, 9);
4994 wback = BitIsSet (opcode, 8);
4995
4996 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
4997 if (BadReg (t) || (wback && (n == t)))
4998 return false;
4999
5000 break;
5001
5002 default:
5003 return false;
5004 }
5005
5006 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5007 if (!success)
5008 return false;
5009
5010 addr_t address;
5011 addr_t offset_addr;
5012
5013 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5014 if (add)
5015 offset_addr = Rn + imm32;
5016 else
5017 offset_addr = Rn - imm32;
5018
5019 // address = if index then offset_addr else R[n];
5020 if (index)
5021 address = offset_addr;
5022 else
5023 address = Rn;
5024
5025 // R[t] = ZeroExtend(MemU[address,1], 32);
5026 Register base_reg;
5027 Register data_reg;
5028 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5029 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5030
5031 EmulateInstruction::Context context;
5032 context.type = eContextRegisterLoad;
5033 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5034
5035 uint64_t data = MemURead (context, address, 1, 0, &success);
5036 if (!success)
5037 return false;
5038
5039 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5040 return false;
5041
5042 // if wback then R[n] = offset_addr;
5043 if (wback)
5044 {
5045 context.type = eContextAdjustBaseRegister;
5046 context.SetAddress (offset_addr);
5047 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5048 return false;
5049 }
5050 }
5051 return true;
5052}
Caroline Ticef55261f2011-02-18 22:24:22 +00005053
5054// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5055// zero-extends it to form a 32-bit word and writes it to a register.
5056bool
5057EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5058{
5059#if 0
5060 if ConditionPassed() then
5061 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5062 base = Align(PC,4);
5063 address = if add then (base + imm32) else (base - imm32);
5064 R[t] = ZeroExtend(MemU[address,1], 32);
5065#endif
5066
5067 bool success = false;
5068 const uint32_t opcode = OpcodeAsUnsigned (&success);
5069 if (!success)
5070 return false;
5071
5072 if (ConditionPassed ())
5073 {
5074 uint32_t t;
5075 uint32_t imm32;
5076 bool add;
5077 switch (encoding)
5078 {
5079 case eEncodingT1:
5080 // if Rt == ’1111’ then SEE PLD;
5081 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5082 t = Bits32 (opcode, 15, 12);
5083 imm32 = Bits32 (opcode, 11, 0);
5084 add = BitIsSet (opcode, 23);
5085
5086 // if t == 13 then UNPREDICTABLE;
5087 if (t == 13)
5088 return false;
5089
5090 break;
5091
5092 case eEncodingA1:
5093 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5094 t = Bits32 (opcode, 15, 12);
5095 imm32 = Bits32 (opcode, 11, 0);
5096 add = BitIsSet (opcode, 23);
5097
5098 // if t == 15 then UNPREDICTABLE;
5099 if (t == 15)
5100 return false;
5101 break;
5102
5103 default:
5104 return false;
5105 }
5106
5107 // base = Align(PC,4);
5108 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5109 if (!success)
5110 return false;
5111
5112 uint32_t base = AlignPC (pc_val);
5113
5114 addr_t address;
5115 // address = if add then (base + imm32) else (base - imm32);
5116 if (add)
5117 address = base + imm32;
5118 else
5119 address = base - imm32;
5120
5121 // R[t] = ZeroExtend(MemU[address,1], 32);
5122 EmulateInstruction::Context context;
5123 context.type = eContextRelativeBranchImmediate;
5124 context.SetImmediate (address - base);
5125
5126 uint64_t data = MemURead (context, address, 1, 0, &success);
5127 if (!success)
5128 return false;
5129
5130 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5131 return false;
5132 }
5133 return true;
5134}
Caroline Ticefe479112011-02-18 18:52:37 +00005135
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005136EmulateInstructionARM::ARMOpcode*
5137EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00005138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005139 static ARMOpcode
5140 g_arm_opcodes[] =
5141 {
5142 //----------------------------------------------------------------------
5143 // Prologue instructions
5144 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00005145
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005146 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005147 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5148 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00005149
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005150 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005151 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005152 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00005153 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00005154 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
5155 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005156 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00005157
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005158 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005159 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00005160
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005161 // push one register
5162 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00005163 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00005164
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005165 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00005166 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5167 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00005168
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005169 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00005170 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005171 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00005172
Johnny Chen9f687722011-02-18 00:02:28 +00005173 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5174 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00005175 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005176 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
5177
5178 //----------------------------------------------------------------------
5179 // Supervisor Call (previously Software Interrupt)
5180 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005181 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
5182
5183 //----------------------------------------------------------------------
5184 // Branch instructions
5185 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005186 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00005187 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
5188 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5189 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5190 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005191 // for example, "bx lr"
5192 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005193
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005194 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00005195 // Data-processing instructions
5196 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005197 // adc (immediate)
5198 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
5199 // adc (register)
5200 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005201 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005202 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005203 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005204 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005205 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005206 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005207 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005208 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen28070c32011-02-12 01:27:26 +00005209 // move bitwise not
Johnny Chen157b9592011-02-18 21:13:05 +00005210 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005211 // asr (immediate)
5212 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005213 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00005214 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005215 // lsl (immediate)
5216 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
5217 // lsl (register)
5218 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
5219 // lsr (immediate)
5220 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
5221 // lsr (register)
5222 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005223 // rrx is a special case encoding of ror (immediate)
5224 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
5225 // ror (immediate)
5226 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
5227 // ror (register)
5228 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005229
5230 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005231 // Load instructions
5232 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00005233 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00005234 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00005235 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00005236 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00005237 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00005238 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00005239 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Ticefa172202011-02-11 22:49:54 +00005240
5241 //----------------------------------------------------------------------
5242 // Store instructions
5243 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00005244 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005245 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00005246 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00005247 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
5248 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00005249
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005250
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005251 };
5252 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
5253
5254 for (size_t i=0; i<k_num_arm_opcodes; ++i)
5255 {
5256 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
5257 return &g_arm_opcodes[i];
5258 }
5259 return NULL;
5260}
Greg Clayton64c84432011-01-21 22:02:52 +00005261
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005262
5263EmulateInstructionARM::ARMOpcode*
5264EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00005265{
Johnny Chenfdd179e2011-01-31 20:09:28 +00005266
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005267 static ARMOpcode
5268 g_thumb_opcodes[] =
5269 {
5270 //----------------------------------------------------------------------
5271 // Prologue instructions
5272 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00005273
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005274 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005275 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5276 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
5277 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00005278
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005279 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005280 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005281 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00005282 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005283 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00005284 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00005285
Johnny Chen864a8e82011-02-18 00:07:39 +00005286 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00005287 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00005288
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005289 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005290 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
5291 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
5292 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
5293 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005294
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005295 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00005296 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5297 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005298
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005299 //----------------------------------------------------------------------
5300 // Epilogue instructions
5301 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00005302
Johnny Chen864a8e82011-02-18 00:07:39 +00005303 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00005304 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5305 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
5306 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00005307 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
5308 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005309
5310 //----------------------------------------------------------------------
5311 // Supervisor Call (previously Software Interrupt)
5312 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00005313 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
5314
5315 //----------------------------------------------------------------------
5316 // If Then makes up to four following instructions conditional.
5317 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005318 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
5319
5320 //----------------------------------------------------------------------
5321 // Branch instructions
5322 //----------------------------------------------------------------------
5323 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
5324 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
5325 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00005326 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005327 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00005328 // J1 == J2 == 1
5329 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5330 // J1 == J2 == 1
5331 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5332 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005333 // for example, "bx lr"
5334 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00005335 // compare and branch
5336 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00005337 // table branch byte
5338 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
5339 // table branch halfword
5340 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005341
5342 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00005343 // Data-processing instructions
5344 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005345 // adc (immediate)
5346 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
5347 // adc (register)
5348 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
5349 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
5350 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00005351 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005352 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00005353 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005354 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005355 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005356 // and (register)
5357 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
5358 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen338bf542011-02-10 19:29:03 +00005359 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00005360 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00005361 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00005362 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00005363 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005364 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
5365 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005366 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005367 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00005368 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005369 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005370 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005371 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005372 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005373 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005374 // asr (immediate)
5375 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00005376 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00005377 // asr (register)
5378 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
5379 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005380 // lsl (immediate)
5381 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
5382 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
5383 // lsl (register)
5384 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
5385 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
5386 // lsr (immediate)
5387 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
5388 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
5389 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00005390 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005391 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005392 // rrx is a special case encoding of ror (immediate)
5393 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
5394 // ror (immediate)
5395 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
5396 // ror (register)
5397 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
5398 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005399
5400 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005401 // Load instructions
5402 //----------------------------------------------------------------------
5403 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00005404 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00005405 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00005406 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
5407 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00005408 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00005409 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
5410 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00005411 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
5412 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
5413 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00005414 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Ticefa172202011-02-11 22:49:54 +00005415
5416 //----------------------------------------------------------------------
5417 // Store instructions
5418 //----------------------------------------------------------------------
5419 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005420 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00005421 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00005422 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
5423 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
5424 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
5425 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
5426 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
5427 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
5428 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
5429 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
5430 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005431 };
5432
5433 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
5434 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
5435 {
5436 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
5437 return &g_thumb_opcodes[i];
5438 }
5439 return NULL;
5440}
Greg Clayton64c84432011-01-21 22:02:52 +00005441
Greg Clayton31e2a382011-01-30 20:03:56 +00005442bool
Greg Clayton395fc332011-02-15 21:59:32 +00005443EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00005444{
5445 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00005446 const char *arch_cstr = arch.AsCString ();
5447 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00005448 {
Greg Clayton395fc332011-02-15 21:59:32 +00005449 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
5450 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
5451 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
5452 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
5453 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
5454 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
5455 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
5456 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
5457 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
5458 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00005459 }
5460 return m_arm_isa != 0;
5461}
5462
5463
Greg Clayton64c84432011-01-21 22:02:52 +00005464bool
5465EmulateInstructionARM::ReadInstruction ()
5466{
5467 bool success = false;
5468 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
5469 if (success)
5470 {
5471 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
5472 if (success)
5473 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00005474 Context read_inst_context;
5475 read_inst_context.type = eContextReadOpcode;
5476 read_inst_context.SetNoArgs ();
5477
Greg Clayton64c84432011-01-21 22:02:52 +00005478 if (m_inst_cpsr & MASK_CPSR_T)
5479 {
5480 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005481 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005482
5483 if (success)
5484 {
5485 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
5486 {
5487 m_inst.opcode_type = eOpcode16;
5488 m_inst.opcode.inst16 = thumb_opcode;
5489 }
5490 else
5491 {
5492 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005493 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005494 }
5495 }
5496 }
5497 else
5498 {
5499 m_inst_mode = eModeARM;
5500 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005501 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005502 }
5503 }
5504 }
5505 if (!success)
5506 {
5507 m_inst_mode = eModeInvalid;
5508 m_inst_pc = LLDB_INVALID_ADDRESS;
5509 }
5510 return success;
5511}
5512
Johnny Chenee9b1f72011-02-09 01:00:31 +00005513uint32_t
5514EmulateInstructionARM::ArchVersion ()
5515{
5516 return m_arm_isa;
5517}
5518
Greg Clayton64c84432011-01-21 22:02:52 +00005519bool
5520EmulateInstructionARM::ConditionPassed ()
5521{
5522 if (m_inst_cpsr == 0)
5523 return false;
5524
5525 const uint32_t cond = CurrentCond ();
5526
5527 if (cond == UINT32_MAX)
5528 return false;
5529
5530 bool result = false;
5531 switch (UnsignedBits(cond, 3, 1))
5532 {
5533 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
5534 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
5535 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
5536 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
5537 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
5538 case 5:
5539 {
5540 bool n = (m_inst_cpsr & MASK_CPSR_N);
5541 bool v = (m_inst_cpsr & MASK_CPSR_V);
5542 result = n == v;
5543 }
5544 break;
5545 case 6:
5546 {
5547 bool n = (m_inst_cpsr & MASK_CPSR_N);
5548 bool v = (m_inst_cpsr & MASK_CPSR_V);
5549 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
5550 }
5551 break;
5552 case 7:
5553 result = true;
5554 break;
5555 }
5556
5557 if (cond & 1)
5558 result = !result;
5559 return result;
5560}
5561
Johnny Chen9ee056b2011-02-08 00:06:35 +00005562uint32_t
5563EmulateInstructionARM::CurrentCond ()
5564{
5565 switch (m_inst_mode)
5566 {
5567 default:
5568 case eModeInvalid:
5569 break;
5570
5571 case eModeARM:
5572 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
5573
5574 case eModeThumb:
5575 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
5576 // 'cond' field of the encoding.
5577 if (m_inst.opcode_type == eOpcode16 &&
5578 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
5579 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
5580 {
5581 return Bits32(m_inst.opcode.inst16, 11, 7);
5582 }
5583 else if (m_inst.opcode_type == eOpcode32 &&
5584 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
5585 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
5586 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
5587 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
5588 {
5589 return Bits32(m_inst.opcode.inst32, 25, 22);
5590 }
5591
5592 return m_it_session.GetCond();
5593 }
5594 return UINT32_MAX; // Return invalid value
5595}
5596
Johnny Chen9ee056b2011-02-08 00:06:35 +00005597bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00005598EmulateInstructionARM::InITBlock()
5599{
5600 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
5601}
5602
5603bool
5604EmulateInstructionARM::LastInITBlock()
5605{
5606 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
5607}
5608
5609bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00005610EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
5611{
5612 addr_t target;
5613
Johnny Chenee9b1f72011-02-09 01:00:31 +00005614 // Check the current instruction set.
5615 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005616 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005617 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00005618 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005619
Johnny Chen9ee056b2011-02-08 00:06:35 +00005620 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005621 return false;
5622
5623 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005624}
5625
5626// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
5627bool
Johnny Chen668b4512011-02-15 21:08:58 +00005628EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005629{
5630 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00005631 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
5632 // we want to record it and issue a WriteRegister callback so the clients
5633 // can track the mode changes accordingly.
5634 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005635
5636 if (BitIsSet(addr, 0))
5637 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005638 if (CurrentInstrSet() != eModeThumb)
5639 {
5640 SelectInstrSet(eModeThumb);
5641 cpsr_changed = true;
5642 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005643 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00005644 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005645 }
5646 else if (BitIsClear(addr, 1))
5647 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005648 if (CurrentInstrSet() != eModeARM)
5649 {
5650 SelectInstrSet(eModeARM);
5651 cpsr_changed = true;
5652 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005653 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00005654 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005655 }
5656 else
5657 return false; // address<1:0> == '10' => UNPREDICTABLE
5658
Johnny Chen0f309db2011-02-09 19:11:32 +00005659 if (cpsr_changed)
5660 {
Johnny Chen558133b2011-02-09 23:59:17 +00005661 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00005662 return false;
5663 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005664 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005665 return false;
5666
5667 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005668}
Greg Clayton64c84432011-01-21 22:02:52 +00005669
Johnny Chenee9b1f72011-02-09 01:00:31 +00005670// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
5671bool
Johnny Chen668b4512011-02-15 21:08:58 +00005672EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00005673{
5674 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00005675 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00005676 else
5677 return BranchWritePC((const Context)context, addr);
5678}
5679
Johnny Chen26863dc2011-02-09 23:43:29 +00005680// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
5681bool
Johnny Chen668b4512011-02-15 21:08:58 +00005682EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00005683{
5684 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00005685 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00005686 else
5687 return BranchWritePC((const Context)context, addr);
5688}
5689
Johnny Chenee9b1f72011-02-09 01:00:31 +00005690EmulateInstructionARM::Mode
5691EmulateInstructionARM::CurrentInstrSet ()
5692{
5693 return m_inst_mode;
5694}
5695
5696// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00005697// ReadInstruction() is performed. This function has a side effect of updating
5698// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00005699bool
5700EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
5701{
Johnny Chen558133b2011-02-09 23:59:17 +00005702 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005703 switch (arm_or_thumb)
5704 {
5705 default:
5706 return false;
5707 eModeARM:
5708 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005709 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005710 break;
5711 eModeThumb:
5712 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005713 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005714 break;
5715 }
5716 return true;
5717}
5718
Johnny Chenef21b592011-02-10 01:52:38 +00005719// This function returns TRUE if the processor currently provides support for
5720// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
5721// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
5722bool
5723EmulateInstructionARM::UnalignedSupport()
5724{
5725 return (ArchVersion() >= ARMv7);
5726}
5727
Johnny Chenbf6ad172011-02-11 01:29:53 +00005728// The main addition and subtraction instructions can produce status information
5729// about both unsigned carry and signed overflow conditions. This status
5730// information can be used to synthesize multi-word additions and subtractions.
5731EmulateInstructionARM::AddWithCarryResult
5732EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
5733{
5734 uint32_t result;
5735 uint8_t carry_out;
5736 uint8_t overflow;
5737
5738 uint64_t unsigned_sum = x + y + carry_in;
5739 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
5740
5741 result = UnsignedBits(unsigned_sum, 31, 0);
5742 carry_out = (result == unsigned_sum ? 0 : 1);
5743 overflow = ((int32_t)result == signed_sum ? 0 : 1);
5744
5745 AddWithCarryResult res = { result, carry_out, overflow };
5746 return res;
5747}
5748
Johnny Chen157b9592011-02-18 21:13:05 +00005749uint32_t
5750EmulateInstructionARM::ReadCoreReg(uint32_t regnum, bool *success)
5751{
5752 uint32_t val;
5753 if (regnum == 15)
5754 {
5755 val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, success);
5756 if (CurrentInstrSet() == eModeThumb)
5757 val += 4;
5758 else
5759 val += 8;
5760 }
5761 else
5762 val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + regnum, 0, success);
5763
5764 return val;
5765}
5766
Johnny Chenca67d1c2011-02-17 01:35:27 +00005767// Write the result to the ARM core register Rd, and optionally update the
5768// condition flags based on the result.
5769//
5770// This helper method tries to encapsulate the following pseudocode from the
5771// ARM Architecture Reference Manual:
5772//
5773// if d == 15 then // Can only occur for encoding A1
5774// ALUWritePC(result); // setflags is always FALSE here
5775// else
5776// R[d] = result;
5777// if setflags then
5778// APSR.N = result<31>;
5779// APSR.Z = IsZeroBit(result);
5780// APSR.C = carry;
5781// // APSR.V unchanged
5782//
5783// In the above case, the API client does not pass in the overflow arg, which
5784// defaults to ~0u.
5785bool
Johnny Chen10530c22011-02-17 22:37:12 +00005786EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
5787 const uint32_t result,
5788 const uint32_t Rd,
5789 bool setflags,
5790 const uint32_t carry,
5791 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00005792{
5793 if (Rd == 15)
5794 {
5795 if (!ALUWritePC (context, result))
5796 return false;
5797 }
5798 else
5799 {
5800 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
5801 return false;
5802 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00005803 return WriteFlags (context, result, carry, overflow);
5804 }
5805 return true;
5806}
5807
5808// This helper method tries to encapsulate the following pseudocode from the
5809// ARM Architecture Reference Manual:
5810//
5811// APSR.N = result<31>;
5812// APSR.Z = IsZeroBit(result);
5813// APSR.C = carry;
5814// APSR.V = overflow
5815//
5816// Default arguments can be specified for carry and overflow parameters, which means
5817// not to update the respective flags.
5818bool
5819EmulateInstructionARM::WriteFlags (Context &context,
5820 const uint32_t result,
5821 const uint32_t carry,
5822 const uint32_t overflow)
5823{
5824 m_new_inst_cpsr = m_inst_cpsr;
5825 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
5826 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
5827 if (carry != ~0u)
5828 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
5829 if (overflow != ~0u)
5830 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
5831 if (m_new_inst_cpsr != m_inst_cpsr)
5832 {
5833 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
5834 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00005835 }
5836 return true;
5837}
5838
Greg Clayton64c84432011-01-21 22:02:52 +00005839bool
5840EmulateInstructionARM::EvaluateInstruction ()
5841{
Johnny Chenc315f862011-02-05 00:46:10 +00005842 // Advance the ITSTATE bits to their values for the next instruction.
5843 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
5844 m_it_session.ITAdvance();
5845
Greg Clayton64c84432011-01-21 22:02:52 +00005846 return false;
5847}