blob: b85dac510fd977d775276f5a6667eb46f0b4f0b7 [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 Clayton8482ded2011-02-01 00:04:43 +000013#include "lldb/Core/ConstString.h"
14
Greg Claytonf29a08f2011-02-09 17:41:27 +000015#include "Plugins/Process/Utility/ARMDefines.h"
16#include "Plugins/Process/Utility/ARMUtils.h"
17#include "Utility/ARM_DWARF_Registers.h"
18
Johnny Chen9b8d7832011-02-02 01:13:56 +000019#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000020 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Johnny Chend6c13f02011-02-08 20:36:34 +000025static inline uint32_t Align(uint32_t val, uint32_t alignment)
26{
27 return alignment * (val / alignment);
28}
29
Johnny Chen0e00af22011-02-10 19:40:42 +000030//----------------------------------------------------------------------
31//
32// ITSession implementation
33//
34//----------------------------------------------------------------------
35
Johnny Chen93070472011-02-04 23:02:47 +000036// A8.6.50
37// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
38static unsigned short CountITSize(unsigned ITMask) {
39 // First count the trailing zeros of the IT mask.
40 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
41 if (TZ > 3)
42 {
43 printf("Encoding error: IT Mask '0000'\n");
44 return 0;
45 }
46 return (4 - TZ);
47}
48
49// Init ITState. Note that at least one bit is always 1 in mask.
50bool ITSession::InitIT(unsigned short bits7_0)
51{
52 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
53 if (ITCounter == 0)
54 return false;
55
56 // A8.6.50 IT
57 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
58 if (FirstCond == 0xF)
59 {
60 printf("Encoding error: IT FirstCond '1111'\n");
61 return false;
62 }
63 if (FirstCond == 0xE && ITCounter != 1)
64 {
65 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
66 return false;
67 }
68
69 ITState = bits7_0;
70 return true;
71}
72
73// Update ITState if necessary.
74void ITSession::ITAdvance()
75{
76 assert(ITCounter);
77 --ITCounter;
78 if (ITCounter == 0)
79 ITState = 0;
80 else
81 {
82 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
83 SetBits32(ITState, 4, 0, NewITState4_0);
84 }
85}
86
87// Return true if we're inside an IT Block.
88bool ITSession::InITBlock()
89{
90 return ITCounter != 0;
91}
92
Johnny Chenc315f862011-02-05 00:46:10 +000093// Return true if we're the last instruction inside an IT Block.
94bool ITSession::LastInITBlock()
95{
96 return ITCounter == 1;
97}
98
Johnny Chen93070472011-02-04 23:02:47 +000099// Get condition bits for the current thumb instruction.
100uint32_t ITSession::GetCond()
101{
Johnny Chenc315f862011-02-05 00:46:10 +0000102 if (InITBlock())
103 return Bits32(ITState, 7, 4);
104 else
105 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000106}
107
Greg Clayton64c84432011-01-21 22:02:52 +0000108// ARM constants used during decoding
109#define REG_RD 0
110#define LDM_REGLIST 1
111#define PC_REG 15
112#define PC_REGLIST_BIT 0x8000
113
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMv4T (1u << 1)
116#define ARMv5T (1u << 2)
117#define ARMv5TE (1u << 3)
118#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000119#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMv6K (1u << 6)
121#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000123#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMvAll (0xffffffffu)
125
Johnny Chen9b8d7832011-02-02 01:13:56 +0000126#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
127#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000129
Johnny Chen0e00af22011-02-10 19:40:42 +0000130//----------------------------------------------------------------------
131//
132// EmulateInstructionARM implementation
133//
134//----------------------------------------------------------------------
135
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000136void
137EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
145
Caroline Ticefa172202011-02-11 22:49:54 +0000146// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
147bool
148EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
149{
150 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteMemoryRandomBits,
151 address,
152 0,
153 0 };
154
155 uint32_t random_data = rand ();
156 const uint32_t addr_byte_size = GetAddressByteSize();
157
158 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
159 return false;
160
161 return true;
162}
163
Caroline Tice713c2662011-02-11 17:59:55 +0000164// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
165bool
166EmulateInstructionARM::WriteBits32Unknown (int n)
167{
168 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteRegisterRandomBits,
169 eRegisterKindDWARF,
170 dwarf_r0 + n,
171 0 };
172
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
189EmulateInstructionARM::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
275 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
276 for (i=0; i<15; ++i)
277 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000278 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000279 {
280 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
281 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000282 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000283 if (!success)
284 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000286 return false;
287 addr += addr_byte_size;
288 }
289 }
290
Johnny Chen7c1bf922011-02-08 23:49:37 +0000291 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 {
293 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000294 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000295 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000296 if (!success)
297 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000299 return false;
300 }
301
302 context.type = EmulateInstruction::eContextAdjustStackPointer;
303 context.arg0 = eRegisterKindGeneric;
304 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000305 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000306
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000307 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310 return true;
311}
312
Johnny Chenef85e912011-01-31 23:07:40 +0000313// Pop Multiple Registers loads multiple registers from the stack, loading from
314// consecutive memory locations staring at the address in SP, and updates
315// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000316bool
317EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000318{
319#if 0
320 // ARM pseudo code...
321 if (ConditionPassed())
322 {
323 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
324 address = SP;
325 for i = 0 to 14
326 if registers<i> == ‘1’ then
327 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
328 if registers<15> == ‘1’ then
329 if UnalignedAllowed then
330 LoadWritePC(MemU[address,4]);
331 else
332 LoadWritePC(MemA[address,4]);
333 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
334 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
335 }
336#endif
337
338 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000339 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000340 if (!success)
341 return false;
342
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000345 const uint32_t addr_byte_size = GetAddressByteSize();
346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349 uint32_t registers = 0;
350 uint32_t Rt; // the destination register
351 switch (encoding) {
352 case eEncodingT1:
353 registers = Bits32(opcode, 7, 0);
354 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000355 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 registers |= (1u << 15);
357 // if BitCount(registers) < 1 then UNPREDICTABLE;
358 if (BitCount(registers) < 1)
359 return false;
360 break;
361 case eEncodingT2:
362 // Ignore bit 13.
363 registers = Bits32(opcode, 15, 0) & ~0x2000;
364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
367 break;
368 case eEncodingT3:
369 Rt = Bits32(opcode, 15, 12);
370 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
371 if (Rt == dwarf_sp)
372 return false;
373 registers = (1u << Rt);
374 break;
375 case eEncodingA1:
376 registers = Bits32(opcode, 15, 0);
377 // Instead of return false, let's handle the following case as well,
378 // which amounts to popping one reg from the full descending stacks.
379 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
380
381 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000382 if (Bit32(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000383 return false;
384 break;
385 case eEncodingA2:
386 Rt = Bits32(opcode, 15, 12);
387 // if t == 13 then UNPREDICTABLE;
388 if (Rt == dwarf_sp)
389 return false;
390 registers = (1u << Rt);
391 break;
392 default:
393 return false;
394 }
395 addr_t sp_offset = addr_byte_size * BitCount (registers);
396 addr_t addr = sp;
397 uint32_t i, data;
398
399 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
400 for (i=0; i<15; ++i)
401 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000402 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000403 {
404 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
405 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000406 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000407 if (!success)
408 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000409 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 return false;
411 addr += addr_byte_size;
412 }
413 }
414
Johnny Chen7c1bf922011-02-08 23:49:37 +0000415 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000416 {
417 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
418 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000419 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000420 if (!success)
421 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000422 // In ARMv5T and above, this is an interworking branch.
423 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000424 return false;
425 addr += addr_byte_size;
426 }
427
428 context.type = EmulateInstruction::eContextAdjustStackPointer;
429 context.arg0 = eRegisterKindGeneric;
430 context.arg1 = LLDB_REGNUM_GENERIC_SP;
431 context.arg2 = sp_offset;
432
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000433 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000434 return false;
435 }
436 return true;
437}
438
Johnny Chen5b442b72011-01-27 19:34:30 +0000439// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000440// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000441bool
442EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000443{
444#if 0
445 // ARM pseudo code...
446 if (ConditionPassed())
447 {
448 EncodingSpecificOperations();
449 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
450 if d == 15 then
451 ALUWritePC(result); // setflags is always FALSE here
452 else
453 R[d] = result;
454 if setflags then
455 APSR.N = result<31>;
456 APSR.Z = IsZeroBit(result);
457 APSR.C = carry;
458 APSR.V = overflow;
459 }
460#endif
461
462 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000463 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000464 if (!success)
465 return false;
466
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000467 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000468 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000470 if (!success)
471 return false;
472 uint32_t Rd; // the destination register
473 uint32_t imm32;
474 switch (encoding) {
475 case eEncodingT1:
476 Rd = 7;
477 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
478 break;
479 case eEncodingA1:
480 Rd = Bits32(opcode, 15, 12);
481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
482 break;
483 default:
484 return false;
485 }
486 addr_t sp_offset = imm32;
487 addr_t addr = sp + sp_offset; // a pointer to the stack area
488
489 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
490 eRegisterKindGeneric,
491 LLDB_REGNUM_GENERIC_SP,
492 sp_offset };
493
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000495 return false;
496 }
497 return true;
498}
499
Johnny Chen2ccad832011-01-28 19:57:25 +0000500// Set r7 or ip to the current stack pointer.
501// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502bool
503EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000504{
505#if 0
506 // ARM pseudo code...
507 if (ConditionPassed())
508 {
509 EncodingSpecificOperations();
510 result = R[m];
511 if d == 15 then
512 ALUWritePC(result); // setflags is always FALSE here
513 else
514 R[d] = result;
515 if setflags then
516 APSR.N = result<31>;
517 APSR.Z = IsZeroBit(result);
518 // APSR.C unchanged
519 // APSR.V unchanged
520 }
521#endif
522
523 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 //if (!success)
526 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000527
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000528 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000529 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000531 if (!success)
532 return false;
533 uint32_t Rd; // the destination register
534 switch (encoding) {
535 case eEncodingT1:
536 Rd = 7;
537 break;
538 case eEncodingA1:
539 Rd = 12;
540 break;
541 default:
542 return false;
543 }
544 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
545 eRegisterKindGeneric,
546 LLDB_REGNUM_GENERIC_SP,
547 0 };
548
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000549 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000550 return false;
551 }
552 return true;
553}
554
Johnny Chen1c13b622011-01-29 00:11:15 +0000555// Move from high register (r8-r15) to low register (r0-r7).
556// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000557bool
558EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000559{
Johnny Chen338bf542011-02-10 19:29:03 +0000560 return EmulateMovRdRm (encoding);
561}
562
563// Move from register to register.
564// MOV (register)
565bool
566EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
567{
Johnny Chen1c13b622011-01-29 00:11:15 +0000568#if 0
569 // ARM pseudo code...
570 if (ConditionPassed())
571 {
572 EncodingSpecificOperations();
573 result = R[m];
574 if d == 15 then
575 ALUWritePC(result); // setflags is always FALSE here
576 else
577 R[d] = result;
578 if setflags then
579 APSR.N = result<31>;
580 APSR.Z = IsZeroBit(result);
581 // APSR.C unchanged
582 // APSR.V unchanged
583 }
584#endif
585
586 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000587 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000588 if (!success)
589 return false;
590
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000591 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000592 {
593 uint32_t Rm; // the source register
594 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000595 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 switch (encoding) {
597 case eEncodingT1:
598 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000599 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000600 setflags = false;
601 break;
602 case eEncodingT2:
603 Rm = Bits32(opcode, 5, 3);
604 Rd = Bits32(opcode, 2, 1);
605 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 break;
607 default:
608 return false;
609 }
Johnny Chen338bf542011-02-10 19:29:03 +0000610 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 if (!success)
612 return false;
613
614 // The context specifies that Rm is to be moved into Rd.
615 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
616 eRegisterKindDWARF,
617 dwarf_r0 + Rm,
618 0 };
619
Johnny Chen338bf542011-02-10 19:29:03 +0000620 if (Rd == 15)
621 {
622 if (!ALUWritePC (context, reg_value))
623 return false;
624 }
625 else
626 {
627 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
628 return false;
629 if (setflags)
630 {
631 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000632 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
633 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000634 if (m_new_inst_cpsr != m_inst_cpsr)
635 {
636 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
637 return false;
638 }
639 }
640 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000641 }
642 return true;
643}
644
Johnny Chen788e0552011-01-27 22:52:23 +0000645// PC relative immediate load into register, possibly followed by ADD (SP plus register).
646// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000647bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000648EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000649{
650#if 0
651 // ARM pseudo code...
652 if (ConditionPassed())
653 {
654 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
655 base = Align(PC,4);
656 address = if add then (base + imm32) else (base - imm32);
657 data = MemU[address,4];
658 if t == 15 then
659 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
660 elsif UnalignedSupport() || address<1:0> = ‘00’ then
661 R[t] = data;
662 else // Can only apply before ARMv7
663 if CurrentInstrSet() == InstrSet_ARM then
664 R[t] = ROR(data, 8*UInt(address<1:0>));
665 else
666 R[t] = bits(32) UNKNOWN;
667 }
668#endif
669
670 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000671 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000672 if (!success)
673 return false;
674
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000675 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000676 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000677 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000678 if (!success)
679 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000680
681 // PC relative immediate load context
682 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
683 eRegisterKindGeneric,
684 LLDB_REGNUM_GENERIC_PC,
685 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000686 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000687 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000688 bool add; // +imm32 or -imm32?
689 addr_t base; // the base address
690 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000691 uint32_t data; // the literal data value from the PC relative load
692 switch (encoding) {
693 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000694 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000695 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000696 add = true;
697 base = Align(pc + 4, 4);
698 context.arg2 = 4 + imm32;
699 break;
700 case eEncodingT2:
701 Rt = Bits32(opcode, 15, 12);
702 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
703 add = BitIsSet(opcode, 23);
704 if (Rt == 15
705 && m_it_session.InITBlock()
706 && !m_it_session.LastInITBlock())
707 return false;
708 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000709 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000710 break;
711 default:
712 return false;
713 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000714
715 if (add)
716 address = base + imm32;
717 else
718 address = base - imm32;
719 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000720 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000721 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000722
723 if (Rt == 15)
724 {
725 if (Bits32(address, 1, 0) == 0)
726 {
727 // In ARMv5T and above, this is an interworking branch.
728 if (!LoadWritePC(context, data))
729 return false;
730 }
731 else
732 return false;
733 }
734 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
735 {
736 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
737 return false;
738 }
739 else // We don't handle ARM for now.
740 return false;
741
742 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000743 return false;
744 }
745 return true;
746}
747
Johnny Chen5b442b72011-01-27 19:34:30 +0000748// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000749// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000750bool
751EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000752{
753#if 0
754 // ARM pseudo code...
755 if (ConditionPassed())
756 {
757 EncodingSpecificOperations();
758 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
759 if d == 15 then // Can only occur for ARM encoding
760 ALUWritePC(result); // setflags is always FALSE here
761 else
762 R[d] = result;
763 if setflags then
764 APSR.N = result<31>;
765 APSR.Z = IsZeroBit(result);
766 APSR.C = carry;
767 APSR.V = overflow;
768 }
769#endif
770
771 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000772 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000773 if (!success)
774 return false;
775
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000776 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000777 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000778 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000779 if (!success)
780 return false;
781 uint32_t imm32; // the immediate operand
782 switch (encoding) {
783 case eEncodingT2:
784 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
785 break;
786 default:
787 return false;
788 }
789 addr_t sp_offset = imm32;
790 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
791
792 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
793 eRegisterKindGeneric,
794 LLDB_REGNUM_GENERIC_SP,
795 sp_offset };
796
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000797 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000798 return false;
799 }
800 return true;
801}
802
803// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000804// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000805bool
806EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000807{
808#if 0
809 // ARM pseudo code...
810 if (ConditionPassed())
811 {
812 EncodingSpecificOperations();
813 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
814 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
815 if d == 15 then
816 ALUWritePC(result); // setflags is always FALSE here
817 else
818 R[d] = result;
819 if setflags then
820 APSR.N = result<31>;
821 APSR.Z = IsZeroBit(result);
822 APSR.C = carry;
823 APSR.V = overflow;
824 }
825#endif
826
827 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000828 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000829 if (!success)
830 return false;
831
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000832 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000833 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000834 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000835 if (!success)
836 return false;
837 uint32_t Rm; // the second operand
838 switch (encoding) {
839 case eEncodingT2:
840 Rm = Bits32(opcode, 6, 3);
841 break;
842 default:
843 return false;
844 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000845 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000846 if (!success)
847 return false;
848
849 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
850
851 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
852 eRegisterKindGeneric,
853 LLDB_REGNUM_GENERIC_SP,
854 reg_value };
855
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000857 return false;
858 }
859 return true;
860}
861
Johnny Chen9b8d7832011-02-02 01:13:56 +0000862// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
863// at a PC-relative address, and changes instruction set from ARM to Thumb, or
864// from Thumb to ARM.
865// BLX (immediate)
866bool
867EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
868{
869#if 0
870 // ARM pseudo code...
871 if (ConditionPassed())
872 {
873 EncodingSpecificOperations();
874 if CurrentInstrSet() == InstrSet_ARM then
875 LR = PC - 4;
876 else
877 LR = PC<31:1> : '1';
878 if targetInstrSet == InstrSet_ARM then
879 targetAddress = Align(PC,4) + imm32;
880 else
881 targetAddress = PC + imm32;
882 SelectInstrSet(targetInstrSet);
883 BranchWritePC(targetAddress);
884 }
885#endif
886
887 bool success = false;
888 const uint32_t opcode = OpcodeAsUnsigned (&success);
889 if (!success)
890 return false;
891
892 if (ConditionPassed())
893 {
894 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
895 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000896 if (!success)
897 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000898 addr_t lr; // next instruction address
899 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000900 int32_t imm32; // PC-relative offset
901 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000902 case eEncodingT1:
903 {
904 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000905 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +0000906 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000907 uint32_t J1 = Bit32(opcode, 13);
908 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +0000909 uint32_t imm11 = Bits32(opcode, 10, 0);
910 uint32_t I1 = !(J1 ^ S);
911 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000912 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000913 imm32 = llvm::SignExtend32<25>(imm25);
914 target = pc + 4 + imm32;
915 context.arg1 = 4 + imm32; // signed offset
916 context.arg2 = eModeThumb; // target instruction set
917 break;
918 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000919 case eEncodingT2:
920 {
921 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000922 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000923 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000924 uint32_t J1 = Bit32(opcode, 13);
925 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000926 uint32_t imm10L = Bits32(opcode, 10, 1);
927 uint32_t I1 = !(J1 ^ S);
928 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000929 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000930 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000931 target = Align(pc + 4, 4) + imm32;
932 context.arg1 = 4 + imm32; // signed offset
933 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000934 break;
935 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000936 case eEncodingA1:
937 lr = pc + 4; // return address
938 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000939 target = Align(pc + 8, 4) + imm32;
940 context.arg1 = 8 + imm32; // signed offset
941 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000942 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000943 case eEncodingA2:
944 lr = pc + 4; // return address
945 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
946 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000947 context.arg1 = 8 + imm32; // signed offset
948 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000949 break;
950 default:
951 return false;
952 }
953 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
954 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000955 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000956 return false;
957 }
958 return true;
959}
960
961// Branch with Link and Exchange (register) calls a subroutine at an address and
962// instruction set specified by a register.
963// BLX (register)
964bool
965EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
966{
967#if 0
968 // ARM pseudo code...
969 if (ConditionPassed())
970 {
971 EncodingSpecificOperations();
972 target = R[m];
973 if CurrentInstrSet() == InstrSet_ARM then
974 next_instr_addr = PC - 4;
975 LR = next_instr_addr;
976 else
977 next_instr_addr = PC - 2;
978 LR = next_instr_addr<31:1> : ‘1’;
979 BXWritePC(target);
980 }
981#endif
982
983 bool success = false;
984 const uint32_t opcode = OpcodeAsUnsigned (&success);
985 if (!success)
986 return false;
987
988 if (ConditionPassed())
989 {
990 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
991 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
992 addr_t lr; // next instruction address
993 addr_t target; // target address
994 if (!success)
995 return false;
996 uint32_t Rm; // the register with the target address
997 switch (encoding) {
998 case eEncodingT1:
999 lr = (pc + 2) | 1u; // return address
1000 Rm = Bits32(opcode, 6, 3);
1001 // if m == 15 then UNPREDICTABLE;
1002 if (Rm == 15)
1003 return false;
1004 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1005 break;
1006 case eEncodingA1:
1007 lr = pc + 4; // return address
1008 Rm = Bits32(opcode, 3, 0);
1009 // if m == 15 then UNPREDICTABLE;
1010 if (Rm == 15)
1011 return false;
1012 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001013 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001014 default:
1015 return false;
1016 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001017 context.arg0 = eRegisterKindDWARF;
1018 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001019 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1020 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001021 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001022 return false;
1023 }
1024 return true;
1025}
1026
Johnny Chen0d0148e2011-01-28 02:26:08 +00001027// Set r7 to point to some ip offset.
1028// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001029bool
1030EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001031{
1032#if 0
1033 // ARM pseudo code...
1034 if (ConditionPassed())
1035 {
1036 EncodingSpecificOperations();
1037 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1038 if d == 15 then // Can only occur for ARM encoding
1039 ALUWritePC(result); // setflags is always FALSE here
1040 else
1041 R[d] = result;
1042 if setflags then
1043 APSR.N = result<31>;
1044 APSR.Z = IsZeroBit(result);
1045 APSR.C = carry;
1046 APSR.V = overflow;
1047 }
1048#endif
1049
1050 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001051 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001052 if (!success)
1053 return false;
1054
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001055 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001056 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001057 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001058 if (!success)
1059 return false;
1060 uint32_t imm32;
1061 switch (encoding) {
1062 case eEncodingA1:
1063 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1064 break;
1065 default:
1066 return false;
1067 }
1068 addr_t ip_offset = imm32;
1069 addr_t addr = ip - ip_offset; // the adjusted ip value
1070
1071 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1072 eRegisterKindDWARF,
1073 dwarf_r12,
1074 -ip_offset };
1075
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001077 return false;
1078 }
1079 return true;
1080}
1081
1082// Set ip to point to some stack offset.
1083// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001084bool
1085EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001086{
1087#if 0
1088 // ARM pseudo code...
1089 if (ConditionPassed())
1090 {
1091 EncodingSpecificOperations();
1092 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1093 if d == 15 then // Can only occur for ARM encoding
1094 ALUWritePC(result); // setflags is always FALSE here
1095 else
1096 R[d] = result;
1097 if setflags then
1098 APSR.N = result<31>;
1099 APSR.Z = IsZeroBit(result);
1100 APSR.C = carry;
1101 APSR.V = overflow;
1102 }
1103#endif
1104
1105 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001106 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001107 if (!success)
1108 return false;
1109
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001110 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001111 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001112 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001113 if (!success)
1114 return false;
1115 uint32_t imm32;
1116 switch (encoding) {
1117 case eEncodingA1:
1118 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1119 break;
1120 default:
1121 return false;
1122 }
1123 addr_t sp_offset = imm32;
1124 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1125
1126 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1127 eRegisterKindGeneric,
1128 LLDB_REGNUM_GENERIC_SP,
1129 -sp_offset };
1130
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001131 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001132 return false;
1133 }
1134 return true;
1135}
1136
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001137// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138bool
1139EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001140{
1141#if 0
1142 // ARM pseudo code...
1143 if (ConditionPassed())
1144 {
1145 EncodingSpecificOperations();
1146 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1147 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001148 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001149 else
1150 R[d] = result;
1151 if setflags then
1152 APSR.N = result<31>;
1153 APSR.Z = IsZeroBit(result);
1154 APSR.C = carry;
1155 APSR.V = overflow;
1156 }
1157#endif
1158
1159 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001160 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001161 if (!success)
1162 return false;
1163
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001164 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001165 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001166 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001167 if (!success)
1168 return false;
1169 uint32_t imm32;
1170 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001171 case eEncodingT1:
1172 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001173 case eEncodingT2:
1174 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1175 break;
1176 case eEncodingT3:
1177 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1178 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001179 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001180 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001181 break;
1182 default:
1183 return false;
1184 }
1185 addr_t sp_offset = imm32;
1186 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1187
1188 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1189 eRegisterKindGeneric,
1190 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001191 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001192
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001193 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001194 return false;
1195 }
1196 return true;
1197}
1198
Johnny Chen08c25e82011-01-31 18:02:28 +00001199// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001200bool
1201EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001202{
1203#if 0
1204 // ARM pseudo code...
1205 if (ConditionPassed())
1206 {
1207 EncodingSpecificOperations();
1208 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1209 address = if index then offset_addr else R[n];
1210 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1211 if wback then R[n] = offset_addr;
1212 }
1213#endif
1214
1215 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001216 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001217 if (!success)
1218 return false;
1219
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001221 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001222 const uint32_t addr_byte_size = GetAddressByteSize();
1223 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001224 if (!success)
1225 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001226 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001227 uint32_t imm12;
1228 switch (encoding) {
1229 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001230 Rt = Bits32(opcode, 15, 12);
1231 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001232 break;
1233 default:
1234 return false;
1235 }
1236 addr_t sp_offset = imm12;
1237 addr_t addr = sp - sp_offset;
1238
1239 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001240 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001241 {
Johnny Chen91d99862011-01-25 19:07:04 +00001242 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1243 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001244 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001245 if (!success)
1246 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001247 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001248 return false;
1249 }
1250 else
1251 {
1252 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1253 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001254 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001255 if (!success)
1256 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001257 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001258 return false;
1259 }
1260
1261 context.type = EmulateInstruction::eContextAdjustStackPointer;
1262 context.arg0 = eRegisterKindGeneric;
1263 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001264 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001265
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001266 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001267 return false;
1268 }
1269 return true;
1270}
1271
Johnny Chen08c25e82011-01-31 18:02:28 +00001272// Vector Push stores multiple extension registers to the stack.
1273// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001274bool
1275EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001276{
1277#if 0
1278 // ARM pseudo code...
1279 if (ConditionPassed())
1280 {
1281 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1282 address = SP - imm32;
1283 SP = SP - imm32;
1284 if single_regs then
1285 for r = 0 to regs-1
1286 MemA[address,4] = S[d+r]; address = address+4;
1287 else
1288 for r = 0 to regs-1
1289 // Store as two word-aligned words in the correct order for current endianness.
1290 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1291 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1292 address = address+8;
1293 }
1294#endif
1295
1296 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001297 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001298 if (!success)
1299 return false;
1300
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001301 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001302 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001303 const uint32_t addr_byte_size = GetAddressByteSize();
1304 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001305 if (!success)
1306 return false;
1307 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001308 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001309 uint32_t imm32; // stack offset
1310 uint32_t regs; // number of registers
1311 switch (encoding) {
1312 case eEncodingT1:
1313 case eEncodingA1:
1314 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001315 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001316 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1317 // If UInt(imm8) is odd, see "FSTMX".
1318 regs = Bits32(opcode, 7, 0) / 2;
1319 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1320 if (regs == 0 || regs > 16 || (d + regs) > 32)
1321 return false;
1322 break;
1323 case eEncodingT2:
1324 case eEncodingA2:
1325 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001326 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001327 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1328 regs = Bits32(opcode, 7, 0);
1329 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1330 if (regs == 0 || regs > 16 || (d + regs) > 32)
1331 return false;
1332 break;
1333 default:
1334 return false;
1335 }
1336 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1337 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1338 addr_t sp_offset = imm32;
1339 addr_t addr = sp - sp_offset;
1340 uint32_t i;
1341
1342 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1343 for (i=d; i<regs; ++i)
1344 {
1345 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1346 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1347 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001348 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001349 if (!success)
1350 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001351 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001352 return false;
1353 addr += reg_byte_size;
1354 }
1355
1356 context.type = EmulateInstruction::eContextAdjustStackPointer;
1357 context.arg0 = eRegisterKindGeneric;
1358 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001359 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001360
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001361 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001362 return false;
1363 }
1364 return true;
1365}
1366
Johnny Chen587a0a42011-02-01 18:35:28 +00001367// Vector Pop loads multiple extension registers from the stack.
1368// It also updates SP to point just above the loaded data.
1369bool
1370EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1371{
1372#if 0
1373 // ARM pseudo code...
1374 if (ConditionPassed())
1375 {
1376 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1377 address = SP;
1378 SP = SP + imm32;
1379 if single_regs then
1380 for r = 0 to regs-1
1381 S[d+r] = MemA[address,4]; address = address+4;
1382 else
1383 for r = 0 to regs-1
1384 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1385 // Combine the word-aligned words in the correct order for current endianness.
1386 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1387 }
1388#endif
1389
1390 bool success = false;
1391 const uint32_t opcode = OpcodeAsUnsigned (&success);
1392 if (!success)
1393 return false;
1394
1395 if (ConditionPassed())
1396 {
1397 const uint32_t addr_byte_size = GetAddressByteSize();
1398 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1399 if (!success)
1400 return false;
1401 bool single_regs;
1402 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1403 uint32_t imm32; // stack offset
1404 uint32_t regs; // number of registers
1405 switch (encoding) {
1406 case eEncodingT1:
1407 case eEncodingA1:
1408 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001409 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001410 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1411 // If UInt(imm8) is odd, see "FLDMX".
1412 regs = Bits32(opcode, 7, 0) / 2;
1413 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1414 if (regs == 0 || regs > 16 || (d + regs) > 32)
1415 return false;
1416 break;
1417 case eEncodingT2:
1418 case eEncodingA2:
1419 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001420 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001421 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1422 regs = Bits32(opcode, 7, 0);
1423 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1424 if (regs == 0 || regs > 16 || (d + regs) > 32)
1425 return false;
1426 break;
1427 default:
1428 return false;
1429 }
1430 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1431 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1432 addr_t sp_offset = imm32;
1433 addr_t addr = sp;
1434 uint32_t i;
1435 uint64_t data; // uint64_t to accomodate 64-bit registers.
1436
1437 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1438 for (i=d; i<regs; ++i)
1439 {
1440 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1441 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1442 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1443 if (!success)
1444 return false;
1445 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1446 return false;
1447 addr += reg_byte_size;
1448 }
1449
1450 context.type = EmulateInstruction::eContextAdjustStackPointer;
1451 context.arg0 = eRegisterKindGeneric;
1452 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1453 context.arg2 = sp_offset;
1454
1455 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1456 return false;
1457 }
1458 return true;
1459}
1460
Johnny Chenb77be412011-02-04 00:40:18 +00001461// SVC (previously SWI)
1462bool
1463EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1464{
1465#if 0
1466 // ARM pseudo code...
1467 if (ConditionPassed())
1468 {
1469 EncodingSpecificOperations();
1470 CallSupervisor();
1471 }
1472#endif
1473
1474 bool success = false;
1475 const uint32_t opcode = OpcodeAsUnsigned (&success);
1476 if (!success)
1477 return false;
1478
1479 if (ConditionPassed())
1480 {
1481 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1482 addr_t lr; // next instruction address
1483 if (!success)
1484 return false;
1485 uint32_t imm32; // the immediate constant
1486 uint32_t mode; // ARM or Thumb mode
1487 switch (encoding) {
1488 case eEncodingT1:
1489 lr = (pc + 2) | 1u; // return address
1490 imm32 = Bits32(opcode, 7, 0);
1491 mode = eModeThumb;
1492 break;
1493 case eEncodingA1:
1494 lr = pc + 4; // return address
1495 imm32 = Bits32(opcode, 23, 0);
1496 mode = eModeARM;
1497 break;
1498 default:
1499 return false;
1500 }
1501 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1502 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1503 return false;
1504 }
1505 return true;
1506}
1507
Johnny Chenc315f862011-02-05 00:46:10 +00001508// If Then makes up to four following instructions (the IT block) conditional.
1509bool
1510EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1511{
1512#if 0
1513 // ARM pseudo code...
1514 EncodingSpecificOperations();
1515 ITSTATE.IT<7:0> = firstcond:mask;
1516#endif
1517
1518 bool success = false;
1519 const uint32_t opcode = OpcodeAsUnsigned (&success);
1520 if (!success)
1521 return false;
1522
1523 m_it_session.InitIT(Bits32(opcode, 7, 0));
1524 return true;
1525}
1526
Johnny Chen3b620b32011-02-07 20:11:47 +00001527// Branch causes a branch to a target address.
1528bool
1529EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1530{
1531#if 0
1532 // ARM pseudo code...
1533 if (ConditionPassed())
1534 {
1535 EncodingSpecificOperations();
1536 BranchWritePC(PC + imm32);
1537 }
1538#endif
1539
1540 bool success = false;
1541 const uint32_t opcode = OpcodeAsUnsigned (&success);
1542 if (!success)
1543 return false;
1544
Johnny Chen9ee056b2011-02-08 00:06:35 +00001545 if (ConditionPassed())
1546 {
1547 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1548 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001549 if (!success)
1550 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001551 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001552 int32_t imm32; // PC-relative offset
1553 switch (encoding) {
1554 case eEncodingT1:
1555 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1556 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1557 target = pc + 4 + imm32;
1558 context.arg1 = 4 + imm32; // signed offset
1559 context.arg2 = eModeThumb; // target instruction set
1560 break;
1561 case eEncodingT2:
1562 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1563 target = pc + 4 + imm32;
1564 context.arg1 = 4 + imm32; // signed offset
1565 context.arg2 = eModeThumb; // target instruction set
1566 break;
1567 case eEncodingT3:
1568 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1569 {
Johnny Chenbd599902011-02-10 21:39:01 +00001570 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001571 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001572 uint32_t J1 = Bit32(opcode, 13);
1573 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001574 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001575 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001576 imm32 = llvm::SignExtend32<21>(imm21);
1577 target = pc + 4 + imm32;
1578 context.arg1 = eModeThumb; // target instruction set
1579 context.arg2 = 4 + imm32; // signed offset
1580 break;
1581 }
1582 case eEncodingT4:
1583 {
Johnny Chenbd599902011-02-10 21:39:01 +00001584 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001585 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001586 uint32_t J1 = Bit32(opcode, 13);
1587 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001588 uint32_t imm11 = Bits32(opcode, 10, 0);
1589 uint32_t I1 = !(J1 ^ S);
1590 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001591 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001592 imm32 = llvm::SignExtend32<25>(imm25);
1593 target = pc + 4 + imm32;
1594 context.arg1 = eModeThumb; // target instruction set
1595 context.arg2 = 4 + imm32; // signed offset
1596 break;
1597 }
1598 case eEncodingA1:
1599 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1600 target = pc + 8 + imm32;
1601 context.arg1 = eModeARM; // target instruction set
1602 context.arg2 = 8 + imm32; // signed offset
1603 break;
1604 default:
1605 return false;
1606 }
1607 if (!BranchWritePC(context, target))
1608 return false;
1609 }
1610 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001611}
1612
Johnny Chen53ebab72011-02-08 23:21:57 +00001613// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1614// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1615// CBNZ, CBZ
1616bool
1617EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1618{
1619#if 0
1620 // ARM pseudo code...
1621 EncodingSpecificOperations();
1622 if nonzero ^ IsZero(R[n]) then
1623 BranchWritePC(PC + imm32);
1624#endif
1625
1626 bool success = false;
1627 const uint32_t opcode = OpcodeAsUnsigned (&success);
1628 if (!success)
1629 return false;
1630
1631 // Read the register value from the operand register Rn.
1632 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1633 if (!success)
1634 return false;
1635
1636 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1637 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1638 if (!success)
1639 return false;
1640
1641 addr_t target; // target address
1642 uint32_t imm32; // PC-relative offset to branch forward
1643 bool nonzero;
1644 switch (encoding) {
1645 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001646 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001647 nonzero = BitIsSet(opcode, 11);
1648 target = pc + 4 + imm32;
1649 context.arg1 = 4 + imm32; // signed offset
1650 context.arg2 = eModeThumb; // target instruction set
1651 break;
1652 default:
1653 return false;
1654 }
1655 if (nonzero ^ (reg_val == 0))
1656 if (!BranchWritePC(context, target))
1657 return false;
1658
1659 return true;
1660}
1661
Johnny Chen26863dc2011-02-09 23:43:29 +00001662// ADD <Rdn>, <Rm>
1663// where <Rdn> the destination register is also the first operand register
1664// and <Rm> is the second operand register.
1665bool
1666EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1667{
1668#if 0
1669 // ARM pseudo code...
1670 if ConditionPassed() then
1671 EncodingSpecificOperations();
1672 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1673 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1674 if d == 15 then
1675 ALUWritePC(result); // setflags is always FALSE here
1676 else
1677 R[d] = result;
1678 if setflags then
1679 APSR.N = result<31>;
1680 APSR.Z = IsZeroBit(result);
1681 APSR.C = carry;
1682 APSR.V = overflow;
1683#endif
1684
1685 bool success = false;
1686 const uint32_t opcode = OpcodeAsUnsigned (&success);
1687 if (!success)
1688 return false;
1689
1690 if (ConditionPassed())
1691 {
1692 uint32_t Rd, Rn, Rm;
1693 //bool setflags = false;
1694 switch (encoding)
1695 {
1696 case eEncodingT2:
1697 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001698 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001699 Rm = Bits32(opcode, 6, 3);
1700 if (Rn == 15 && Rm == 15)
1701 return false;
1702 break;
1703 default:
1704 return false;
1705 }
1706
1707 int32_t result, val1, val2;
1708 // Read the first operand.
1709 if (Rn == 15)
1710 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1711 else
1712 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1713 if (!success)
1714 return false;
1715
1716 // Read the second operand.
1717 if (Rm == 15)
1718 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1719 else
1720 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1721 if (!success)
1722 return false;
1723
1724 result = val1 + val2;
1725 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1726 result,
1727 0,
1728 0 };
1729
1730 if (Rd == 15)
1731 {
1732 if (!ALUWritePC (context, result))
1733 return false;
1734 }
1735 else
1736 {
1737 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1738 return false;
1739 }
1740 }
1741 return true;
1742}
1743
Johnny Chene4a4d302011-02-11 21:53:58 +00001744// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001745bool
1746EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1747{
1748#if 0
1749 // ARM pseudo code...
1750 if ConditionPassed() then
1751 EncodingSpecificOperations();
1752 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1753 APSR.N = result<31>;
1754 APSR.Z = IsZeroBit(result);
1755 APSR.C = carry;
1756 APSR.V = overflow;
1757#endif
1758
1759 bool success = false;
1760 const uint32_t opcode = OpcodeAsUnsigned (&success);
1761 if (!success)
1762 return false;
1763
1764 uint32_t Rn; // the first operand
1765 uint32_t imm32; // the immediate value to be compared with
1766 switch (encoding) {
1767 case eEncodingT1:
1768 Rn = Bits32(opcode, 10, 8);
1769 imm32 = Bits32(opcode, 7, 0);
1770 break;
1771 default:
1772 return false;
1773 }
1774 // Read the register value from the operand register Rn.
1775 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1776 if (!success)
1777 return false;
1778
1779 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1780 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1781 m_new_inst_cpsr = m_inst_cpsr;
1782 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1783 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1784 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1785 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1786 if (m_new_inst_cpsr != m_inst_cpsr)
1787 {
1788 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1789 return false;
1790 }
1791 return true;
1792}
1793
Johnny Chene4a4d302011-02-11 21:53:58 +00001794// CMP (register)
1795bool
1796EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1797{
1798#if 0
1799 // ARM pseudo code...
1800 if ConditionPassed() then
1801 EncodingSpecificOperations();
1802 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1803 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1804 APSR.N = result<31>;
1805 APSR.Z = IsZeroBit(result);
1806 APSR.C = carry;
1807 APSR.V = overflow;
1808#endif
1809
1810 bool success = false;
1811 const uint32_t opcode = OpcodeAsUnsigned (&success);
1812 if (!success)
1813 return false;
1814
1815 uint32_t Rn; // the first operand
1816 uint32_t Rm; // the second operand
1817 switch (encoding) {
1818 case eEncodingT1:
1819 Rn = Bits32(opcode, 2, 0);
1820 Rm = Bits32(opcode, 5, 3);
1821 break;
1822 case eEncodingT2:
1823 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1824 Rm = Bits32(opcode, 6, 3);
1825 if (Rn < 8 && Rm < 8)
1826 return false;
1827 if (Rn == 15 || Rm == 15)
1828 return false;
1829 break;
1830 default:
1831 return false;
1832 }
1833 // Read the register value from register Rn.
1834 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1835 if (!success)
1836 return false;
1837 // Read the register value from register Rm.
1838 // The register value is not being shifted since we don't handle ARM for now.
1839 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1840 if (!success)
1841 return false;
1842
1843 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1844 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
1845 m_new_inst_cpsr = m_inst_cpsr;
1846 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1847 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1848 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1849 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1850 if (m_new_inst_cpsr != m_inst_cpsr)
1851 {
1852 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1853 return false;
1854 }
1855 return true;
1856}
1857
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001858// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00001859// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001860// can be written back to the base register.
1861bool
1862EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1863{
1864#if 0
1865 // ARM pseudo code...
1866 if ConditionPassed()
1867 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1868 address = R[n];
1869
1870 for i = 0 to 14
1871 if registers<i> == '1' then
1872 R[i] = MemA[address, 4]; address = address + 4;
1873 if registers<15> == '1' then
1874 LoadWritePC (MemA[address, 4]);
1875
1876 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1877 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1878
1879#endif
1880
1881 bool success = false;
1882 const uint32_t opcode = OpcodeAsUnsigned (&success);
1883 if (!success)
1884 return false;
1885
1886 if (ConditionPassed())
1887 {
1888 uint32_t n;
1889 uint32_t registers = 0;
1890 bool wback;
1891 const uint32_t addr_byte_size = GetAddressByteSize();
1892 switch (encoding)
1893 {
1894 case eEncodingT1:
1895 n = Bits32 (opcode, 10, 8);
1896 registers = Bits32 (opcode, 7, 0);
1897 wback = BitIsClear (registers, n);
1898 // if BitCount(registers) < 1 then UNPREDICTABLE;
1899 if (BitCount(registers) < 1)
1900 return false;
1901 break;
1902 case eEncodingT2:
1903 n = Bits32 (opcode, 19, 16);
1904 registers = Bits32 (opcode, 15, 0);
1905 wback = BitIsSet (opcode, 21);
1906 if ((n == 15)
1907 || (BitCount (registers) < 2)
1908 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1909 return false;
1910 if (BitIsSet (registers, 15)
1911 && m_it_session.InITBlock()
1912 && !m_it_session.LastInITBlock())
1913 return false;
1914 if (wback
1915 && BitIsSet (registers, n))
1916 return false;
1917 break;
1918 case eEncodingA1:
1919 n = Bits32 (opcode, 19, 16);
1920 registers = Bits32 (opcode, 15, 0);
1921 wback = BitIsSet (opcode, 21);
1922 if ((n == 15)
1923 || (BitCount (registers) < 1))
1924 return false;
1925 break;
1926 default:
1927 return false;
1928 }
1929
1930 int32_t offset = 0;
1931 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1932 if (!success)
1933 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001934
1935 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1936 eRegisterKindDWARF,
1937 dwarf_r0 + n,
1938 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001939
1940 for (int i = 0; i < 14; ++i)
1941 {
1942 if (BitIsSet (registers, i))
1943 {
Caroline Tice85aab332011-02-08 23:56:10 +00001944 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1945 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001946 if (wback && (n == 13)) // Pop Instruction
1947 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1948
1949 // R[i] = MemA [address, 4]; address = address + 4;
1950 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1951 if (!success)
1952 return false;
1953
1954 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1955 return false;
1956
1957 offset += addr_byte_size;
1958 }
1959 }
1960
1961 if (BitIsSet (registers, 15))
1962 {
1963 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001964 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1965 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001966 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1967 if (!success)
1968 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001969 // In ARMv5T and above, this is an interworking branch.
1970 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001971 return false;
1972 }
1973
1974 if (wback && BitIsClear (registers, n))
1975 {
Caroline Ticefa172202011-02-11 22:49:54 +00001976 // R[n] = R[n] + 4 * BitCount (registers)
1977 int32_t offset = addr_byte_size * BitCount (registers);
1978 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice85aab332011-02-08 23:56:10 +00001979 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001980
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001981 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1982 return false;
1983 }
1984 if (wback && BitIsSet (registers, n))
1985 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00001986 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001987 }
1988 return true;
1989}
Caroline Tice713c2662011-02-11 17:59:55 +00001990
1991// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
1992// The consecutive memorty locations end at this address and the address just below the lowest of those locations
1993// can optionally be written back tot he base registers.
1994bool
1995EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
1996{
1997#if 0
1998 // ARM pseudo code...
1999 if ConditionPassed() then
2000 EncodingSpecificOperations();
2001 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002002
Caroline Tice713c2662011-02-11 17:59:55 +00002003 for i = 0 to 14
2004 if registers<i> == ’1’ then
2005 R[i] = MemA[address,4]; address = address + 4;
2006
2007 if registers<15> == ’1’ then
2008 LoadWritePC(MemA[address,4]);
2009
2010 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2011 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2012#endif
2013
2014 bool success = false;
2015 const uint32_t opcode = OpcodeAsUnsigned (&success);
2016 if (!success)
2017 return false;
2018
2019 if (ConditionPassed())
2020 {
2021 uint32_t n;
2022 uint32_t registers = 0;
2023 bool wback;
2024 const uint32_t addr_byte_size = GetAddressByteSize();
2025
2026 // EncodingSpecificOperations();
2027 switch (encoding)
2028 {
2029 case eEncodingA1:
2030 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2031 n = Bits32 (opcode, 19, 16);
2032 registers = Bits32 (opcode, 15, 0);
2033 wback = BitIsSet (opcode, 21);
2034
2035 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2036 if ((n == 15) || (BitCount (registers) < 1))
2037 return false;
2038
2039 break;
2040
2041 default:
2042 return false;
2043 }
2044 // address = R[n] - 4*BitCount(registers) + 4;
2045
2046 int32_t offset = 0;
2047 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2048
2049 if (!success)
2050 return false;
2051
2052 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2053
2054 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2055 eRegisterKindDWARF,
2056 dwarf_r0 + n,
2057 offset };
2058
2059 // for i = 0 to 14
2060 for (int i = 0; i < 14; ++i)
2061 {
2062 // if registers<i> == ’1’ then
2063 if (BitIsSet (registers, i))
2064 {
2065 // R[i] = MemA[address,4]; address = address + 4;
2066 context.arg2 = offset;
2067 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2068 if (!success)
2069 return false;
2070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2071 return false;
2072 offset += addr_byte_size;
2073 }
2074 }
2075
2076 // if registers<15> == ’1’ then
2077 // LoadWritePC(MemA[address,4]);
2078 if (BitIsSet (registers, 15))
2079 {
2080 context.arg2 = offset;
2081 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2082 if (!success)
2083 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002084 // In ARMv5T and above, this is an interworking branch.
2085 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002086 return false;
2087 }
2088
2089 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2090 if (wback && BitIsClear (registers, n))
2091 {
Caroline Tice713c2662011-02-11 17:59:55 +00002092 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2093 if (!success)
2094 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002095
2096 offset = (addr_byte_size * BitCount (registers)) * -1;
2097 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2098 context.arg2 = offset;
2099 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002100 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2101 return false;
2102 }
2103
2104 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2105 if (wback && BitIsSet (registers, n))
2106 return WriteBits32Unknown (n);
2107 }
2108 return true;
2109}
2110
2111// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2112// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2113// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002114bool
2115EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2116{
2117#if 0
2118 // ARM pseudo code...
2119 if ConditionPassed() then
2120 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2121 address = R[n] - 4*BitCount(registers);
2122
2123 for i = 0 to 14
2124 if registers<i> == ’1’ then
2125 R[i] = MemA[address,4]; address = address + 4;
2126 if registers<15> == ’1’ then
2127 LoadWritePC(MemA[address,4]);
2128
2129 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2130 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2131#endif
2132
2133 bool success = false;
2134 const uint32_t opcode = OpcodeAsUnsigned (&success);
2135 if (!success)
2136 return false;
2137
2138 if (ConditionPassed())
2139 {
2140 uint32_t n;
2141 uint32_t registers = 0;
2142 bool wback;
2143 const uint32_t addr_byte_size = GetAddressByteSize();
2144 switch (encoding)
2145 {
2146 case eEncodingT1:
2147 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2148 n = Bits32 (opcode, 19, 16);
2149 registers = Bits32 (opcode, 15, 0);
2150 wback = BitIsSet (opcode, 21);
2151
2152 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2153 if ((n == 15)
2154 || (BitCount (registers) < 2)
2155 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2156 return false;
2157
2158 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
2159 if (BitIsSet (registers, 15)
2160 && m_it_session.InITBlock()
2161 && !m_it_session.LastInITBlock())
2162 return false;
2163
2164 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2165 if (wback && BitIsSet (registers, n))
2166 return false;
2167
2168 break;
2169
2170 case eEncodingA1:
2171 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2172 n = Bits32 (opcode, 19, 16);
2173 registers = Bits32 (opcode, 15, 0);
2174 wback = BitIsSet (opcode, 21);
2175
2176 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2177 if ((n == 15) || (BitCount (registers) < 1))
2178 return false;
2179
2180 break;
2181
2182 default:
2183 return false;
2184 }
2185
Caroline Tice713c2662011-02-11 17:59:55 +00002186 // address = R[n] - 4*BitCount(registers);
2187
Caroline Tice0b29e242011-02-08 23:16:02 +00002188 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002189 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2190
2191 if (!success)
2192 return false;
2193
2194 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002195 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2196 eRegisterKindDWARF,
2197 dwarf_r0 + n,
2198 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002199
2200 for (int i = 0; i < 14; ++i)
2201 {
2202 if (BitIsSet (registers, i))
2203 {
2204 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002205 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002206 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2207 if (!success)
2208 return false;
2209
2210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2211 return false;
2212
2213 offset += addr_byte_size;
2214 }
2215 }
2216
2217 // if registers<15> == ’1’ then
2218 // LoadWritePC(MemA[address,4]);
2219 if (BitIsSet (registers, 15))
2220 {
Caroline Tice85aab332011-02-08 23:56:10 +00002221 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002222 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2223 if (!success)
2224 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002225 // In ARMv5T and above, this is an interworking branch.
2226 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002227 return false;
2228 }
2229
2230 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2231 if (wback && BitIsClear (registers, n))
2232 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002233 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2234 if (!success)
2235 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002236
2237 offset = (addr_byte_size * BitCount (registers)) * -1;
2238 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2239 context.arg2 = offset;
2240 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002241 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2242 return false;
2243 }
2244
2245 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2246 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002247 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002248 }
2249 return true;
2250}
Caroline Tice85aab332011-02-08 23:56:10 +00002251
Caroline Tice713c2662011-02-11 17:59:55 +00002252// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2253// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2254// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002255bool
2256EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2257{
2258#if 0
2259 if ConditionPassed() then
2260 EncodingSpecificOperations();
2261 address = R[n] + 4;
2262
2263 for i = 0 to 14
2264 if registers<i> == ’1’ then
2265 R[i] = MemA[address,4]; address = address + 4;
2266 if registers<15> == ’1’ then
2267 LoadWritePC(MemA[address,4]);
2268
2269 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2270 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2271#endif
2272
2273 bool success = false;
2274 const uint32_t opcode = OpcodeAsUnsigned (&success);
2275 if (!success)
2276 return false;
2277
2278 if (ConditionPassed())
2279 {
2280 uint32_t n;
2281 uint32_t registers = 0;
2282 bool wback;
2283 const uint32_t addr_byte_size = GetAddressByteSize();
2284 switch (encoding)
2285 {
2286 case eEncodingA1:
2287 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2288 n = Bits32 (opcode, 19, 16);
2289 registers = Bits32 (opcode, 15, 0);
2290 wback = BitIsSet (opcode, 21);
2291
2292 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2293 if ((n == 15) || (BitCount (registers) < 1))
2294 return false;
2295
2296 break;
2297 default:
2298 return false;
2299 }
2300 // address = R[n] + 4;
2301
2302 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002303 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2304
2305 if (!success)
2306 return false;
2307
2308 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002309
2310 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2311 eRegisterKindDWARF,
2312 dwarf_r0 + n,
2313 offset };
2314
2315 for (int i = 0; i < 14; ++i)
2316 {
2317 if (BitIsSet (registers, i))
2318 {
2319 // R[i] = MemA[address,4]; address = address + 4;
2320
2321 context.arg2 = offset;
2322 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2323 if (!success)
2324 return false;
2325
2326 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2327 return false;
2328
2329 offset += addr_byte_size;
2330 }
2331 }
2332
2333 // if registers<15> == ’1’ then
2334 // LoadWritePC(MemA[address,4]);
2335 if (BitIsSet (registers, 15))
2336 {
2337 context.arg2 = offset;
2338 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2339 if (!success)
2340 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002341 // In ARMv5T and above, this is an interworking branch.
2342 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002343 return false;
2344 }
2345
2346 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2347 if (wback && BitIsClear (registers, n))
2348 {
Caroline Tice85aab332011-02-08 23:56:10 +00002349 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2350 if (!success)
2351 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002352
2353 offset = addr_byte_size * BitCount (registers);
2354 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2355 context.arg2 = offset;
2356 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002357 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2358 return false;
2359 }
2360
2361 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2362 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002363 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002364 }
2365 return true;
2366}
Caroline Tice0b29e242011-02-08 23:16:02 +00002367
Johnny Chenef21b592011-02-10 01:52:38 +00002368// Load Register (immediate) calculates an address from a base register value and
2369// an immediate offset, loads a word from memory, and writes to a register.
2370// LDR (immediate, Thumb)
2371bool
2372EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2373{
2374#if 0
2375 // ARM pseudo code...
2376 if (ConditionPassed())
2377 {
2378 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2379 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2380 address = if index then offset_addr else R[n];
2381 data = MemU[address,4];
2382 if wback then R[n] = offset_addr;
2383 if t == 15 then
2384 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2385 elsif UnalignedSupport() || address<1:0> = '00' then
2386 R[t] = data;
2387 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2388 }
2389#endif
2390
2391 bool success = false;
2392 const uint32_t opcode = OpcodeAsUnsigned (&success);
2393 if (!success)
2394 return false;
2395
2396 if (ConditionPassed())
2397 {
2398 uint32_t Rt; // the destination register
2399 uint32_t Rn; // the base register
2400 uint32_t imm32; // the immediate offset used to form the address
2401 addr_t offset_addr; // the offset address
2402 addr_t address; // the calculated address
2403 uint32_t data; // the literal data value from memory load
2404 bool add, index, wback;
2405 switch (encoding) {
2406 case eEncodingT1:
2407 Rt = Bits32(opcode, 5, 3);
2408 Rn = Bits32(opcode, 2, 0);
2409 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2410 // index = TRUE; add = TRUE; wback = FALSE
2411 add = true;
2412 index = true;
2413 wback = false;
2414 break;
2415 default:
2416 return false;
2417 }
2418 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2419 if (!success)
2420 return false;
2421 if (add)
2422 offset_addr = base + imm32;
2423 else
2424 offset_addr = base - imm32;
2425
2426 address = (index ? offset_addr : base);
2427
2428 if (wback)
2429 {
2430 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2431 eRegisterKindDWARF,
2432 dwarf_r0 + Rn,
2433 (int32_t) (offset_addr - base)};
2434 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2435 return false;
2436 }
2437
2438 // Prepare to write to the Rt register.
2439 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2440 0,
2441 0,
2442 0};
2443
2444 // Read memory from the address.
2445 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2446 if (!success)
2447 return false;
2448 context.arg0 = data;
2449
2450 if (Rt == 15)
2451 {
2452 if (Bits32(address, 1, 0) == 0)
2453 {
2454 if (!LoadWritePC(context, data))
2455 return false;
2456 }
2457 else
2458 return false;
2459 }
2460 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2461 {
2462 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2463 return false;
2464 }
2465 else
2466 return false;
2467 }
2468 return true;
2469}
2470
Caroline Ticefa172202011-02-11 22:49:54 +00002471// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2472// consecutive memory locations start at this address, and teh address just above the last of those locations can
2473// optionally be written back to the base register.
2474bool
2475EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2476{
2477#if 0
2478 if ConditionPassed() then
2479 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2480 address = R[n];
2481
2482 for i = 0 to 14
2483 if registers<i> == ’1’ then
2484 if i == n && wback && i != LowestSetBit(registers) then
2485 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2486 else
2487 MemA[address,4] = R[i];
2488 address = address + 4;
2489
2490 if registers<15> == ’1’ then // Only possible for encoding A1
2491 MemA[address,4] = PCStoreValue();
2492 if wback then R[n] = R[n] + 4*BitCount(registers);
2493#endif
2494
2495 bool success = false;
2496 const uint32_t opcode = OpcodeAsUnsigned (&success);
2497 if (!success)
2498 return false;
2499
2500 if (ConditionPassed ())
2501 {
2502 uint32_t n;
2503 uint32_t registers = 0;
2504 bool wback;
2505 const uint32_t addr_byte_size = GetAddressByteSize();
2506
2507 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2508 switch (encoding)
2509 {
2510 case eEncodingT1:
2511 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2512 n = Bits32 (opcode, 10, 8);
2513 registers = Bits32 (opcode, 7, 0);
2514 wback = true;
2515
2516 // if BitCount(registers) < 1 then UNPREDICTABLE;
2517 if (BitCount (registers) < 1)
2518 return false;
2519
2520 break;
2521
2522 case eEncodingT2:
2523 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2524 n = Bits32 (opcode, 19, 16);
2525 registers = Bits32 (opcode, 15, 0);
2526 wback = BitIsSet (opcode, 21);
2527
2528 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2529 if ((n == 15) || (BitCount (registers) < 2))
2530 return false;
2531
2532 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2533 if (wback && BitIsSet (registers, n))
2534 return false;
2535
2536 break;
2537
2538 case eEncodingA1:
2539 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2540 n = Bits32 (opcode, 19, 16);
2541 registers = Bits32 (opcode, 15, 0);
2542 wback = BitIsSet (opcode, 21);
2543
2544 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2545 if ((n == 15) || (BitCount (registers) < 1))
2546 return false;
2547
2548 break;
2549
2550 default:
2551 return false;
2552 }
2553
2554 // address = R[n];
2555 int32_t offset = 0;
2556 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2557 if (!success)
2558 return false;
2559
2560 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterStore,
2561 eRegisterKindDWARF,
2562 dwarf_r0 + n,
2563 offset };
2564
2565 // for i = 0 to 14
2566 for (int i = 0; i < 14; ++i)
2567 {
2568 int lowest_set_bit = 14;
2569 // if registers<i> == ’1’ then
2570 if (BitIsSet (registers, i))
2571 {
2572 if (i < lowest_set_bit)
2573 lowest_set_bit = i;
2574 // if i == n && wback && i != LowestSetBit(registers) then
2575 if ((i == n) && wback && (i != lowest_set_bit))
2576 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2577 WriteBits32UnknownToMemory (address + offset);
2578 else
2579 {
2580 // MemA[address,4] = R[i];
2581 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2582 if (!success)
2583 return false;
2584
2585 context.arg1 = dwarf_r0 + i;
2586 context.arg2 = address + offset;
2587 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2588 return false;
2589 }
2590
2591 // address = address + 4;
2592 offset += addr_byte_size;
2593 }
2594 }
2595
2596 // if registers<15> == ’1’ then // Only possible for encoding A1
2597 // MemA[address,4] = PCStoreValue();
2598 if (BitIsSet (registers, 15))
2599 {
2600 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2601 if (!success)
2602 return false;
2603
2604 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
2605 context.arg2 = address + offset - sp; // arg2 in the context is the stack pointer offset
2606 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2607 if (!success)
2608 return false;
2609
2610 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2611 return false;
2612 }
2613
2614 // if wback then R[n] = R[n] + 4*BitCount(registers);
2615 if (wback)
2616 {
2617 offset = addr_byte_size * BitCount (registers);
2618 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2619 context.arg1 = dwarf_r0 + n;
2620 context.arg2 = offset;
2621 addr_t data = address + offset;
2622 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2623 return false;
2624 }
2625 }
2626 return true;
2627}
2628
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002629EmulateInstructionARM::ARMOpcode*
2630EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002631{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002632 static ARMOpcode
2633 g_arm_opcodes[] =
2634 {
2635 //----------------------------------------------------------------------
2636 // Prologue instructions
2637 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002638
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002639 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002640 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2641 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002642
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002643 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002644 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2645 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002646 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002647 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2648 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2649 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002650
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002651 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002652 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002653
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002654 // push one register
2655 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002656 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002657
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002658 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002659 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2660 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002661
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002662 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002663 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002664 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002665
Johnny Chenc28a76d2011-02-01 18:51:48 +00002666 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2667 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002668 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002669 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2670
2671 //----------------------------------------------------------------------
2672 // Supervisor Call (previously Software Interrupt)
2673 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002674 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2675
2676 //----------------------------------------------------------------------
2677 // Branch instructions
2678 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002679 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002680 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2681 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2682 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2683 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002684
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002685 //----------------------------------------------------------------------
2686 // Load instructions
2687 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002688 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002689 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002690 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002691 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2692
2693 //----------------------------------------------------------------------
2694 // Store instructions
2695 //----------------------------------------------------------------------
2696 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002697
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002698 };
2699 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2700
2701 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2702 {
2703 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2704 return &g_arm_opcodes[i];
2705 }
2706 return NULL;
2707}
Greg Clayton64c84432011-01-21 22:02:52 +00002708
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002709
2710EmulateInstructionARM::ARMOpcode*
2711EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002712{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002713
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002714 static ARMOpcode
2715 g_thumb_opcodes[] =
2716 {
2717 //----------------------------------------------------------------------
2718 // Prologue instructions
2719 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002720
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002721 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002722 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002723 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2724 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002725
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002726 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002727 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002728 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002729 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002730 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2731 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002732
Johnny Chenc9de9102011-02-11 19:12:30 +00002733 // PC-relative load into register (see also EmulateAddSPRm)
2734 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002735
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002736 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002737 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2738 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002739 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2740 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002741
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002742 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002743 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2744 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002745
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002746 //----------------------------------------------------------------------
2747 // Epilogue instructions
2748 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002749
Johnny Chenc28a76d2011-02-01 18:51:48 +00002750 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2751 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002752 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2753 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2754 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2755 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002756
2757 //----------------------------------------------------------------------
2758 // Supervisor Call (previously Software Interrupt)
2759 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002760 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2761
2762 //----------------------------------------------------------------------
2763 // If Then makes up to four following instructions conditional.
2764 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002765 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2766
2767 //----------------------------------------------------------------------
2768 // Branch instructions
2769 //----------------------------------------------------------------------
2770 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2771 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2772 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002773 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002774 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00002775 // J1 == J2 == 1
2776 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2777 // J1 == J2 == 1
2778 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2779 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002780 // compare and branch
2781 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002782
2783 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002784 // Data-processing instructions
2785 //----------------------------------------------------------------------
2786 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2787 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002788 // move from high register to high register
2789 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2790 // move from low register to low register
2791 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00002792 // compare a register with immediate
2793 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00002794 // compare Rn with Rm (Rn and Rm both from r0-r7)
2795 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
2796 // compare Rn with Rm (Rn and Rm not both from r0-r7)
2797 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002798
2799 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002800 // Load instructions
2801 //----------------------------------------------------------------------
2802 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002803 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002804 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00002805 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
2806 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00002807 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
2808
2809 //----------------------------------------------------------------------
2810 // Store instructions
2811 //----------------------------------------------------------------------
2812 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
2813 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002814
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002815 };
2816
2817 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2818 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2819 {
2820 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2821 return &g_thumb_opcodes[i];
2822 }
2823 return NULL;
2824}
Greg Clayton64c84432011-01-21 22:02:52 +00002825
Greg Clayton31e2a382011-01-30 20:03:56 +00002826bool
2827EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2828{
2829 m_arm_isa = 0;
2830 const char *triple_cstr = triple.GetCString();
2831 if (triple_cstr)
2832 {
2833 const char *dash = ::strchr (triple_cstr, '-');
2834 if (dash)
2835 {
2836 std::string arch (triple_cstr, dash);
2837 const char *arch_cstr = arch.c_str();
2838 if (strcasecmp(arch_cstr, "armv4t") == 0)
2839 m_arm_isa = ARMv4T;
2840 else if (strcasecmp(arch_cstr, "armv4") == 0)
2841 m_arm_isa = ARMv4;
2842 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2843 m_arm_isa = ARMv5TEJ;
2844 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2845 m_arm_isa = ARMv5TE;
2846 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2847 m_arm_isa = ARMv5T;
2848 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2849 m_arm_isa = ARMv6K;
2850 else if (strcasecmp(arch_cstr, "armv6") == 0)
2851 m_arm_isa = ARMv6;
2852 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2853 m_arm_isa = ARMv6T2;
2854 else if (strcasecmp(arch_cstr, "armv7") == 0)
2855 m_arm_isa = ARMv7;
2856 else if (strcasecmp(arch_cstr, "armv8") == 0)
2857 m_arm_isa = ARMv8;
2858 }
2859 }
2860 return m_arm_isa != 0;
2861}
2862
2863
Greg Clayton64c84432011-01-21 22:02:52 +00002864bool
2865EmulateInstructionARM::ReadInstruction ()
2866{
2867 bool success = false;
2868 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2869 if (success)
2870 {
2871 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2872 if (success)
2873 {
2874 Context read_inst_context = {eContextReadOpcode, 0, 0};
2875 if (m_inst_cpsr & MASK_CPSR_T)
2876 {
2877 m_inst_mode = eModeThumb;
2878 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2879
2880 if (success)
2881 {
2882 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2883 {
2884 m_inst.opcode_type = eOpcode16;
2885 m_inst.opcode.inst16 = thumb_opcode;
2886 }
2887 else
2888 {
2889 m_inst.opcode_type = eOpcode32;
2890 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2891 }
2892 }
2893 }
2894 else
2895 {
2896 m_inst_mode = eModeARM;
2897 m_inst.opcode_type = eOpcode32;
2898 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2899 }
2900 }
2901 }
2902 if (!success)
2903 {
2904 m_inst_mode = eModeInvalid;
2905 m_inst_pc = LLDB_INVALID_ADDRESS;
2906 }
2907 return success;
2908}
2909
Johnny Chenee9b1f72011-02-09 01:00:31 +00002910uint32_t
2911EmulateInstructionARM::ArchVersion ()
2912{
2913 return m_arm_isa;
2914}
2915
Greg Clayton64c84432011-01-21 22:02:52 +00002916bool
2917EmulateInstructionARM::ConditionPassed ()
2918{
2919 if (m_inst_cpsr == 0)
2920 return false;
2921
2922 const uint32_t cond = CurrentCond ();
2923
2924 if (cond == UINT32_MAX)
2925 return false;
2926
2927 bool result = false;
2928 switch (UnsignedBits(cond, 3, 1))
2929 {
2930 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2931 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2932 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2933 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2934 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2935 case 5:
2936 {
2937 bool n = (m_inst_cpsr & MASK_CPSR_N);
2938 bool v = (m_inst_cpsr & MASK_CPSR_V);
2939 result = n == v;
2940 }
2941 break;
2942 case 6:
2943 {
2944 bool n = (m_inst_cpsr & MASK_CPSR_N);
2945 bool v = (m_inst_cpsr & MASK_CPSR_V);
2946 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2947 }
2948 break;
2949 case 7:
2950 result = true;
2951 break;
2952 }
2953
2954 if (cond & 1)
2955 result = !result;
2956 return result;
2957}
2958
Johnny Chen9ee056b2011-02-08 00:06:35 +00002959uint32_t
2960EmulateInstructionARM::CurrentCond ()
2961{
2962 switch (m_inst_mode)
2963 {
2964 default:
2965 case eModeInvalid:
2966 break;
2967
2968 case eModeARM:
2969 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2970
2971 case eModeThumb:
2972 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2973 // 'cond' field of the encoding.
2974 if (m_inst.opcode_type == eOpcode16 &&
2975 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2976 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2977 {
2978 return Bits32(m_inst.opcode.inst16, 11, 7);
2979 }
2980 else if (m_inst.opcode_type == eOpcode32 &&
2981 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2982 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2983 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2984 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2985 {
2986 return Bits32(m_inst.opcode.inst32, 25, 22);
2987 }
2988
2989 return m_it_session.GetCond();
2990 }
2991 return UINT32_MAX; // Return invalid value
2992}
2993
Johnny Chen9ee056b2011-02-08 00:06:35 +00002994bool
2995EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2996{
2997 addr_t target;
2998
Johnny Chenee9b1f72011-02-09 01:00:31 +00002999 // Check the current instruction set.
3000 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003001 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003002 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003003 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003004
Johnny Chen9ee056b2011-02-08 00:06:35 +00003005 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003006 return false;
3007
3008 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003009}
3010
3011// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3012bool
3013EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
3014{
3015 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003016 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3017 // we want to record it and issue a WriteRegister callback so the clients
3018 // can track the mode changes accordingly.
3019 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003020
3021 if (BitIsSet(addr, 0))
3022 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003023 if (CurrentInstrSet() != eModeThumb)
3024 {
3025 SelectInstrSet(eModeThumb);
3026 cpsr_changed = true;
3027 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003028 target = addr & 0xfffffffe;
3029 context.arg2 = eModeThumb;
3030 }
3031 else if (BitIsClear(addr, 1))
3032 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003033 if (CurrentInstrSet() != eModeARM)
3034 {
3035 SelectInstrSet(eModeARM);
3036 cpsr_changed = true;
3037 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003038 target = addr & 0xfffffffc;
3039 context.arg2 = eModeARM;
3040 }
3041 else
3042 return false; // address<1:0> == '10' => UNPREDICTABLE
3043
Johnny Chen0f309db2011-02-09 19:11:32 +00003044 if (cpsr_changed)
3045 {
Johnny Chen558133b2011-02-09 23:59:17 +00003046 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003047 return false;
3048 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003049 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003050 return false;
3051
3052 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003053}
Greg Clayton64c84432011-01-21 22:02:52 +00003054
Johnny Chenee9b1f72011-02-09 01:00:31 +00003055// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3056bool
3057EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
3058{
3059 if (ArchVersion() >= ARMv5T)
3060 return BXWritePC(context, addr);
3061 else
3062 return BranchWritePC((const Context)context, addr);
3063}
3064
Johnny Chen26863dc2011-02-09 23:43:29 +00003065// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3066bool
3067EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
3068{
3069 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
3070 return BXWritePC(context, addr);
3071 else
3072 return BranchWritePC((const Context)context, addr);
3073}
3074
Johnny Chenee9b1f72011-02-09 01:00:31 +00003075EmulateInstructionARM::Mode
3076EmulateInstructionARM::CurrentInstrSet ()
3077{
3078 return m_inst_mode;
3079}
3080
3081// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003082// ReadInstruction() is performed. This function has a side effect of updating
3083// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003084bool
3085EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3086{
Johnny Chen558133b2011-02-09 23:59:17 +00003087 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003088 switch (arm_or_thumb)
3089 {
3090 default:
3091 return false;
3092 eModeARM:
3093 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003094 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003095 break;
3096 eModeThumb:
3097 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003098 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003099 break;
3100 }
3101 return true;
3102}
3103
Johnny Chenef21b592011-02-10 01:52:38 +00003104// This function returns TRUE if the processor currently provides support for
3105// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3106// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3107bool
3108EmulateInstructionARM::UnalignedSupport()
3109{
3110 return (ArchVersion() >= ARMv7);
3111}
3112
Johnny Chenbf6ad172011-02-11 01:29:53 +00003113// The main addition and subtraction instructions can produce status information
3114// about both unsigned carry and signed overflow conditions. This status
3115// information can be used to synthesize multi-word additions and subtractions.
3116EmulateInstructionARM::AddWithCarryResult
3117EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3118{
3119 uint32_t result;
3120 uint8_t carry_out;
3121 uint8_t overflow;
3122
3123 uint64_t unsigned_sum = x + y + carry_in;
3124 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3125
3126 result = UnsignedBits(unsigned_sum, 31, 0);
3127 carry_out = (result == unsigned_sum ? 0 : 1);
3128 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3129
3130 AddWithCarryResult res = { result, carry_out, overflow };
3131 return res;
3132}
3133
Greg Clayton64c84432011-01-21 22:02:52 +00003134bool
3135EmulateInstructionARM::EvaluateInstruction ()
3136{
Johnny Chenc315f862011-02-05 00:46:10 +00003137 // Advance the ITSTATE bits to their values for the next instruction.
3138 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3139 m_it_session.ITAdvance();
3140
Greg Clayton64c84432011-01-21 22:02:52 +00003141 return false;
3142}