blob: 278928d82bc673c5d43f371e5a8ce214ec50ed2a [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;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
369 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000370 break;
371 case eEncodingT3:
372 Rt = Bits32(opcode, 15, 12);
373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 if (Rt == 13)
375 return false;
376 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
378 registers = (1u << Rt);
379 break;
380 case eEncodingA1:
381 registers = Bits32(opcode, 15, 0);
382 // Instead of return false, let's handle the following case as well,
383 // which amounts to popping one reg from the full descending stacks.
384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
385
386 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 break;
390 case eEncodingA2:
391 Rt = Bits32(opcode, 15, 12);
392 // if t == 13 then UNPREDICTABLE;
393 if (Rt == dwarf_sp)
394 return false;
395 registers = (1u << Rt);
396 break;
397 default:
398 return false;
399 }
400 addr_t sp_offset = addr_byte_size * BitCount (registers);
401 addr_t addr = sp;
402 uint32_t i, data;
403
404 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
405 for (i=0; i<15; ++i)
406 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000407 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000408 {
409 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
410 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000411 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000412 if (!success)
413 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000415 return false;
416 addr += addr_byte_size;
417 }
418 }
419
Johnny Chen7c1bf922011-02-08 23:49:37 +0000420 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 {
422 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
423 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000424 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000425 if (!success)
426 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000427 // In ARMv5T and above, this is an interworking branch.
428 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000429 return false;
430 addr += addr_byte_size;
431 }
432
433 context.type = EmulateInstruction::eContextAdjustStackPointer;
434 context.arg0 = eRegisterKindGeneric;
435 context.arg1 = LLDB_REGNUM_GENERIC_SP;
436 context.arg2 = sp_offset;
437
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 }
441 return true;
442}
443
Johnny Chen5b442b72011-01-27 19:34:30 +0000444// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000445// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446bool
447EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448{
449#if 0
450 // ARM pseudo code...
451 if (ConditionPassed())
452 {
453 EncodingSpecificOperations();
454 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
455 if d == 15 then
456 ALUWritePC(result); // setflags is always FALSE here
457 else
458 R[d] = result;
459 if setflags then
460 APSR.N = result<31>;
461 APSR.Z = IsZeroBit(result);
462 APSR.C = carry;
463 APSR.V = overflow;
464 }
465#endif
466
467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if (!success)
470 return false;
471
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
494 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
495 eRegisterKindGeneric,
496 LLDB_REGNUM_GENERIC_SP,
497 sp_offset };
498
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000499 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000500 return false;
501 }
502 return true;
503}
504
Johnny Chen2ccad832011-01-28 19:57:25 +0000505// Set r7 or ip to the current stack pointer.
506// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000507bool
508EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000509{
510#if 0
511 // ARM pseudo code...
512 if (ConditionPassed())
513 {
514 EncodingSpecificOperations();
515 result = R[m];
516 if d == 15 then
517 ALUWritePC(result); // setflags is always FALSE here
518 else
519 R[d] = result;
520 if setflags then
521 APSR.N = result<31>;
522 APSR.Z = IsZeroBit(result);
523 // APSR.C unchanged
524 // APSR.V unchanged
525 }
526#endif
527
528 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000529 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000530 //if (!success)
531 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000532
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000533 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000534 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000536 if (!success)
537 return false;
538 uint32_t Rd; // the destination register
539 switch (encoding) {
540 case eEncodingT1:
541 Rd = 7;
542 break;
543 case eEncodingA1:
544 Rd = 12;
545 break;
546 default:
547 return false;
548 }
549 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
550 eRegisterKindGeneric,
551 LLDB_REGNUM_GENERIC_SP,
552 0 };
553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen1c13b622011-01-29 00:11:15 +0000560// Move from high register (r8-r15) to low register (r0-r7).
561// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
563EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000564{
Johnny Chen338bf542011-02-10 19:29:03 +0000565 return EmulateMovRdRm (encoding);
566}
567
568// Move from register to register.
569// MOV (register)
570bool
571EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
572{
Johnny Chen1c13b622011-01-29 00:11:15 +0000573#if 0
574 // ARM pseudo code...
575 if (ConditionPassed())
576 {
577 EncodingSpecificOperations();
578 result = R[m];
579 if d == 15 then
580 ALUWritePC(result); // setflags is always FALSE here
581 else
582 R[d] = result;
583 if setflags then
584 APSR.N = result<31>;
585 APSR.Z = IsZeroBit(result);
586 // APSR.C unchanged
587 // APSR.V unchanged
588 }
589#endif
590
591 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000592 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000593 if (!success)
594 return false;
595
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000596 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000597 {
598 uint32_t Rm; // the source register
599 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000600 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 switch (encoding) {
602 case eEncodingT1:
603 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000604 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000605 setflags = false;
606 break;
607 case eEncodingT2:
608 Rm = Bits32(opcode, 5, 3);
609 Rd = Bits32(opcode, 2, 1);
610 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 break;
612 default:
613 return false;
614 }
Johnny Chen338bf542011-02-10 19:29:03 +0000615 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000616 if (!success)
617 return false;
618
619 // The context specifies that Rm is to be moved into Rd.
620 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
621 eRegisterKindDWARF,
622 dwarf_r0 + Rm,
623 0 };
624
Johnny Chen338bf542011-02-10 19:29:03 +0000625 if (Rd == 15)
626 {
627 if (!ALUWritePC (context, reg_value))
628 return false;
629 }
630 else
631 {
632 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
633 return false;
634 if (setflags)
635 {
636 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000637 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
638 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000639 if (m_new_inst_cpsr != m_inst_cpsr)
640 {
641 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
642 return false;
643 }
644 }
645 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000646 }
647 return true;
648}
649
Johnny Chen788e0552011-01-27 22:52:23 +0000650// PC relative immediate load into register, possibly followed by ADD (SP plus register).
651// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000652bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000653EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000654{
655#if 0
656 // ARM pseudo code...
657 if (ConditionPassed())
658 {
659 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
660 base = Align(PC,4);
661 address = if add then (base + imm32) else (base - imm32);
662 data = MemU[address,4];
663 if t == 15 then
664 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
665 elsif UnalignedSupport() || address<1:0> = ‘00’ then
666 R[t] = data;
667 else // Can only apply before ARMv7
668 if CurrentInstrSet() == InstrSet_ARM then
669 R[t] = ROR(data, 8*UInt(address<1:0>));
670 else
671 R[t] = bits(32) UNKNOWN;
672 }
673#endif
674
675 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000676 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000677 if (!success)
678 return false;
679
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000680 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000681 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000682 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000683 if (!success)
684 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000685
686 // PC relative immediate load context
687 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
688 eRegisterKindGeneric,
689 LLDB_REGNUM_GENERIC_PC,
690 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000691 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000692 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000693 bool add; // +imm32 or -imm32?
694 addr_t base; // the base address
695 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000696 uint32_t data; // the literal data value from the PC relative load
697 switch (encoding) {
698 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000699 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000700 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000701 add = true;
702 base = Align(pc + 4, 4);
703 context.arg2 = 4 + imm32;
704 break;
705 case eEncodingT2:
706 Rt = Bits32(opcode, 15, 12);
707 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
708 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000709 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000710 return false;
711 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000712 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000713 break;
714 default:
715 return false;
716 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000717
718 if (add)
719 address = base + imm32;
720 else
721 address = base - imm32;
722 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000723 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000724 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000725
726 if (Rt == 15)
727 {
728 if (Bits32(address, 1, 0) == 0)
729 {
730 // In ARMv5T and above, this is an interworking branch.
731 if (!LoadWritePC(context, data))
732 return false;
733 }
734 else
735 return false;
736 }
737 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
738 {
739 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
740 return false;
741 }
742 else // We don't handle ARM for now.
743 return false;
744
745 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000746 return false;
747 }
748 return true;
749}
750
Johnny Chen5b442b72011-01-27 19:34:30 +0000751// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000752// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000753bool
754EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000755{
756#if 0
757 // ARM pseudo code...
758 if (ConditionPassed())
759 {
760 EncodingSpecificOperations();
761 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
762 if d == 15 then // Can only occur for ARM encoding
763 ALUWritePC(result); // setflags is always FALSE here
764 else
765 R[d] = result;
766 if setflags then
767 APSR.N = result<31>;
768 APSR.Z = IsZeroBit(result);
769 APSR.C = carry;
770 APSR.V = overflow;
771 }
772#endif
773
774 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000775 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000776 if (!success)
777 return false;
778
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000779 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000780 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000781 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000782 if (!success)
783 return false;
784 uint32_t imm32; // the immediate operand
785 switch (encoding) {
786 case eEncodingT2:
787 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
788 break;
789 default:
790 return false;
791 }
792 addr_t sp_offset = imm32;
793 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
794
795 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
796 eRegisterKindGeneric,
797 LLDB_REGNUM_GENERIC_SP,
798 sp_offset };
799
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000800 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000801 return false;
802 }
803 return true;
804}
805
806// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000807// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000808bool
809EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000810{
811#if 0
812 // ARM pseudo code...
813 if (ConditionPassed())
814 {
815 EncodingSpecificOperations();
816 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
817 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
818 if d == 15 then
819 ALUWritePC(result); // setflags is always FALSE here
820 else
821 R[d] = result;
822 if setflags then
823 APSR.N = result<31>;
824 APSR.Z = IsZeroBit(result);
825 APSR.C = carry;
826 APSR.V = overflow;
827 }
828#endif
829
830 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000831 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000832 if (!success)
833 return false;
834
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000835 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000836 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000837 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000838 if (!success)
839 return false;
840 uint32_t Rm; // the second operand
841 switch (encoding) {
842 case eEncodingT2:
843 Rm = Bits32(opcode, 6, 3);
844 break;
845 default:
846 return false;
847 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000848 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000849 if (!success)
850 return false;
851
852 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
853
854 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
855 eRegisterKindGeneric,
856 LLDB_REGNUM_GENERIC_SP,
857 reg_value };
858
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000859 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000860 return false;
861 }
862 return true;
863}
864
Johnny Chen9b8d7832011-02-02 01:13:56 +0000865// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
866// at a PC-relative address, and changes instruction set from ARM to Thumb, or
867// from Thumb to ARM.
868// BLX (immediate)
869bool
870EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
871{
872#if 0
873 // ARM pseudo code...
874 if (ConditionPassed())
875 {
876 EncodingSpecificOperations();
877 if CurrentInstrSet() == InstrSet_ARM then
878 LR = PC - 4;
879 else
880 LR = PC<31:1> : '1';
881 if targetInstrSet == InstrSet_ARM then
882 targetAddress = Align(PC,4) + imm32;
883 else
884 targetAddress = PC + imm32;
885 SelectInstrSet(targetInstrSet);
886 BranchWritePC(targetAddress);
887 }
888#endif
889
890 bool success = false;
891 const uint32_t opcode = OpcodeAsUnsigned (&success);
892 if (!success)
893 return false;
894
895 if (ConditionPassed())
896 {
897 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
898 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000899 if (!success)
900 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000901 addr_t lr; // next instruction address
902 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000903 int32_t imm32; // PC-relative offset
904 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000905 case eEncodingT1:
906 {
907 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000908 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +0000909 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000910 uint32_t J1 = Bit32(opcode, 13);
911 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +0000912 uint32_t imm11 = Bits32(opcode, 10, 0);
913 uint32_t I1 = !(J1 ^ S);
914 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000915 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000916 imm32 = llvm::SignExtend32<25>(imm25);
917 target = pc + 4 + imm32;
918 context.arg1 = 4 + imm32; // signed offset
919 context.arg2 = eModeThumb; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +0000920 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +0000921 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +0000922 break;
923 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000924 case eEncodingT2:
925 {
926 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000927 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000928 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000929 uint32_t J1 = Bit32(opcode, 13);
930 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000931 uint32_t imm10L = Bits32(opcode, 10, 1);
932 uint32_t I1 = !(J1 ^ S);
933 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000934 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000935 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000936 target = Align(pc + 4, 4) + imm32;
937 context.arg1 = 4 + imm32; // signed offset
938 context.arg2 = eModeARM; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +0000939 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +0000940 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000941 break;
942 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000943 case eEncodingA1:
944 lr = pc + 4; // return address
945 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000946 target = Align(pc + 8, 4) + imm32;
947 context.arg1 = 8 + imm32; // signed offset
948 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000949 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000950 case eEncodingA2:
951 lr = pc + 4; // return address
952 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
953 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000954 context.arg1 = 8 + imm32; // signed offset
955 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000956 break;
957 default:
958 return false;
959 }
960 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
961 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000962 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000963 return false;
964 }
965 return true;
966}
967
968// Branch with Link and Exchange (register) calls a subroutine at an address and
969// instruction set specified by a register.
970// BLX (register)
971bool
972EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
973{
974#if 0
975 // ARM pseudo code...
976 if (ConditionPassed())
977 {
978 EncodingSpecificOperations();
979 target = R[m];
980 if CurrentInstrSet() == InstrSet_ARM then
981 next_instr_addr = PC - 4;
982 LR = next_instr_addr;
983 else
984 next_instr_addr = PC - 2;
985 LR = next_instr_addr<31:1> : ‘1’;
986 BXWritePC(target);
987 }
988#endif
989
990 bool success = false;
991 const uint32_t opcode = OpcodeAsUnsigned (&success);
992 if (!success)
993 return false;
994
995 if (ConditionPassed())
996 {
997 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
998 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
999 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001000 if (!success)
1001 return false;
1002 uint32_t Rm; // the register with the target address
1003 switch (encoding) {
1004 case eEncodingT1:
1005 lr = (pc + 2) | 1u; // return address
1006 Rm = Bits32(opcode, 6, 3);
1007 // if m == 15 then UNPREDICTABLE;
1008 if (Rm == 15)
1009 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001010 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001011 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001012 break;
1013 case eEncodingA1:
1014 lr = pc + 4; // return address
1015 Rm = Bits32(opcode, 3, 0);
1016 // if m == 15 then UNPREDICTABLE;
1017 if (Rm == 15)
1018 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001019 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001020 default:
1021 return false;
1022 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001023 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1024 if (!success)
1025 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001026 context.arg0 = eRegisterKindDWARF;
1027 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001028 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1029 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001030 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001031 return false;
1032 }
1033 return true;
1034}
1035
Johnny Chenab3b3512011-02-12 00:10:51 +00001036// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1037// BX
1038bool
1039EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1040{
1041#if 0
1042 // ARM pseudo code...
1043 if (ConditionPassed())
1044 {
1045 EncodingSpecificOperations();
1046 BXWritePC(R[m]);
1047 }
1048#endif
1049
1050 bool success = false;
1051 const uint32_t opcode = OpcodeAsUnsigned (&success);
1052 if (!success)
1053 return false;
1054
1055 if (ConditionPassed())
1056 {
1057 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1058 uint32_t Rm; // the register with the target address
1059 switch (encoding) {
1060 case eEncodingT1:
1061 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001062 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001063 return false;
1064 break;
1065 case eEncodingA1:
1066 Rm = Bits32(opcode, 3, 0);
1067 break;
1068 default:
1069 return false;
1070 }
1071 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1072 if (!success)
1073 return false;
1074 context.arg0 = eRegisterKindDWARF;
1075 context.arg1 = dwarf_r0 + Rm;
1076 if (!BXWritePC(context, target))
1077 return false;
1078 }
1079 return true;
1080}
1081
Johnny Chen0d0148e2011-01-28 02:26:08 +00001082// Set r7 to point to some ip offset.
1083// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001084bool
1085EmulateInstructionARM::EmulateSubR7IPImmediate (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 ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 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 ip_offset = imm32;
1124 addr_t addr = ip - ip_offset; // the adjusted ip value
1125
1126 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1127 eRegisterKindDWARF,
1128 dwarf_r12,
1129 -ip_offset };
1130
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001131 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001132 return false;
1133 }
1134 return true;
1135}
1136
1137// Set ip to point to some stack offset.
1138// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001139bool
1140EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001141{
1142#if 0
1143 // ARM pseudo code...
1144 if (ConditionPassed())
1145 {
1146 EncodingSpecificOperations();
1147 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1148 if d == 15 then // Can only occur for ARM encoding
1149 ALUWritePC(result); // setflags is always FALSE here
1150 else
1151 R[d] = result;
1152 if setflags then
1153 APSR.N = result<31>;
1154 APSR.Z = IsZeroBit(result);
1155 APSR.C = carry;
1156 APSR.V = overflow;
1157 }
1158#endif
1159
1160 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001161 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001162 if (!success)
1163 return false;
1164
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001165 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001166 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001167 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001168 if (!success)
1169 return false;
1170 uint32_t imm32;
1171 switch (encoding) {
1172 case eEncodingA1:
1173 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1174 break;
1175 default:
1176 return false;
1177 }
1178 addr_t sp_offset = imm32;
1179 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1180
1181 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1182 eRegisterKindGeneric,
1183 LLDB_REGNUM_GENERIC_SP,
1184 -sp_offset };
1185
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001187 return false;
1188 }
1189 return true;
1190}
1191
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001192// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001193bool
1194EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001195{
1196#if 0
1197 // ARM pseudo code...
1198 if (ConditionPassed())
1199 {
1200 EncodingSpecificOperations();
1201 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1202 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001203 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001204 else
1205 R[d] = result;
1206 if setflags then
1207 APSR.N = result<31>;
1208 APSR.Z = IsZeroBit(result);
1209 APSR.C = carry;
1210 APSR.V = overflow;
1211 }
1212#endif
1213
1214 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001215 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001216 if (!success)
1217 return false;
1218
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001219 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001220 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001221 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001222 if (!success)
1223 return false;
1224 uint32_t imm32;
1225 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001226 case eEncodingT1:
1227 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001228 case eEncodingT2:
1229 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1230 break;
1231 case eEncodingT3:
1232 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1233 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001234 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001235 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001236 break;
1237 default:
1238 return false;
1239 }
1240 addr_t sp_offset = imm32;
1241 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1242
1243 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1244 eRegisterKindGeneric,
1245 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001246 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001247
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001248 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001249 return false;
1250 }
1251 return true;
1252}
1253
Johnny Chen08c25e82011-01-31 18:02:28 +00001254// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001255bool
1256EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001257{
1258#if 0
1259 // ARM pseudo code...
1260 if (ConditionPassed())
1261 {
1262 EncodingSpecificOperations();
1263 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1264 address = if index then offset_addr else R[n];
1265 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1266 if wback then R[n] = offset_addr;
1267 }
1268#endif
1269
1270 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001271 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001272 if (!success)
1273 return false;
1274
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001275 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001276 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001277 const uint32_t addr_byte_size = GetAddressByteSize();
1278 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001279 if (!success)
1280 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001281 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001282 uint32_t imm12;
1283 switch (encoding) {
1284 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001285 Rt = Bits32(opcode, 15, 12);
1286 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001287 break;
1288 default:
1289 return false;
1290 }
1291 addr_t sp_offset = imm12;
1292 addr_t addr = sp - sp_offset;
1293
1294 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001295 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001296 {
Johnny Chen91d99862011-01-25 19:07:04 +00001297 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1298 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001299 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001300 if (!success)
1301 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001302 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001303 return false;
1304 }
1305 else
1306 {
1307 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1308 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001309 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001310 if (!success)
1311 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001312 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001313 return false;
1314 }
1315
1316 context.type = EmulateInstruction::eContextAdjustStackPointer;
1317 context.arg0 = eRegisterKindGeneric;
1318 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001319 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001320
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001321 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001322 return false;
1323 }
1324 return true;
1325}
1326
Johnny Chen08c25e82011-01-31 18:02:28 +00001327// Vector Push stores multiple extension registers to the stack.
1328// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001329bool
1330EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001331{
1332#if 0
1333 // ARM pseudo code...
1334 if (ConditionPassed())
1335 {
1336 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1337 address = SP - imm32;
1338 SP = SP - imm32;
1339 if single_regs then
1340 for r = 0 to regs-1
1341 MemA[address,4] = S[d+r]; address = address+4;
1342 else
1343 for r = 0 to regs-1
1344 // Store as two word-aligned words in the correct order for current endianness.
1345 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1346 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1347 address = address+8;
1348 }
1349#endif
1350
1351 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001352 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001353 if (!success)
1354 return false;
1355
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001356 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001357 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001358 const uint32_t addr_byte_size = GetAddressByteSize();
1359 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001360 if (!success)
1361 return false;
1362 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001363 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001364 uint32_t imm32; // stack offset
1365 uint32_t regs; // number of registers
1366 switch (encoding) {
1367 case eEncodingT1:
1368 case eEncodingA1:
1369 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001370 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001371 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1372 // If UInt(imm8) is odd, see "FSTMX".
1373 regs = Bits32(opcode, 7, 0) / 2;
1374 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1375 if (regs == 0 || regs > 16 || (d + regs) > 32)
1376 return false;
1377 break;
1378 case eEncodingT2:
1379 case eEncodingA2:
1380 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001381 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001382 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1383 regs = Bits32(opcode, 7, 0);
1384 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1385 if (regs == 0 || regs > 16 || (d + regs) > 32)
1386 return false;
1387 break;
1388 default:
1389 return false;
1390 }
1391 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1392 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1393 addr_t sp_offset = imm32;
1394 addr_t addr = sp - sp_offset;
1395 uint32_t i;
1396
1397 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1398 for (i=d; i<regs; ++i)
1399 {
1400 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1401 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1402 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001403 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001404 if (!success)
1405 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001406 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001407 return false;
1408 addr += reg_byte_size;
1409 }
1410
1411 context.type = EmulateInstruction::eContextAdjustStackPointer;
1412 context.arg0 = eRegisterKindGeneric;
1413 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001414 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001415
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001416 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001417 return false;
1418 }
1419 return true;
1420}
1421
Johnny Chen587a0a42011-02-01 18:35:28 +00001422// Vector Pop loads multiple extension registers from the stack.
1423// It also updates SP to point just above the loaded data.
1424bool
1425EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1426{
1427#if 0
1428 // ARM pseudo code...
1429 if (ConditionPassed())
1430 {
1431 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1432 address = SP;
1433 SP = SP + imm32;
1434 if single_regs then
1435 for r = 0 to regs-1
1436 S[d+r] = MemA[address,4]; address = address+4;
1437 else
1438 for r = 0 to regs-1
1439 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1440 // Combine the word-aligned words in the correct order for current endianness.
1441 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1442 }
1443#endif
1444
1445 bool success = false;
1446 const uint32_t opcode = OpcodeAsUnsigned (&success);
1447 if (!success)
1448 return false;
1449
1450 if (ConditionPassed())
1451 {
1452 const uint32_t addr_byte_size = GetAddressByteSize();
1453 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1454 if (!success)
1455 return false;
1456 bool single_regs;
1457 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1458 uint32_t imm32; // stack offset
1459 uint32_t regs; // number of registers
1460 switch (encoding) {
1461 case eEncodingT1:
1462 case eEncodingA1:
1463 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001464 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001465 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1466 // If UInt(imm8) is odd, see "FLDMX".
1467 regs = Bits32(opcode, 7, 0) / 2;
1468 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1469 if (regs == 0 || regs > 16 || (d + regs) > 32)
1470 return false;
1471 break;
1472 case eEncodingT2:
1473 case eEncodingA2:
1474 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001475 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001476 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1477 regs = Bits32(opcode, 7, 0);
1478 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1479 if (regs == 0 || regs > 16 || (d + regs) > 32)
1480 return false;
1481 break;
1482 default:
1483 return false;
1484 }
1485 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1486 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1487 addr_t sp_offset = imm32;
1488 addr_t addr = sp;
1489 uint32_t i;
1490 uint64_t data; // uint64_t to accomodate 64-bit registers.
1491
1492 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1493 for (i=d; i<regs; ++i)
1494 {
1495 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1496 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1497 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1498 if (!success)
1499 return false;
1500 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1501 return false;
1502 addr += reg_byte_size;
1503 }
1504
1505 context.type = EmulateInstruction::eContextAdjustStackPointer;
1506 context.arg0 = eRegisterKindGeneric;
1507 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1508 context.arg2 = sp_offset;
1509
1510 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1511 return false;
1512 }
1513 return true;
1514}
1515
Johnny Chenb77be412011-02-04 00:40:18 +00001516// SVC (previously SWI)
1517bool
1518EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1519{
1520#if 0
1521 // ARM pseudo code...
1522 if (ConditionPassed())
1523 {
1524 EncodingSpecificOperations();
1525 CallSupervisor();
1526 }
1527#endif
1528
1529 bool success = false;
1530 const uint32_t opcode = OpcodeAsUnsigned (&success);
1531 if (!success)
1532 return false;
1533
1534 if (ConditionPassed())
1535 {
1536 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1537 addr_t lr; // next instruction address
1538 if (!success)
1539 return false;
1540 uint32_t imm32; // the immediate constant
1541 uint32_t mode; // ARM or Thumb mode
1542 switch (encoding) {
1543 case eEncodingT1:
1544 lr = (pc + 2) | 1u; // return address
1545 imm32 = Bits32(opcode, 7, 0);
1546 mode = eModeThumb;
1547 break;
1548 case eEncodingA1:
1549 lr = pc + 4; // return address
1550 imm32 = Bits32(opcode, 23, 0);
1551 mode = eModeARM;
1552 break;
1553 default:
1554 return false;
1555 }
1556 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1557 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1558 return false;
1559 }
1560 return true;
1561}
1562
Johnny Chenc315f862011-02-05 00:46:10 +00001563// If Then makes up to four following instructions (the IT block) conditional.
1564bool
1565EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1566{
1567#if 0
1568 // ARM pseudo code...
1569 EncodingSpecificOperations();
1570 ITSTATE.IT<7:0> = firstcond:mask;
1571#endif
1572
1573 bool success = false;
1574 const uint32_t opcode = OpcodeAsUnsigned (&success);
1575 if (!success)
1576 return false;
1577
1578 m_it_session.InitIT(Bits32(opcode, 7, 0));
1579 return true;
1580}
1581
Johnny Chen3b620b32011-02-07 20:11:47 +00001582// Branch causes a branch to a target address.
1583bool
1584EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1585{
1586#if 0
1587 // ARM pseudo code...
1588 if (ConditionPassed())
1589 {
1590 EncodingSpecificOperations();
1591 BranchWritePC(PC + imm32);
1592 }
1593#endif
1594
1595 bool success = false;
1596 const uint32_t opcode = OpcodeAsUnsigned (&success);
1597 if (!success)
1598 return false;
1599
Johnny Chen9ee056b2011-02-08 00:06:35 +00001600 if (ConditionPassed())
1601 {
1602 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1603 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001604 if (!success)
1605 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001606 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001607 int32_t imm32; // PC-relative offset
1608 switch (encoding) {
1609 case eEncodingT1:
1610 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1611 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1612 target = pc + 4 + imm32;
1613 context.arg1 = 4 + imm32; // signed offset
1614 context.arg2 = eModeThumb; // target instruction set
1615 break;
1616 case eEncodingT2:
1617 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1618 target = pc + 4 + imm32;
1619 context.arg1 = 4 + imm32; // signed offset
1620 context.arg2 = eModeThumb; // target instruction set
1621 break;
1622 case eEncodingT3:
1623 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1624 {
Johnny Chenbd599902011-02-10 21:39:01 +00001625 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001626 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001627 uint32_t J1 = Bit32(opcode, 13);
1628 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001629 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001630 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001631 imm32 = llvm::SignExtend32<21>(imm21);
1632 target = pc + 4 + imm32;
1633 context.arg1 = eModeThumb; // target instruction set
1634 context.arg2 = 4 + imm32; // signed offset
1635 break;
1636 }
1637 case eEncodingT4:
1638 {
Johnny Chenbd599902011-02-10 21:39:01 +00001639 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001640 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001641 uint32_t J1 = Bit32(opcode, 13);
1642 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001643 uint32_t imm11 = Bits32(opcode, 10, 0);
1644 uint32_t I1 = !(J1 ^ S);
1645 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001646 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001647 imm32 = llvm::SignExtend32<25>(imm25);
1648 target = pc + 4 + imm32;
1649 context.arg1 = eModeThumb; // target instruction set
1650 context.arg2 = 4 + imm32; // signed offset
1651 break;
1652 }
1653 case eEncodingA1:
1654 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1655 target = pc + 8 + imm32;
1656 context.arg1 = eModeARM; // target instruction set
1657 context.arg2 = 8 + imm32; // signed offset
1658 break;
1659 default:
1660 return false;
1661 }
1662 if (!BranchWritePC(context, target))
1663 return false;
1664 }
1665 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001666}
1667
Johnny Chen53ebab72011-02-08 23:21:57 +00001668// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1669// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1670// CBNZ, CBZ
1671bool
1672EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1673{
1674#if 0
1675 // ARM pseudo code...
1676 EncodingSpecificOperations();
1677 if nonzero ^ IsZero(R[n]) then
1678 BranchWritePC(PC + imm32);
1679#endif
1680
1681 bool success = false;
1682 const uint32_t opcode = OpcodeAsUnsigned (&success);
1683 if (!success)
1684 return false;
1685
1686 // Read the register value from the operand register Rn.
1687 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1688 if (!success)
1689 return false;
1690
1691 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1692 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1693 if (!success)
1694 return false;
1695
1696 addr_t target; // target address
1697 uint32_t imm32; // PC-relative offset to branch forward
1698 bool nonzero;
1699 switch (encoding) {
1700 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001701 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001702 nonzero = BitIsSet(opcode, 11);
1703 target = pc + 4 + imm32;
1704 context.arg1 = 4 + imm32; // signed offset
1705 context.arg2 = eModeThumb; // target instruction set
1706 break;
1707 default:
1708 return false;
1709 }
1710 if (nonzero ^ (reg_val == 0))
1711 if (!BranchWritePC(context, target))
1712 return false;
1713
1714 return true;
1715}
1716
Johnny Chen26863dc2011-02-09 23:43:29 +00001717// ADD <Rdn>, <Rm>
1718// where <Rdn> the destination register is also the first operand register
1719// and <Rm> is the second operand register.
1720bool
1721EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1722{
1723#if 0
1724 // ARM pseudo code...
1725 if ConditionPassed() then
1726 EncodingSpecificOperations();
1727 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1728 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1729 if d == 15 then
1730 ALUWritePC(result); // setflags is always FALSE here
1731 else
1732 R[d] = result;
1733 if setflags then
1734 APSR.N = result<31>;
1735 APSR.Z = IsZeroBit(result);
1736 APSR.C = carry;
1737 APSR.V = overflow;
1738#endif
1739
1740 bool success = false;
1741 const uint32_t opcode = OpcodeAsUnsigned (&success);
1742 if (!success)
1743 return false;
1744
1745 if (ConditionPassed())
1746 {
1747 uint32_t Rd, Rn, Rm;
1748 //bool setflags = false;
1749 switch (encoding)
1750 {
1751 case eEncodingT2:
1752 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001753 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001754 Rm = Bits32(opcode, 6, 3);
1755 if (Rn == 15 && Rm == 15)
1756 return false;
1757 break;
1758 default:
1759 return false;
1760 }
1761
1762 int32_t result, val1, val2;
1763 // Read the first operand.
1764 if (Rn == 15)
1765 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1766 else
1767 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1768 if (!success)
1769 return false;
1770
1771 // Read the second operand.
1772 if (Rm == 15)
1773 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1774 else
1775 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1776 if (!success)
1777 return false;
1778
1779 result = val1 + val2;
1780 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1781 result,
1782 0,
1783 0 };
1784
1785 if (Rd == 15)
1786 {
1787 if (!ALUWritePC (context, result))
1788 return false;
1789 }
1790 else
1791 {
1792 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1793 return false;
1794 }
1795 }
1796 return true;
1797}
1798
Johnny Chene4a4d302011-02-11 21:53:58 +00001799// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001800bool
1801EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1802{
1803#if 0
1804 // ARM pseudo code...
1805 if ConditionPassed() then
1806 EncodingSpecificOperations();
1807 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1808 APSR.N = result<31>;
1809 APSR.Z = IsZeroBit(result);
1810 APSR.C = carry;
1811 APSR.V = overflow;
1812#endif
1813
1814 bool success = false;
1815 const uint32_t opcode = OpcodeAsUnsigned (&success);
1816 if (!success)
1817 return false;
1818
1819 uint32_t Rn; // the first operand
1820 uint32_t imm32; // the immediate value to be compared with
1821 switch (encoding) {
1822 case eEncodingT1:
1823 Rn = Bits32(opcode, 10, 8);
1824 imm32 = Bits32(opcode, 7, 0);
1825 break;
1826 default:
1827 return false;
1828 }
1829 // Read the register value from the operand register Rn.
1830 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1831 if (!success)
1832 return false;
1833
1834 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1835 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1836 m_new_inst_cpsr = m_inst_cpsr;
1837 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1838 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1839 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1840 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1841 if (m_new_inst_cpsr != m_inst_cpsr)
1842 {
1843 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1844 return false;
1845 }
1846 return true;
1847}
1848
Johnny Chene4a4d302011-02-11 21:53:58 +00001849// CMP (register)
1850bool
1851EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1852{
1853#if 0
1854 // ARM pseudo code...
1855 if ConditionPassed() then
1856 EncodingSpecificOperations();
1857 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1858 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1859 APSR.N = result<31>;
1860 APSR.Z = IsZeroBit(result);
1861 APSR.C = carry;
1862 APSR.V = overflow;
1863#endif
1864
1865 bool success = false;
1866 const uint32_t opcode = OpcodeAsUnsigned (&success);
1867 if (!success)
1868 return false;
1869
1870 uint32_t Rn; // the first operand
1871 uint32_t Rm; // the second operand
1872 switch (encoding) {
1873 case eEncodingT1:
1874 Rn = Bits32(opcode, 2, 0);
1875 Rm = Bits32(opcode, 5, 3);
1876 break;
1877 case eEncodingT2:
1878 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1879 Rm = Bits32(opcode, 6, 3);
1880 if (Rn < 8 && Rm < 8)
1881 return false;
1882 if (Rn == 15 || Rm == 15)
1883 return false;
1884 break;
1885 default:
1886 return false;
1887 }
1888 // Read the register value from register Rn.
1889 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1890 if (!success)
1891 return false;
1892 // Read the register value from register Rm.
1893 // The register value is not being shifted since we don't handle ARM for now.
1894 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1895 if (!success)
1896 return false;
1897
1898 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1899 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
1900 m_new_inst_cpsr = m_inst_cpsr;
1901 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1902 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1903 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1904 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1905 if (m_new_inst_cpsr != m_inst_cpsr)
1906 {
1907 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1908 return false;
1909 }
1910 return true;
1911}
1912
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001913// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00001914// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001915// can be written back to the base register.
1916bool
1917EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1918{
1919#if 0
1920 // ARM pseudo code...
1921 if ConditionPassed()
1922 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1923 address = R[n];
1924
1925 for i = 0 to 14
1926 if registers<i> == '1' then
1927 R[i] = MemA[address, 4]; address = address + 4;
1928 if registers<15> == '1' then
1929 LoadWritePC (MemA[address, 4]);
1930
1931 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1932 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1933
1934#endif
1935
1936 bool success = false;
1937 const uint32_t opcode = OpcodeAsUnsigned (&success);
1938 if (!success)
1939 return false;
1940
1941 if (ConditionPassed())
1942 {
1943 uint32_t n;
1944 uint32_t registers = 0;
1945 bool wback;
1946 const uint32_t addr_byte_size = GetAddressByteSize();
1947 switch (encoding)
1948 {
1949 case eEncodingT1:
1950 n = Bits32 (opcode, 10, 8);
1951 registers = Bits32 (opcode, 7, 0);
1952 wback = BitIsClear (registers, n);
1953 // if BitCount(registers) < 1 then UNPREDICTABLE;
1954 if (BitCount(registers) < 1)
1955 return false;
1956 break;
1957 case eEncodingT2:
1958 n = Bits32 (opcode, 19, 16);
1959 registers = Bits32 (opcode, 15, 0);
1960 wback = BitIsSet (opcode, 21);
1961 if ((n == 15)
1962 || (BitCount (registers) < 2)
1963 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1964 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001965 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001966 return false;
1967 if (wback
1968 && BitIsSet (registers, n))
1969 return false;
1970 break;
1971 case eEncodingA1:
1972 n = Bits32 (opcode, 19, 16);
1973 registers = Bits32 (opcode, 15, 0);
1974 wback = BitIsSet (opcode, 21);
1975 if ((n == 15)
1976 || (BitCount (registers) < 1))
1977 return false;
1978 break;
1979 default:
1980 return false;
1981 }
1982
1983 int32_t offset = 0;
1984 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1985 if (!success)
1986 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001987
1988 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1989 eRegisterKindDWARF,
1990 dwarf_r0 + n,
1991 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001992
1993 for (int i = 0; i < 14; ++i)
1994 {
1995 if (BitIsSet (registers, i))
1996 {
Caroline Tice85aab332011-02-08 23:56:10 +00001997 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1998 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001999 if (wback && (n == 13)) // Pop Instruction
2000 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2001
2002 // R[i] = MemA [address, 4]; address = address + 4;
2003 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2004 if (!success)
2005 return false;
2006
2007 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2008 return false;
2009
2010 offset += addr_byte_size;
2011 }
2012 }
2013
2014 if (BitIsSet (registers, 15))
2015 {
2016 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002017 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2018 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002019 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2020 if (!success)
2021 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002022 // In ARMv5T and above, this is an interworking branch.
2023 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002024 return false;
2025 }
2026
2027 if (wback && BitIsClear (registers, n))
2028 {
Caroline Ticefa172202011-02-11 22:49:54 +00002029 // R[n] = R[n] + 4 * BitCount (registers)
2030 int32_t offset = addr_byte_size * BitCount (registers);
2031 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice85aab332011-02-08 23:56:10 +00002032 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002033
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2035 return false;
2036 }
2037 if (wback && BitIsSet (registers, n))
2038 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002039 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002040 }
2041 return true;
2042}
Caroline Tice713c2662011-02-11 17:59:55 +00002043
2044// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2045// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2046// can optionally be written back tot he base registers.
2047bool
2048EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2049{
2050#if 0
2051 // ARM pseudo code...
2052 if ConditionPassed() then
2053 EncodingSpecificOperations();
2054 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002055
Caroline Tice713c2662011-02-11 17:59:55 +00002056 for i = 0 to 14
2057 if registers<i> == ’1’ then
2058 R[i] = MemA[address,4]; address = address + 4;
2059
2060 if registers<15> == ’1’ then
2061 LoadWritePC(MemA[address,4]);
2062
2063 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2064 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2065#endif
2066
2067 bool success = false;
2068 const uint32_t opcode = OpcodeAsUnsigned (&success);
2069 if (!success)
2070 return false;
2071
2072 if (ConditionPassed())
2073 {
2074 uint32_t n;
2075 uint32_t registers = 0;
2076 bool wback;
2077 const uint32_t addr_byte_size = GetAddressByteSize();
2078
2079 // EncodingSpecificOperations();
2080 switch (encoding)
2081 {
2082 case eEncodingA1:
2083 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2084 n = Bits32 (opcode, 19, 16);
2085 registers = Bits32 (opcode, 15, 0);
2086 wback = BitIsSet (opcode, 21);
2087
2088 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2089 if ((n == 15) || (BitCount (registers) < 1))
2090 return false;
2091
2092 break;
2093
2094 default:
2095 return false;
2096 }
2097 // address = R[n] - 4*BitCount(registers) + 4;
2098
2099 int32_t offset = 0;
2100 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2101
2102 if (!success)
2103 return false;
2104
2105 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2106
2107 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2108 eRegisterKindDWARF,
2109 dwarf_r0 + n,
2110 offset };
2111
2112 // for i = 0 to 14
2113 for (int i = 0; i < 14; ++i)
2114 {
2115 // if registers<i> == ’1’ then
2116 if (BitIsSet (registers, i))
2117 {
2118 // R[i] = MemA[address,4]; address = address + 4;
2119 context.arg2 = offset;
2120 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2121 if (!success)
2122 return false;
2123 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2124 return false;
2125 offset += addr_byte_size;
2126 }
2127 }
2128
2129 // if registers<15> == ’1’ then
2130 // LoadWritePC(MemA[address,4]);
2131 if (BitIsSet (registers, 15))
2132 {
2133 context.arg2 = offset;
2134 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2135 if (!success)
2136 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002137 // In ARMv5T and above, this is an interworking branch.
2138 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002139 return false;
2140 }
2141
2142 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2143 if (wback && BitIsClear (registers, n))
2144 {
Caroline Tice713c2662011-02-11 17:59:55 +00002145 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2146 if (!success)
2147 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002148
2149 offset = (addr_byte_size * BitCount (registers)) * -1;
2150 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2151 context.arg2 = offset;
2152 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002153 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2154 return false;
2155 }
2156
2157 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2158 if (wback && BitIsSet (registers, n))
2159 return WriteBits32Unknown (n);
2160 }
2161 return true;
2162}
2163
2164// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2165// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2166// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002167bool
2168EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2169{
2170#if 0
2171 // ARM pseudo code...
2172 if ConditionPassed() then
2173 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2174 address = R[n] - 4*BitCount(registers);
2175
2176 for i = 0 to 14
2177 if registers<i> == ’1’ then
2178 R[i] = MemA[address,4]; address = address + 4;
2179 if registers<15> == ’1’ then
2180 LoadWritePC(MemA[address,4]);
2181
2182 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2183 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2184#endif
2185
2186 bool success = false;
2187 const uint32_t opcode = OpcodeAsUnsigned (&success);
2188 if (!success)
2189 return false;
2190
2191 if (ConditionPassed())
2192 {
2193 uint32_t n;
2194 uint32_t registers = 0;
2195 bool wback;
2196 const uint32_t addr_byte_size = GetAddressByteSize();
2197 switch (encoding)
2198 {
2199 case eEncodingT1:
2200 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2201 n = Bits32 (opcode, 19, 16);
2202 registers = Bits32 (opcode, 15, 0);
2203 wback = BitIsSet (opcode, 21);
2204
2205 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2206 if ((n == 15)
2207 || (BitCount (registers) < 2)
2208 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2209 return false;
2210
2211 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002212 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002213 return false;
2214
2215 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2216 if (wback && BitIsSet (registers, n))
2217 return false;
2218
2219 break;
2220
2221 case eEncodingA1:
2222 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2223 n = Bits32 (opcode, 19, 16);
2224 registers = Bits32 (opcode, 15, 0);
2225 wback = BitIsSet (opcode, 21);
2226
2227 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2228 if ((n == 15) || (BitCount (registers) < 1))
2229 return false;
2230
2231 break;
2232
2233 default:
2234 return false;
2235 }
2236
Caroline Tice713c2662011-02-11 17:59:55 +00002237 // address = R[n] - 4*BitCount(registers);
2238
Caroline Tice0b29e242011-02-08 23:16:02 +00002239 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002240 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2241
2242 if (!success)
2243 return false;
2244
2245 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002246 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2247 eRegisterKindDWARF,
2248 dwarf_r0 + n,
2249 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002250
2251 for (int i = 0; i < 14; ++i)
2252 {
2253 if (BitIsSet (registers, i))
2254 {
2255 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002256 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002257 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2258 if (!success)
2259 return false;
2260
2261 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2262 return false;
2263
2264 offset += addr_byte_size;
2265 }
2266 }
2267
2268 // if registers<15> == ’1’ then
2269 // LoadWritePC(MemA[address,4]);
2270 if (BitIsSet (registers, 15))
2271 {
Caroline Tice85aab332011-02-08 23:56:10 +00002272 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002273 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2274 if (!success)
2275 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002276 // In ARMv5T and above, this is an interworking branch.
2277 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002278 return false;
2279 }
2280
2281 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2282 if (wback && BitIsClear (registers, n))
2283 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002284 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2285 if (!success)
2286 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002287
2288 offset = (addr_byte_size * BitCount (registers)) * -1;
2289 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2290 context.arg2 = offset;
2291 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002292 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2293 return false;
2294 }
2295
2296 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2297 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002298 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002299 }
2300 return true;
2301}
Caroline Tice85aab332011-02-08 23:56:10 +00002302
Caroline Tice713c2662011-02-11 17:59:55 +00002303// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2304// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2305// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002306bool
2307EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2308{
2309#if 0
2310 if ConditionPassed() then
2311 EncodingSpecificOperations();
2312 address = R[n] + 4;
2313
2314 for i = 0 to 14
2315 if registers<i> == ’1’ then
2316 R[i] = MemA[address,4]; address = address + 4;
2317 if registers<15> == ’1’ then
2318 LoadWritePC(MemA[address,4]);
2319
2320 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2321 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2322#endif
2323
2324 bool success = false;
2325 const uint32_t opcode = OpcodeAsUnsigned (&success);
2326 if (!success)
2327 return false;
2328
2329 if (ConditionPassed())
2330 {
2331 uint32_t n;
2332 uint32_t registers = 0;
2333 bool wback;
2334 const uint32_t addr_byte_size = GetAddressByteSize();
2335 switch (encoding)
2336 {
2337 case eEncodingA1:
2338 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2339 n = Bits32 (opcode, 19, 16);
2340 registers = Bits32 (opcode, 15, 0);
2341 wback = BitIsSet (opcode, 21);
2342
2343 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2344 if ((n == 15) || (BitCount (registers) < 1))
2345 return false;
2346
2347 break;
2348 default:
2349 return false;
2350 }
2351 // address = R[n] + 4;
2352
2353 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002354 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2355
2356 if (!success)
2357 return false;
2358
2359 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002360
2361 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2362 eRegisterKindDWARF,
2363 dwarf_r0 + n,
2364 offset };
2365
2366 for (int i = 0; i < 14; ++i)
2367 {
2368 if (BitIsSet (registers, i))
2369 {
2370 // R[i] = MemA[address,4]; address = address + 4;
2371
2372 context.arg2 = offset;
2373 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2374 if (!success)
2375 return false;
2376
2377 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2378 return false;
2379
2380 offset += addr_byte_size;
2381 }
2382 }
2383
2384 // if registers<15> == ’1’ then
2385 // LoadWritePC(MemA[address,4]);
2386 if (BitIsSet (registers, 15))
2387 {
2388 context.arg2 = offset;
2389 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2390 if (!success)
2391 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002392 // In ARMv5T and above, this is an interworking branch.
2393 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002394 return false;
2395 }
2396
2397 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2398 if (wback && BitIsClear (registers, n))
2399 {
Caroline Tice85aab332011-02-08 23:56:10 +00002400 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2401 if (!success)
2402 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002403
2404 offset = addr_byte_size * BitCount (registers);
2405 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2406 context.arg2 = offset;
2407 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002408 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2409 return false;
2410 }
2411
2412 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2413 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002414 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002415 }
2416 return true;
2417}
Caroline Tice0b29e242011-02-08 23:16:02 +00002418
Johnny Chenef21b592011-02-10 01:52:38 +00002419// Load Register (immediate) calculates an address from a base register value and
2420// an immediate offset, loads a word from memory, and writes to a register.
2421// LDR (immediate, Thumb)
2422bool
2423EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2424{
2425#if 0
2426 // ARM pseudo code...
2427 if (ConditionPassed())
2428 {
2429 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2430 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2431 address = if index then offset_addr else R[n];
2432 data = MemU[address,4];
2433 if wback then R[n] = offset_addr;
2434 if t == 15 then
2435 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2436 elsif UnalignedSupport() || address<1:0> = '00' then
2437 R[t] = data;
2438 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2439 }
2440#endif
2441
2442 bool success = false;
2443 const uint32_t opcode = OpcodeAsUnsigned (&success);
2444 if (!success)
2445 return false;
2446
2447 if (ConditionPassed())
2448 {
2449 uint32_t Rt; // the destination register
2450 uint32_t Rn; // the base register
2451 uint32_t imm32; // the immediate offset used to form the address
2452 addr_t offset_addr; // the offset address
2453 addr_t address; // the calculated address
2454 uint32_t data; // the literal data value from memory load
2455 bool add, index, wback;
2456 switch (encoding) {
2457 case eEncodingT1:
2458 Rt = Bits32(opcode, 5, 3);
2459 Rn = Bits32(opcode, 2, 0);
2460 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2461 // index = TRUE; add = TRUE; wback = FALSE
2462 add = true;
2463 index = true;
2464 wback = false;
2465 break;
2466 default:
2467 return false;
2468 }
2469 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2470 if (!success)
2471 return false;
2472 if (add)
2473 offset_addr = base + imm32;
2474 else
2475 offset_addr = base - imm32;
2476
2477 address = (index ? offset_addr : base);
2478
2479 if (wback)
2480 {
2481 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2482 eRegisterKindDWARF,
2483 dwarf_r0 + Rn,
2484 (int32_t) (offset_addr - base)};
2485 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2486 return false;
2487 }
2488
2489 // Prepare to write to the Rt register.
2490 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2491 0,
2492 0,
2493 0};
2494
2495 // Read memory from the address.
2496 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2497 if (!success)
2498 return false;
2499 context.arg0 = data;
2500
2501 if (Rt == 15)
2502 {
2503 if (Bits32(address, 1, 0) == 0)
2504 {
2505 if (!LoadWritePC(context, data))
2506 return false;
2507 }
2508 else
2509 return false;
2510 }
2511 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2512 {
2513 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2514 return false;
2515 }
2516 else
2517 return false;
2518 }
2519 return true;
2520}
2521
Caroline Ticefa172202011-02-11 22:49:54 +00002522// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2523// consecutive memory locations start at this address, and teh address just above the last of those locations can
2524// optionally be written back to the base register.
2525bool
2526EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2527{
2528#if 0
2529 if ConditionPassed() then
2530 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2531 address = R[n];
2532
2533 for i = 0 to 14
2534 if registers<i> == ’1’ then
2535 if i == n && wback && i != LowestSetBit(registers) then
2536 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2537 else
2538 MemA[address,4] = R[i];
2539 address = address + 4;
2540
2541 if registers<15> == ’1’ then // Only possible for encoding A1
2542 MemA[address,4] = PCStoreValue();
2543 if wback then R[n] = R[n] + 4*BitCount(registers);
2544#endif
2545
2546 bool success = false;
2547 const uint32_t opcode = OpcodeAsUnsigned (&success);
2548 if (!success)
2549 return false;
2550
2551 if (ConditionPassed ())
2552 {
2553 uint32_t n;
2554 uint32_t registers = 0;
2555 bool wback;
2556 const uint32_t addr_byte_size = GetAddressByteSize();
2557
2558 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2559 switch (encoding)
2560 {
2561 case eEncodingT1:
2562 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2563 n = Bits32 (opcode, 10, 8);
2564 registers = Bits32 (opcode, 7, 0);
2565 wback = true;
2566
2567 // if BitCount(registers) < 1 then UNPREDICTABLE;
2568 if (BitCount (registers) < 1)
2569 return false;
2570
2571 break;
2572
2573 case eEncodingT2:
2574 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2575 n = Bits32 (opcode, 19, 16);
2576 registers = Bits32 (opcode, 15, 0);
2577 wback = BitIsSet (opcode, 21);
2578
2579 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2580 if ((n == 15) || (BitCount (registers) < 2))
2581 return false;
2582
2583 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2584 if (wback && BitIsSet (registers, n))
2585 return false;
2586
2587 break;
2588
2589 case eEncodingA1:
2590 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2591 n = Bits32 (opcode, 19, 16);
2592 registers = Bits32 (opcode, 15, 0);
2593 wback = BitIsSet (opcode, 21);
2594
2595 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2596 if ((n == 15) || (BitCount (registers) < 1))
2597 return false;
2598
2599 break;
2600
2601 default:
2602 return false;
2603 }
2604
2605 // address = R[n];
2606 int32_t offset = 0;
2607 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2608 if (!success)
2609 return false;
2610
2611 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterStore,
2612 eRegisterKindDWARF,
2613 dwarf_r0 + n,
2614 offset };
2615
2616 // for i = 0 to 14
2617 for (int i = 0; i < 14; ++i)
2618 {
2619 int lowest_set_bit = 14;
2620 // if registers<i> == ’1’ then
2621 if (BitIsSet (registers, i))
2622 {
2623 if (i < lowest_set_bit)
2624 lowest_set_bit = i;
2625 // if i == n && wback && i != LowestSetBit(registers) then
2626 if ((i == n) && wback && (i != lowest_set_bit))
2627 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2628 WriteBits32UnknownToMemory (address + offset);
2629 else
2630 {
2631 // MemA[address,4] = R[i];
2632 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2633 if (!success)
2634 return false;
2635
2636 context.arg1 = dwarf_r0 + i;
2637 context.arg2 = address + offset;
2638 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2639 return false;
2640 }
2641
2642 // address = address + 4;
2643 offset += addr_byte_size;
2644 }
2645 }
2646
2647 // if registers<15> == ’1’ then // Only possible for encoding A1
2648 // MemA[address,4] = PCStoreValue();
2649 if (BitIsSet (registers, 15))
2650 {
2651 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2652 if (!success)
2653 return false;
2654
2655 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
2656 context.arg2 = address + offset - sp; // arg2 in the context is the stack pointer offset
2657 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2658 if (!success)
2659 return false;
2660
2661 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2662 return false;
2663 }
2664
2665 // if wback then R[n] = R[n] + 4*BitCount(registers);
2666 if (wback)
2667 {
2668 offset = addr_byte_size * BitCount (registers);
2669 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2670 context.arg1 = dwarf_r0 + n;
2671 context.arg2 = offset;
2672 addr_t data = address + offset;
2673 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2674 return false;
2675 }
2676 }
2677 return true;
2678}
2679
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002680EmulateInstructionARM::ARMOpcode*
2681EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002682{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002683 static ARMOpcode
2684 g_arm_opcodes[] =
2685 {
2686 //----------------------------------------------------------------------
2687 // Prologue instructions
2688 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002689
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002690 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002691 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2692 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002693
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002694 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002695 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2696 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002697 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002698 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2699 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2700 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002701
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002702 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002703 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002704
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002705 // push one register
2706 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002707 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002708
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002709 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002710 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2711 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002712
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002713 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002714 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002715 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002716
Johnny Chenc28a76d2011-02-01 18:51:48 +00002717 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2718 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002719 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002720 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2721
2722 //----------------------------------------------------------------------
2723 // Supervisor Call (previously Software Interrupt)
2724 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002725 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2726
2727 //----------------------------------------------------------------------
2728 // Branch instructions
2729 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002730 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002731 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2732 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2733 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2734 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002735 // for example, "bx lr"
2736 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002737
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002738 //----------------------------------------------------------------------
2739 // Load instructions
2740 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002741 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002742 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002743 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002744 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2745
2746 //----------------------------------------------------------------------
2747 // Store instructions
2748 //----------------------------------------------------------------------
2749 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002750
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002751 };
2752 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2753
2754 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2755 {
2756 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2757 return &g_arm_opcodes[i];
2758 }
2759 return NULL;
2760}
Greg Clayton64c84432011-01-21 22:02:52 +00002761
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002762
2763EmulateInstructionARM::ARMOpcode*
2764EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002765{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002766
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002767 static ARMOpcode
2768 g_thumb_opcodes[] =
2769 {
2770 //----------------------------------------------------------------------
2771 // Prologue instructions
2772 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002773
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002774 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002775 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002776 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2777 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002778
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002779 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002780 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002781 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002782 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002783 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2784 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002785
Johnny Chenc9de9102011-02-11 19:12:30 +00002786 // PC-relative load into register (see also EmulateAddSPRm)
2787 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002788
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002789 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002790 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2791 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002792 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2793 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002794
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002795 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002796 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2797 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002798
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002799 //----------------------------------------------------------------------
2800 // Epilogue instructions
2801 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002802
Johnny Chenc28a76d2011-02-01 18:51:48 +00002803 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2804 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002805 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2806 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2807 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2808 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002809
2810 //----------------------------------------------------------------------
2811 // Supervisor Call (previously Software Interrupt)
2812 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002813 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2814
2815 //----------------------------------------------------------------------
2816 // If Then makes up to four following instructions conditional.
2817 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002818 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2819
2820 //----------------------------------------------------------------------
2821 // Branch instructions
2822 //----------------------------------------------------------------------
2823 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2824 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2825 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002826 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002827 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00002828 // J1 == J2 == 1
2829 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2830 // J1 == J2 == 1
2831 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2832 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002833 // for example, "bx lr"
2834 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002835 // compare and branch
2836 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002837
2838 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002839 // Data-processing instructions
2840 //----------------------------------------------------------------------
2841 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2842 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002843 // move from high register to high register
2844 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2845 // move from low register to low register
2846 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00002847 // compare a register with immediate
2848 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00002849 // compare Rn with Rm (Rn and Rm both from r0-r7)
2850 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
2851 // compare Rn with Rm (Rn and Rm not both from r0-r7)
2852 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002853
2854 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002855 // Load instructions
2856 //----------------------------------------------------------------------
2857 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002858 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002859 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00002860 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
2861 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00002862 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
2863
2864 //----------------------------------------------------------------------
2865 // Store instructions
2866 //----------------------------------------------------------------------
2867 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
2868 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002869
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002870 };
2871
2872 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2873 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2874 {
2875 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2876 return &g_thumb_opcodes[i];
2877 }
2878 return NULL;
2879}
Greg Clayton64c84432011-01-21 22:02:52 +00002880
Greg Clayton31e2a382011-01-30 20:03:56 +00002881bool
2882EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2883{
2884 m_arm_isa = 0;
2885 const char *triple_cstr = triple.GetCString();
2886 if (triple_cstr)
2887 {
2888 const char *dash = ::strchr (triple_cstr, '-');
2889 if (dash)
2890 {
2891 std::string arch (triple_cstr, dash);
2892 const char *arch_cstr = arch.c_str();
2893 if (strcasecmp(arch_cstr, "armv4t") == 0)
2894 m_arm_isa = ARMv4T;
2895 else if (strcasecmp(arch_cstr, "armv4") == 0)
2896 m_arm_isa = ARMv4;
2897 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2898 m_arm_isa = ARMv5TEJ;
2899 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2900 m_arm_isa = ARMv5TE;
2901 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2902 m_arm_isa = ARMv5T;
2903 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2904 m_arm_isa = ARMv6K;
2905 else if (strcasecmp(arch_cstr, "armv6") == 0)
2906 m_arm_isa = ARMv6;
2907 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2908 m_arm_isa = ARMv6T2;
2909 else if (strcasecmp(arch_cstr, "armv7") == 0)
2910 m_arm_isa = ARMv7;
2911 else if (strcasecmp(arch_cstr, "armv8") == 0)
2912 m_arm_isa = ARMv8;
2913 }
2914 }
2915 return m_arm_isa != 0;
2916}
2917
2918
Greg Clayton64c84432011-01-21 22:02:52 +00002919bool
2920EmulateInstructionARM::ReadInstruction ()
2921{
2922 bool success = false;
2923 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2924 if (success)
2925 {
2926 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2927 if (success)
2928 {
2929 Context read_inst_context = {eContextReadOpcode, 0, 0};
2930 if (m_inst_cpsr & MASK_CPSR_T)
2931 {
2932 m_inst_mode = eModeThumb;
2933 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2934
2935 if (success)
2936 {
2937 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2938 {
2939 m_inst.opcode_type = eOpcode16;
2940 m_inst.opcode.inst16 = thumb_opcode;
2941 }
2942 else
2943 {
2944 m_inst.opcode_type = eOpcode32;
2945 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2946 }
2947 }
2948 }
2949 else
2950 {
2951 m_inst_mode = eModeARM;
2952 m_inst.opcode_type = eOpcode32;
2953 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2954 }
2955 }
2956 }
2957 if (!success)
2958 {
2959 m_inst_mode = eModeInvalid;
2960 m_inst_pc = LLDB_INVALID_ADDRESS;
2961 }
2962 return success;
2963}
2964
Johnny Chenee9b1f72011-02-09 01:00:31 +00002965uint32_t
2966EmulateInstructionARM::ArchVersion ()
2967{
2968 return m_arm_isa;
2969}
2970
Greg Clayton64c84432011-01-21 22:02:52 +00002971bool
2972EmulateInstructionARM::ConditionPassed ()
2973{
2974 if (m_inst_cpsr == 0)
2975 return false;
2976
2977 const uint32_t cond = CurrentCond ();
2978
2979 if (cond == UINT32_MAX)
2980 return false;
2981
2982 bool result = false;
2983 switch (UnsignedBits(cond, 3, 1))
2984 {
2985 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2986 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2987 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2988 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2989 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2990 case 5:
2991 {
2992 bool n = (m_inst_cpsr & MASK_CPSR_N);
2993 bool v = (m_inst_cpsr & MASK_CPSR_V);
2994 result = n == v;
2995 }
2996 break;
2997 case 6:
2998 {
2999 bool n = (m_inst_cpsr & MASK_CPSR_N);
3000 bool v = (m_inst_cpsr & MASK_CPSR_V);
3001 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3002 }
3003 break;
3004 case 7:
3005 result = true;
3006 break;
3007 }
3008
3009 if (cond & 1)
3010 result = !result;
3011 return result;
3012}
3013
Johnny Chen9ee056b2011-02-08 00:06:35 +00003014uint32_t
3015EmulateInstructionARM::CurrentCond ()
3016{
3017 switch (m_inst_mode)
3018 {
3019 default:
3020 case eModeInvalid:
3021 break;
3022
3023 case eModeARM:
3024 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3025
3026 case eModeThumb:
3027 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3028 // 'cond' field of the encoding.
3029 if (m_inst.opcode_type == eOpcode16 &&
3030 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3031 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3032 {
3033 return Bits32(m_inst.opcode.inst16, 11, 7);
3034 }
3035 else if (m_inst.opcode_type == eOpcode32 &&
3036 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3037 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3038 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3039 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3040 {
3041 return Bits32(m_inst.opcode.inst32, 25, 22);
3042 }
3043
3044 return m_it_session.GetCond();
3045 }
3046 return UINT32_MAX; // Return invalid value
3047}
3048
Johnny Chen9ee056b2011-02-08 00:06:35 +00003049bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003050EmulateInstructionARM::InITBlock()
3051{
3052 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3053}
3054
3055bool
3056EmulateInstructionARM::LastInITBlock()
3057{
3058 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3059}
3060
3061bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003062EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3063{
3064 addr_t target;
3065
Johnny Chenee9b1f72011-02-09 01:00:31 +00003066 // Check the current instruction set.
3067 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003068 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003069 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003070 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003071
Johnny Chen9ee056b2011-02-08 00:06:35 +00003072 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003073 return false;
3074
3075 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003076}
3077
3078// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3079bool
3080EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
3081{
3082 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003083 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3084 // we want to record it and issue a WriteRegister callback so the clients
3085 // can track the mode changes accordingly.
3086 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003087
3088 if (BitIsSet(addr, 0))
3089 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003090 if (CurrentInstrSet() != eModeThumb)
3091 {
3092 SelectInstrSet(eModeThumb);
3093 cpsr_changed = true;
3094 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003095 target = addr & 0xfffffffe;
3096 context.arg2 = eModeThumb;
3097 }
3098 else if (BitIsClear(addr, 1))
3099 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003100 if (CurrentInstrSet() != eModeARM)
3101 {
3102 SelectInstrSet(eModeARM);
3103 cpsr_changed = true;
3104 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003105 target = addr & 0xfffffffc;
3106 context.arg2 = eModeARM;
3107 }
3108 else
3109 return false; // address<1:0> == '10' => UNPREDICTABLE
3110
Johnny Chen0f309db2011-02-09 19:11:32 +00003111 if (cpsr_changed)
3112 {
Johnny Chen558133b2011-02-09 23:59:17 +00003113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003114 return false;
3115 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003116 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003117 return false;
3118
3119 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003120}
Greg Clayton64c84432011-01-21 22:02:52 +00003121
Johnny Chenee9b1f72011-02-09 01:00:31 +00003122// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3123bool
3124EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
3125{
3126 if (ArchVersion() >= ARMv5T)
3127 return BXWritePC(context, addr);
3128 else
3129 return BranchWritePC((const Context)context, addr);
3130}
3131
Johnny Chen26863dc2011-02-09 23:43:29 +00003132// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3133bool
3134EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
3135{
3136 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
3137 return BXWritePC(context, addr);
3138 else
3139 return BranchWritePC((const Context)context, addr);
3140}
3141
Johnny Chenee9b1f72011-02-09 01:00:31 +00003142EmulateInstructionARM::Mode
3143EmulateInstructionARM::CurrentInstrSet ()
3144{
3145 return m_inst_mode;
3146}
3147
3148// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003149// ReadInstruction() is performed. This function has a side effect of updating
3150// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003151bool
3152EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3153{
Johnny Chen558133b2011-02-09 23:59:17 +00003154 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003155 switch (arm_or_thumb)
3156 {
3157 default:
3158 return false;
3159 eModeARM:
3160 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003161 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003162 break;
3163 eModeThumb:
3164 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003165 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003166 break;
3167 }
3168 return true;
3169}
3170
Johnny Chenef21b592011-02-10 01:52:38 +00003171// This function returns TRUE if the processor currently provides support for
3172// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3173// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3174bool
3175EmulateInstructionARM::UnalignedSupport()
3176{
3177 return (ArchVersion() >= ARMv7);
3178}
3179
Johnny Chenbf6ad172011-02-11 01:29:53 +00003180// The main addition and subtraction instructions can produce status information
3181// about both unsigned carry and signed overflow conditions. This status
3182// information can be used to synthesize multi-word additions and subtractions.
3183EmulateInstructionARM::AddWithCarryResult
3184EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3185{
3186 uint32_t result;
3187 uint8_t carry_out;
3188 uint8_t overflow;
3189
3190 uint64_t unsigned_sum = x + y + carry_in;
3191 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3192
3193 result = UnsignedBits(unsigned_sum, 31, 0);
3194 carry_out = (result == unsigned_sum ? 0 : 1);
3195 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3196
3197 AddWithCarryResult res = { result, carry_out, overflow };
3198 return res;
3199}
3200
Greg Clayton64c84432011-01-21 22:02:52 +00003201bool
3202EmulateInstructionARM::EvaluateInstruction ()
3203{
Johnny Chenc315f862011-02-05 00:46:10 +00003204 // Advance the ITSTATE bits to their values for the next instruction.
3205 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3206 m_it_session.ITAdvance();
3207
Greg Clayton64c84432011-01-21 22:02:52 +00003208 return false;
3209}