blob: 445e64283242b1ebbe53410dd65fb5ab2e8fb483 [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
10#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000011#include "lldb/Core/ConstString.h"
12
Greg Claytonf29a08f2011-02-09 17:41:27 +000013#include "Plugins/Process/Utility/ARMDefines.h"
14#include "Plugins/Process/Utility/ARMUtils.h"
15#include "Utility/ARM_DWARF_Registers.h"
16
Johnny Chen9b8d7832011-02-02 01:13:56 +000017#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000018 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000019
20using namespace lldb;
21using namespace lldb_private;
22
Johnny Chend6c13f02011-02-08 20:36:34 +000023static inline uint32_t Align(uint32_t val, uint32_t alignment)
24{
25 return alignment * (val / alignment);
26}
27
Johnny Chen0e00af22011-02-10 19:40:42 +000028//----------------------------------------------------------------------
29//
30// ITSession implementation
31//
32//----------------------------------------------------------------------
33
Johnny Chen93070472011-02-04 23:02:47 +000034// A8.6.50
35// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
36static unsigned short CountITSize(unsigned ITMask) {
37 // First count the trailing zeros of the IT mask.
38 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
39 if (TZ > 3)
40 {
41 printf("Encoding error: IT Mask '0000'\n");
42 return 0;
43 }
44 return (4 - TZ);
45}
46
47// Init ITState. Note that at least one bit is always 1 in mask.
48bool ITSession::InitIT(unsigned short bits7_0)
49{
50 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
51 if (ITCounter == 0)
52 return false;
53
54 // A8.6.50 IT
55 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
56 if (FirstCond == 0xF)
57 {
58 printf("Encoding error: IT FirstCond '1111'\n");
59 return false;
60 }
61 if (FirstCond == 0xE && ITCounter != 1)
62 {
63 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
64 return false;
65 }
66
67 ITState = bits7_0;
68 return true;
69}
70
71// Update ITState if necessary.
72void ITSession::ITAdvance()
73{
74 assert(ITCounter);
75 --ITCounter;
76 if (ITCounter == 0)
77 ITState = 0;
78 else
79 {
80 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
81 SetBits32(ITState, 4, 0, NewITState4_0);
82 }
83}
84
85// Return true if we're inside an IT Block.
86bool ITSession::InITBlock()
87{
88 return ITCounter != 0;
89}
90
Johnny Chenc315f862011-02-05 00:46:10 +000091// Return true if we're the last instruction inside an IT Block.
92bool ITSession::LastInITBlock()
93{
94 return ITCounter == 1;
95}
96
Johnny Chen93070472011-02-04 23:02:47 +000097// Get condition bits for the current thumb instruction.
98uint32_t ITSession::GetCond()
99{
Johnny Chenc315f862011-02-05 00:46:10 +0000100 if (InITBlock())
101 return Bits32(ITState, 7, 4);
102 else
103 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000104}
105
Greg Clayton64c84432011-01-21 22:02:52 +0000106// ARM constants used during decoding
107#define REG_RD 0
108#define LDM_REGLIST 1
109#define PC_REG 15
110#define PC_REGLIST_BIT 0x8000
111
Johnny Chen251af6a2011-01-21 22:47:25 +0000112#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000113#define ARMv4T (1u << 1)
114#define ARMv5T (1u << 2)
115#define ARMv5TE (1u << 3)
116#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000117#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000118#define ARMv6K (1u << 6)
119#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000120#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000121#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000122#define ARMvAll (0xffffffffu)
123
Johnny Chen9b8d7832011-02-02 01:13:56 +0000124#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
125#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
126#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000127
Johnny Chen0e00af22011-02-10 19:40:42 +0000128//----------------------------------------------------------------------
129//
130// EmulateInstructionARM implementation
131//
132//----------------------------------------------------------------------
133
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000134void
135EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000136{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000137}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139void
140EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000141{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142}
143
Johnny Chen08c25e82011-01-31 18:02:28 +0000144// Push Multiple Registers stores multiple registers to the stack, storing to
145// consecutive memory locations ending just below the address in SP, and updates
146// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000147bool
148EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000149{
150#if 0
151 // ARM pseudo code...
152 if (ConditionPassed())
153 {
154 EncodingSpecificOperations();
155 NullCheckIfThumbEE(13);
156 address = SP - 4*BitCount(registers);
157
158 for (i = 0 to 14)
159 {
160 if (registers<i> == ’1’)
161 {
162 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
163 MemA[address,4] = bits(32) UNKNOWN;
164 else
165 MemA[address,4] = R[i];
166 address = address + 4;
167 }
168 }
169
170 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
171 MemA[address,4] = PCStoreValue();
172
173 SP = SP - 4*BitCount(registers);
174 }
175#endif
176
177 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000178 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000179 if (!success)
180 return false;
181
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000182 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000183 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000184 const uint32_t addr_byte_size = GetAddressByteSize();
185 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000186 if (!success)
187 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000188 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000189 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000190 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000191 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000192 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000193 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000194 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000195 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000196 // if BitCount(registers) < 1 then UNPREDICTABLE;
197 if (BitCount(registers) < 1)
198 return false;
199 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000200 case eEncodingT2:
201 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000202 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000203 // if BitCount(registers) < 2 then UNPREDICTABLE;
204 if (BitCount(registers) < 2)
205 return false;
206 break;
207 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000208 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000209 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000210 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000211 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000212 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000213 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000214 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000215 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000216 // Instead of return false, let's handle the following case as well,
217 // which amounts to pushing one reg onto the full descending stacks.
218 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000219 break;
220 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000221 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000222 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000223 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000224 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000225 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000226 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000227 default:
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 }
Johnny Chence1ca772011-01-25 01:13:00 +0000230 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000231 addr_t addr = sp - sp_offset;
232 uint32_t i;
233
234 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
235 for (i=0; i<15; ++i)
236 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000237 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000238 {
239 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
240 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000241 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000242 if (!success)
243 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000244 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000245 return false;
246 addr += addr_byte_size;
247 }
248 }
249
Johnny Chen7c1bf922011-02-08 23:49:37 +0000250 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000251 {
252 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000253 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000254 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000255 if (!success)
256 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000257 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000258 return false;
259 }
260
261 context.type = EmulateInstruction::eContextAdjustStackPointer;
262 context.arg0 = eRegisterKindGeneric;
263 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000264 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000265
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000266 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000267 return false;
268 }
269 return true;
270}
271
Johnny Chenef85e912011-01-31 23:07:40 +0000272// Pop Multiple Registers loads multiple registers from the stack, loading from
273// consecutive memory locations staring at the address in SP, and updates
274// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000275bool
276EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000277{
278#if 0
279 // ARM pseudo code...
280 if (ConditionPassed())
281 {
282 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
283 address = SP;
284 for i = 0 to 14
285 if registers<i> == ‘1’ then
286 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
287 if registers<15> == ‘1’ then
288 if UnalignedAllowed then
289 LoadWritePC(MemU[address,4]);
290 else
291 LoadWritePC(MemA[address,4]);
292 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
293 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
294 }
295#endif
296
297 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000299 if (!success)
300 return false;
301
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000302 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000303 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000304 const uint32_t addr_byte_size = GetAddressByteSize();
305 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000306 if (!success)
307 return false;
308 uint32_t registers = 0;
309 uint32_t Rt; // the destination register
310 switch (encoding) {
311 case eEncodingT1:
312 registers = Bits32(opcode, 7, 0);
313 // The P bit represents PC.
314 if (Bits32(opcode, 8, 8))
315 registers |= (1u << 15);
316 // if BitCount(registers) < 1 then UNPREDICTABLE;
317 if (BitCount(registers) < 1)
318 return false;
319 break;
320 case eEncodingT2:
321 // Ignore bit 13.
322 registers = Bits32(opcode, 15, 0) & ~0x2000;
323 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
324 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
325 return false;
326 break;
327 case eEncodingT3:
328 Rt = Bits32(opcode, 15, 12);
329 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
330 if (Rt == dwarf_sp)
331 return false;
332 registers = (1u << Rt);
333 break;
334 case eEncodingA1:
335 registers = Bits32(opcode, 15, 0);
336 // Instead of return false, let's handle the following case as well,
337 // which amounts to popping one reg from the full descending stacks.
338 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
339
340 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
341 if (Bits32(opcode, 13, 13))
342 return false;
343 break;
344 case eEncodingA2:
345 Rt = Bits32(opcode, 15, 12);
346 // if t == 13 then UNPREDICTABLE;
347 if (Rt == dwarf_sp)
348 return false;
349 registers = (1u << Rt);
350 break;
351 default:
352 return false;
353 }
354 addr_t sp_offset = addr_byte_size * BitCount (registers);
355 addr_t addr = sp;
356 uint32_t i, data;
357
358 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
359 for (i=0; i<15; ++i)
360 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000361 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000362 {
363 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
364 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000365 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000366 if (!success)
367 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000368 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
370 addr += addr_byte_size;
371 }
372 }
373
Johnny Chen7c1bf922011-02-08 23:49:37 +0000374 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000375 {
376 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
377 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000378 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000379 if (!success)
380 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000381 // In ARMv5T and above, this is an interworking branch.
382 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000383 return false;
384 addr += addr_byte_size;
385 }
386
387 context.type = EmulateInstruction::eContextAdjustStackPointer;
388 context.arg0 = eRegisterKindGeneric;
389 context.arg1 = LLDB_REGNUM_GENERIC_SP;
390 context.arg2 = sp_offset;
391
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000392 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000393 return false;
394 }
395 return true;
396}
397
Johnny Chen5b442b72011-01-27 19:34:30 +0000398// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000399// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000400bool
401EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000402{
403#if 0
404 // ARM pseudo code...
405 if (ConditionPassed())
406 {
407 EncodingSpecificOperations();
408 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
409 if d == 15 then
410 ALUWritePC(result); // setflags is always FALSE here
411 else
412 R[d] = result;
413 if setflags then
414 APSR.N = result<31>;
415 APSR.Z = IsZeroBit(result);
416 APSR.C = carry;
417 APSR.V = overflow;
418 }
419#endif
420
421 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000422 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000423 if (!success)
424 return false;
425
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000427 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000428 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000429 if (!success)
430 return false;
431 uint32_t Rd; // the destination register
432 uint32_t imm32;
433 switch (encoding) {
434 case eEncodingT1:
435 Rd = 7;
436 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
437 break;
438 case eEncodingA1:
439 Rd = Bits32(opcode, 15, 12);
440 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
441 break;
442 default:
443 return false;
444 }
445 addr_t sp_offset = imm32;
446 addr_t addr = sp + sp_offset; // a pointer to the stack area
447
448 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
449 eRegisterKindGeneric,
450 LLDB_REGNUM_GENERIC_SP,
451 sp_offset };
452
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000453 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000454 return false;
455 }
456 return true;
457}
458
Johnny Chen2ccad832011-01-28 19:57:25 +0000459// Set r7 or ip to the current stack pointer.
460// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000461bool
462EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000463{
464#if 0
465 // ARM pseudo code...
466 if (ConditionPassed())
467 {
468 EncodingSpecificOperations();
469 result = R[m];
470 if d == 15 then
471 ALUWritePC(result); // setflags is always FALSE here
472 else
473 R[d] = result;
474 if setflags then
475 APSR.N = result<31>;
476 APSR.Z = IsZeroBit(result);
477 // APSR.C unchanged
478 // APSR.V unchanged
479 }
480#endif
481
482 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000483 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000484 //if (!success)
485 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000486
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000487 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000488 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000489 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000490 if (!success)
491 return false;
492 uint32_t Rd; // the destination register
493 switch (encoding) {
494 case eEncodingT1:
495 Rd = 7;
496 break;
497 case eEncodingA1:
498 Rd = 12;
499 break;
500 default:
501 return false;
502 }
503 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
504 eRegisterKindGeneric,
505 LLDB_REGNUM_GENERIC_SP,
506 0 };
507
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000509 return false;
510 }
511 return true;
512}
513
Johnny Chen1c13b622011-01-29 00:11:15 +0000514// Move from high register (r8-r15) to low register (r0-r7).
515// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000516bool
517EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000518{
Johnny Chen338bf542011-02-10 19:29:03 +0000519 return EmulateMovRdRm (encoding);
520}
521
522// Move from register to register.
523// MOV (register)
524bool
525EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
526{
Johnny Chen1c13b622011-01-29 00:11:15 +0000527#if 0
528 // ARM pseudo code...
529 if (ConditionPassed())
530 {
531 EncodingSpecificOperations();
532 result = R[m];
533 if d == 15 then
534 ALUWritePC(result); // setflags is always FALSE here
535 else
536 R[d] = result;
537 if setflags then
538 APSR.N = result<31>;
539 APSR.Z = IsZeroBit(result);
540 // APSR.C unchanged
541 // APSR.V unchanged
542 }
543#endif
544
545 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000546 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000547 if (!success)
548 return false;
549
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000550 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000551 {
552 uint32_t Rm; // the source register
553 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000554 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000555 switch (encoding) {
556 case eEncodingT1:
557 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000558 Rd = Bits32(opcode, 7, 7) << 3 | Bits32(opcode, 2, 1);
559 setflags = false;
560 break;
561 case eEncodingT2:
562 Rm = Bits32(opcode, 5, 3);
563 Rd = Bits32(opcode, 2, 1);
564 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000565 break;
566 default:
567 return false;
568 }
Johnny Chen338bf542011-02-10 19:29:03 +0000569 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000570 if (!success)
571 return false;
572
573 // The context specifies that Rm is to be moved into Rd.
574 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
575 eRegisterKindDWARF,
576 dwarf_r0 + Rm,
577 0 };
578
Johnny Chen338bf542011-02-10 19:29:03 +0000579 if (Rd == 15)
580 {
581 if (!ALUWritePC (context, reg_value))
582 return false;
583 }
584 else
585 {
586 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
587 return false;
588 if (setflags)
589 {
590 m_new_inst_cpsr = m_inst_cpsr;
591 SetBits32(m_new_inst_cpsr, CPSR_N, Bits32(reg_value, CPSR_N));
592 SetBits32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
593 if (m_new_inst_cpsr != m_inst_cpsr)
594 {
595 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
596 return false;
597 }
598 }
599 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 }
601 return true;
602}
603
Johnny Chen788e0552011-01-27 22:52:23 +0000604// PC relative immediate load into register, possibly followed by ADD (SP plus register).
605// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000606bool
607EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000608{
609#if 0
610 // ARM pseudo code...
611 if (ConditionPassed())
612 {
613 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
614 base = Align(PC,4);
615 address = if add then (base + imm32) else (base - imm32);
616 data = MemU[address,4];
617 if t == 15 then
618 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
619 elsif UnalignedSupport() || address<1:0> = ‘00’ then
620 R[t] = data;
621 else // Can only apply before ARMv7
622 if CurrentInstrSet() == InstrSet_ARM then
623 R[t] = ROR(data, 8*UInt(address<1:0>));
624 else
625 R[t] = bits(32) UNKNOWN;
626 }
627#endif
628
629 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000630 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000631 if (!success)
632 return false;
633
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000634 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000635 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000636 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000637 if (!success)
638 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000639
640 // PC relative immediate load context
641 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
642 eRegisterKindGeneric,
643 LLDB_REGNUM_GENERIC_PC,
644 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000645 uint32_t Rd; // the destination register
646 uint32_t imm32; // immediate offset from the PC
647 addr_t addr; // the PC relative address
648 uint32_t data; // the literal data value from the PC relative load
649 switch (encoding) {
650 case eEncodingT1:
651 Rd = Bits32(opcode, 10, 8);
652 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
653 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000654 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000655 break;
656 default:
657 return false;
658 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000659 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000660 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000661 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000663 return false;
664 }
665 return true;
666}
667
Johnny Chen5b442b72011-01-27 19:34:30 +0000668// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000669// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000670bool
671EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000672{
673#if 0
674 // ARM pseudo code...
675 if (ConditionPassed())
676 {
677 EncodingSpecificOperations();
678 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
679 if d == 15 then // Can only occur for ARM encoding
680 ALUWritePC(result); // setflags is always FALSE here
681 else
682 R[d] = result;
683 if setflags then
684 APSR.N = result<31>;
685 APSR.Z = IsZeroBit(result);
686 APSR.C = carry;
687 APSR.V = overflow;
688 }
689#endif
690
691 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000692 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000693 if (!success)
694 return false;
695
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000696 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000697 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000698 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000699 if (!success)
700 return false;
701 uint32_t imm32; // the immediate operand
702 switch (encoding) {
703 case eEncodingT2:
704 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
705 break;
706 default:
707 return false;
708 }
709 addr_t sp_offset = imm32;
710 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
711
712 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
713 eRegisterKindGeneric,
714 LLDB_REGNUM_GENERIC_SP,
715 sp_offset };
716
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000717 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000718 return false;
719 }
720 return true;
721}
722
723// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000724// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000725bool
726EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000727{
728#if 0
729 // ARM pseudo code...
730 if (ConditionPassed())
731 {
732 EncodingSpecificOperations();
733 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
734 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
735 if d == 15 then
736 ALUWritePC(result); // setflags is always FALSE here
737 else
738 R[d] = result;
739 if setflags then
740 APSR.N = result<31>;
741 APSR.Z = IsZeroBit(result);
742 APSR.C = carry;
743 APSR.V = overflow;
744 }
745#endif
746
747 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000748 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000749 if (!success)
750 return false;
751
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000752 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000753 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000754 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000755 if (!success)
756 return false;
757 uint32_t Rm; // the second operand
758 switch (encoding) {
759 case eEncodingT2:
760 Rm = Bits32(opcode, 6, 3);
761 break;
762 default:
763 return false;
764 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000765 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000766 if (!success)
767 return false;
768
769 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
770
771 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
772 eRegisterKindGeneric,
773 LLDB_REGNUM_GENERIC_SP,
774 reg_value };
775
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000776 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000777 return false;
778 }
779 return true;
780}
781
Johnny Chen9b8d7832011-02-02 01:13:56 +0000782// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
783// at a PC-relative address, and changes instruction set from ARM to Thumb, or
784// from Thumb to ARM.
785// BLX (immediate)
786bool
787EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
788{
789#if 0
790 // ARM pseudo code...
791 if (ConditionPassed())
792 {
793 EncodingSpecificOperations();
794 if CurrentInstrSet() == InstrSet_ARM then
795 LR = PC - 4;
796 else
797 LR = PC<31:1> : '1';
798 if targetInstrSet == InstrSet_ARM then
799 targetAddress = Align(PC,4) + imm32;
800 else
801 targetAddress = PC + imm32;
802 SelectInstrSet(targetInstrSet);
803 BranchWritePC(targetAddress);
804 }
805#endif
806
807 bool success = false;
808 const uint32_t opcode = OpcodeAsUnsigned (&success);
809 if (!success)
810 return false;
811
812 if (ConditionPassed())
813 {
814 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
815 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000816 if (!success)
817 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000818 addr_t lr; // next instruction address
819 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000820 int32_t imm32; // PC-relative offset
821 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000822 case eEncodingT1:
823 {
824 lr = (pc + 4) | 1u; // return address
825 uint32_t S = Bits32(opcode, 26, 26);
826 uint32_t imm10 = Bits32(opcode, 25, 16);
827 uint32_t J1 = Bits32(opcode, 13, 13);
828 uint32_t J2 = Bits32(opcode, 11, 11);
829 uint32_t imm11 = Bits32(opcode, 10, 0);
830 uint32_t I1 = !(J1 ^ S);
831 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000832 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000833 imm32 = llvm::SignExtend32<25>(imm25);
834 target = pc + 4 + imm32;
835 context.arg1 = 4 + imm32; // signed offset
836 context.arg2 = eModeThumb; // target instruction set
837 break;
838 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000839 case eEncodingT2:
840 {
841 lr = (pc + 4) | 1u; // return address
842 uint32_t S = Bits32(opcode, 26, 26);
843 uint32_t imm10H = Bits32(opcode, 25, 16);
844 uint32_t J1 = Bits32(opcode, 13, 13);
845 uint32_t J2 = Bits32(opcode, 11, 11);
846 uint32_t imm10L = Bits32(opcode, 10, 1);
847 uint32_t I1 = !(J1 ^ S);
848 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000849 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000850 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000851 target = Align(pc + 4, 4) + imm32;
852 context.arg1 = 4 + imm32; // signed offset
853 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000854 break;
855 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000856 case eEncodingA1:
857 lr = pc + 4; // return address
858 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000859 target = Align(pc + 8, 4) + imm32;
860 context.arg1 = 8 + imm32; // signed offset
861 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000862 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000863 case eEncodingA2:
864 lr = pc + 4; // return address
865 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
866 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000867 context.arg1 = 8 + imm32; // signed offset
868 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000869 break;
870 default:
871 return false;
872 }
873 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
874 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000875 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000876 return false;
877 }
878 return true;
879}
880
881// Branch with Link and Exchange (register) calls a subroutine at an address and
882// instruction set specified by a register.
883// BLX (register)
884bool
885EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
886{
887#if 0
888 // ARM pseudo code...
889 if (ConditionPassed())
890 {
891 EncodingSpecificOperations();
892 target = R[m];
893 if CurrentInstrSet() == InstrSet_ARM then
894 next_instr_addr = PC - 4;
895 LR = next_instr_addr;
896 else
897 next_instr_addr = PC - 2;
898 LR = next_instr_addr<31:1> : ‘1’;
899 BXWritePC(target);
900 }
901#endif
902
903 bool success = false;
904 const uint32_t opcode = OpcodeAsUnsigned (&success);
905 if (!success)
906 return false;
907
908 if (ConditionPassed())
909 {
910 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
911 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
912 addr_t lr; // next instruction address
913 addr_t target; // target address
914 if (!success)
915 return false;
916 uint32_t Rm; // the register with the target address
917 switch (encoding) {
918 case eEncodingT1:
919 lr = (pc + 2) | 1u; // return address
920 Rm = Bits32(opcode, 6, 3);
921 // if m == 15 then UNPREDICTABLE;
922 if (Rm == 15)
923 return false;
924 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
925 break;
926 case eEncodingA1:
927 lr = pc + 4; // return address
928 Rm = Bits32(opcode, 3, 0);
929 // if m == 15 then UNPREDICTABLE;
930 if (Rm == 15)
931 return false;
932 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000933 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000934 default:
935 return false;
936 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000937 context.arg0 = eRegisterKindDWARF;
938 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000939 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
940 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000941 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000942 return false;
943 }
944 return true;
945}
946
Johnny Chen0d0148e2011-01-28 02:26:08 +0000947// Set r7 to point to some ip offset.
948// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000949bool
950EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000951{
952#if 0
953 // ARM pseudo code...
954 if (ConditionPassed())
955 {
956 EncodingSpecificOperations();
957 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
958 if d == 15 then // Can only occur for ARM encoding
959 ALUWritePC(result); // setflags is always FALSE here
960 else
961 R[d] = result;
962 if setflags then
963 APSR.N = result<31>;
964 APSR.Z = IsZeroBit(result);
965 APSR.C = carry;
966 APSR.V = overflow;
967 }
968#endif
969
970 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000971 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000972 if (!success)
973 return false;
974
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000975 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000976 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000977 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000978 if (!success)
979 return false;
980 uint32_t imm32;
981 switch (encoding) {
982 case eEncodingA1:
983 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
984 break;
985 default:
986 return false;
987 }
988 addr_t ip_offset = imm32;
989 addr_t addr = ip - ip_offset; // the adjusted ip value
990
991 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
992 eRegisterKindDWARF,
993 dwarf_r12,
994 -ip_offset };
995
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000997 return false;
998 }
999 return true;
1000}
1001
1002// Set ip to point to some stack offset.
1003// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001004bool
1005EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001006{
1007#if 0
1008 // ARM pseudo code...
1009 if (ConditionPassed())
1010 {
1011 EncodingSpecificOperations();
1012 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1013 if d == 15 then // Can only occur for ARM encoding
1014 ALUWritePC(result); // setflags is always FALSE here
1015 else
1016 R[d] = result;
1017 if setflags then
1018 APSR.N = result<31>;
1019 APSR.Z = IsZeroBit(result);
1020 APSR.C = carry;
1021 APSR.V = overflow;
1022 }
1023#endif
1024
1025 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001026 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001027 if (!success)
1028 return false;
1029
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001030 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001031 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001032 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001033 if (!success)
1034 return false;
1035 uint32_t imm32;
1036 switch (encoding) {
1037 case eEncodingA1:
1038 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1039 break;
1040 default:
1041 return false;
1042 }
1043 addr_t sp_offset = imm32;
1044 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1045
1046 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1047 eRegisterKindGeneric,
1048 LLDB_REGNUM_GENERIC_SP,
1049 -sp_offset };
1050
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001051 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001052 return false;
1053 }
1054 return true;
1055}
1056
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001057// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001058bool
1059EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001060{
1061#if 0
1062 // ARM pseudo code...
1063 if (ConditionPassed())
1064 {
1065 EncodingSpecificOperations();
1066 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1067 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001068 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001069 else
1070 R[d] = result;
1071 if setflags then
1072 APSR.N = result<31>;
1073 APSR.Z = IsZeroBit(result);
1074 APSR.C = carry;
1075 APSR.V = overflow;
1076 }
1077#endif
1078
1079 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001080 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001081 if (!success)
1082 return false;
1083
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001084 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001085 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001086 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001087 if (!success)
1088 return false;
1089 uint32_t imm32;
1090 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001091 case eEncodingT1:
1092 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001093 case eEncodingT2:
1094 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1095 break;
1096 case eEncodingT3:
1097 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1098 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001099 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001100 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001101 break;
1102 default:
1103 return false;
1104 }
1105 addr_t sp_offset = imm32;
1106 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1107
1108 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1109 eRegisterKindGeneric,
1110 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001111 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001112
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001114 return false;
1115 }
1116 return true;
1117}
1118
Johnny Chen08c25e82011-01-31 18:02:28 +00001119// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001120bool
1121EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001122{
1123#if 0
1124 // ARM pseudo code...
1125 if (ConditionPassed())
1126 {
1127 EncodingSpecificOperations();
1128 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1129 address = if index then offset_addr else R[n];
1130 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1131 if wback then R[n] = offset_addr;
1132 }
1133#endif
1134
1135 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001136 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001137 if (!success)
1138 return false;
1139
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001141 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001142 const uint32_t addr_byte_size = GetAddressByteSize();
1143 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001144 if (!success)
1145 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001146 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001147 uint32_t imm12;
1148 switch (encoding) {
1149 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001150 Rt = Bits32(opcode, 15, 12);
1151 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001152 break;
1153 default:
1154 return false;
1155 }
1156 addr_t sp_offset = imm12;
1157 addr_t addr = sp - sp_offset;
1158
1159 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001160 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001161 {
Johnny Chen91d99862011-01-25 19:07:04 +00001162 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1163 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001164 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001165 if (!success)
1166 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001167 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001168 return false;
1169 }
1170 else
1171 {
1172 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1173 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001174 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001175 if (!success)
1176 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001177 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001178 return false;
1179 }
1180
1181 context.type = EmulateInstruction::eContextAdjustStackPointer;
1182 context.arg0 = eRegisterKindGeneric;
1183 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001184 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001185
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001186 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001187 return false;
1188 }
1189 return true;
1190}
1191
Johnny Chen08c25e82011-01-31 18:02:28 +00001192// Vector Push stores multiple extension registers to the stack.
1193// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001194bool
1195EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001196{
1197#if 0
1198 // ARM pseudo code...
1199 if (ConditionPassed())
1200 {
1201 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1202 address = SP - imm32;
1203 SP = SP - imm32;
1204 if single_regs then
1205 for r = 0 to regs-1
1206 MemA[address,4] = S[d+r]; address = address+4;
1207 else
1208 for r = 0 to regs-1
1209 // Store as two word-aligned words in the correct order for current endianness.
1210 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1211 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1212 address = address+8;
1213 }
1214#endif
1215
1216 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001218 if (!success)
1219 return false;
1220
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001221 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001222 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001223 const uint32_t addr_byte_size = GetAddressByteSize();
1224 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001225 if (!success)
1226 return false;
1227 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001228 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001229 uint32_t imm32; // stack offset
1230 uint32_t regs; // number of registers
1231 switch (encoding) {
1232 case eEncodingT1:
1233 case eEncodingA1:
1234 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001235 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001236 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1237 // If UInt(imm8) is odd, see "FSTMX".
1238 regs = Bits32(opcode, 7, 0) / 2;
1239 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1240 if (regs == 0 || regs > 16 || (d + regs) > 32)
1241 return false;
1242 break;
1243 case eEncodingT2:
1244 case eEncodingA2:
1245 single_regs = true;
1246 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1247 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1248 regs = Bits32(opcode, 7, 0);
1249 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1250 if (regs == 0 || regs > 16 || (d + regs) > 32)
1251 return false;
1252 break;
1253 default:
1254 return false;
1255 }
1256 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1257 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1258 addr_t sp_offset = imm32;
1259 addr_t addr = sp - sp_offset;
1260 uint32_t i;
1261
1262 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1263 for (i=d; i<regs; ++i)
1264 {
1265 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1266 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1267 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001268 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001269 if (!success)
1270 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001271 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001272 return false;
1273 addr += reg_byte_size;
1274 }
1275
1276 context.type = EmulateInstruction::eContextAdjustStackPointer;
1277 context.arg0 = eRegisterKindGeneric;
1278 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001279 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001280
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001281 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001282 return false;
1283 }
1284 return true;
1285}
1286
Johnny Chen587a0a42011-02-01 18:35:28 +00001287// Vector Pop loads multiple extension registers from the stack.
1288// It also updates SP to point just above the loaded data.
1289bool
1290EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1291{
1292#if 0
1293 // ARM pseudo code...
1294 if (ConditionPassed())
1295 {
1296 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1297 address = SP;
1298 SP = SP + imm32;
1299 if single_regs then
1300 for r = 0 to regs-1
1301 S[d+r] = MemA[address,4]; address = address+4;
1302 else
1303 for r = 0 to regs-1
1304 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1305 // Combine the word-aligned words in the correct order for current endianness.
1306 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1307 }
1308#endif
1309
1310 bool success = false;
1311 const uint32_t opcode = OpcodeAsUnsigned (&success);
1312 if (!success)
1313 return false;
1314
1315 if (ConditionPassed())
1316 {
1317 const uint32_t addr_byte_size = GetAddressByteSize();
1318 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1319 if (!success)
1320 return false;
1321 bool single_regs;
1322 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1323 uint32_t imm32; // stack offset
1324 uint32_t regs; // number of registers
1325 switch (encoding) {
1326 case eEncodingT1:
1327 case eEncodingA1:
1328 single_regs = false;
1329 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1330 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1331 // If UInt(imm8) is odd, see "FLDMX".
1332 regs = Bits32(opcode, 7, 0) / 2;
1333 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1334 if (regs == 0 || regs > 16 || (d + regs) > 32)
1335 return false;
1336 break;
1337 case eEncodingT2:
1338 case eEncodingA2:
1339 single_regs = true;
1340 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1341 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1342 regs = Bits32(opcode, 7, 0);
1343 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1344 if (regs == 0 || regs > 16 || (d + regs) > 32)
1345 return false;
1346 break;
1347 default:
1348 return false;
1349 }
1350 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1351 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1352 addr_t sp_offset = imm32;
1353 addr_t addr = sp;
1354 uint32_t i;
1355 uint64_t data; // uint64_t to accomodate 64-bit registers.
1356
1357 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1358 for (i=d; i<regs; ++i)
1359 {
1360 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1361 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1362 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1363 if (!success)
1364 return false;
1365 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1366 return false;
1367 addr += reg_byte_size;
1368 }
1369
1370 context.type = EmulateInstruction::eContextAdjustStackPointer;
1371 context.arg0 = eRegisterKindGeneric;
1372 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1373 context.arg2 = sp_offset;
1374
1375 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1376 return false;
1377 }
1378 return true;
1379}
1380
Johnny Chenb77be412011-02-04 00:40:18 +00001381// SVC (previously SWI)
1382bool
1383EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1384{
1385#if 0
1386 // ARM pseudo code...
1387 if (ConditionPassed())
1388 {
1389 EncodingSpecificOperations();
1390 CallSupervisor();
1391 }
1392#endif
1393
1394 bool success = false;
1395 const uint32_t opcode = OpcodeAsUnsigned (&success);
1396 if (!success)
1397 return false;
1398
1399 if (ConditionPassed())
1400 {
1401 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1402 addr_t lr; // next instruction address
1403 if (!success)
1404 return false;
1405 uint32_t imm32; // the immediate constant
1406 uint32_t mode; // ARM or Thumb mode
1407 switch (encoding) {
1408 case eEncodingT1:
1409 lr = (pc + 2) | 1u; // return address
1410 imm32 = Bits32(opcode, 7, 0);
1411 mode = eModeThumb;
1412 break;
1413 case eEncodingA1:
1414 lr = pc + 4; // return address
1415 imm32 = Bits32(opcode, 23, 0);
1416 mode = eModeARM;
1417 break;
1418 default:
1419 return false;
1420 }
1421 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1422 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1423 return false;
1424 }
1425 return true;
1426}
1427
Johnny Chenc315f862011-02-05 00:46:10 +00001428// If Then makes up to four following instructions (the IT block) conditional.
1429bool
1430EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1431{
1432#if 0
1433 // ARM pseudo code...
1434 EncodingSpecificOperations();
1435 ITSTATE.IT<7:0> = firstcond:mask;
1436#endif
1437
1438 bool success = false;
1439 const uint32_t opcode = OpcodeAsUnsigned (&success);
1440 if (!success)
1441 return false;
1442
1443 m_it_session.InitIT(Bits32(opcode, 7, 0));
1444 return true;
1445}
1446
Johnny Chen3b620b32011-02-07 20:11:47 +00001447// Branch causes a branch to a target address.
1448bool
1449EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1450{
1451#if 0
1452 // ARM pseudo code...
1453 if (ConditionPassed())
1454 {
1455 EncodingSpecificOperations();
1456 BranchWritePC(PC + imm32);
1457 }
1458#endif
1459
1460 bool success = false;
1461 const uint32_t opcode = OpcodeAsUnsigned (&success);
1462 if (!success)
1463 return false;
1464
Johnny Chen9ee056b2011-02-08 00:06:35 +00001465 if (ConditionPassed())
1466 {
1467 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1468 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001469 if (!success)
1470 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001471 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001472 int32_t imm32; // PC-relative offset
1473 switch (encoding) {
1474 case eEncodingT1:
1475 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1476 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1477 target = pc + 4 + imm32;
1478 context.arg1 = 4 + imm32; // signed offset
1479 context.arg2 = eModeThumb; // target instruction set
1480 break;
1481 case eEncodingT2:
1482 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1483 target = pc + 4 + imm32;
1484 context.arg1 = 4 + imm32; // signed offset
1485 context.arg2 = eModeThumb; // target instruction set
1486 break;
1487 case eEncodingT3:
1488 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1489 {
1490 uint32_t S = Bits32(opcode, 26, 26);
1491 uint32_t imm6 = Bits32(opcode, 21, 16);
1492 uint32_t J1 = Bits32(opcode, 13, 13);
1493 uint32_t J2 = Bits32(opcode, 11, 11);
1494 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001495 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001496 imm32 = llvm::SignExtend32<21>(imm21);
1497 target = pc + 4 + imm32;
1498 context.arg1 = eModeThumb; // target instruction set
1499 context.arg2 = 4 + imm32; // signed offset
1500 break;
1501 }
1502 case eEncodingT4:
1503 {
1504 uint32_t S = Bits32(opcode, 26, 26);
1505 uint32_t imm10 = Bits32(opcode, 25, 16);
1506 uint32_t J1 = Bits32(opcode, 13, 13);
1507 uint32_t J2 = Bits32(opcode, 11, 11);
1508 uint32_t imm11 = Bits32(opcode, 10, 0);
1509 uint32_t I1 = !(J1 ^ S);
1510 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001511 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001512 imm32 = llvm::SignExtend32<25>(imm25);
1513 target = pc + 4 + imm32;
1514 context.arg1 = eModeThumb; // target instruction set
1515 context.arg2 = 4 + imm32; // signed offset
1516 break;
1517 }
1518 case eEncodingA1:
1519 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1520 target = pc + 8 + imm32;
1521 context.arg1 = eModeARM; // target instruction set
1522 context.arg2 = 8 + imm32; // signed offset
1523 break;
1524 default:
1525 return false;
1526 }
1527 if (!BranchWritePC(context, target))
1528 return false;
1529 }
1530 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001531}
1532
Johnny Chen53ebab72011-02-08 23:21:57 +00001533// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1534// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1535// CBNZ, CBZ
1536bool
1537EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1538{
1539#if 0
1540 // ARM pseudo code...
1541 EncodingSpecificOperations();
1542 if nonzero ^ IsZero(R[n]) then
1543 BranchWritePC(PC + imm32);
1544#endif
1545
1546 bool success = false;
1547 const uint32_t opcode = OpcodeAsUnsigned (&success);
1548 if (!success)
1549 return false;
1550
1551 // Read the register value from the operand register Rn.
1552 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1553 if (!success)
1554 return false;
1555
1556 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1557 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1558 if (!success)
1559 return false;
1560
1561 addr_t target; // target address
1562 uint32_t imm32; // PC-relative offset to branch forward
1563 bool nonzero;
1564 switch (encoding) {
1565 case eEncodingT1:
1566 imm32 = Bits32(opcode, 9, 9) << 6 | Bits32(opcode, 7, 3) << 1;
1567 nonzero = BitIsSet(opcode, 11);
1568 target = pc + 4 + imm32;
1569 context.arg1 = 4 + imm32; // signed offset
1570 context.arg2 = eModeThumb; // target instruction set
1571 break;
1572 default:
1573 return false;
1574 }
1575 if (nonzero ^ (reg_val == 0))
1576 if (!BranchWritePC(context, target))
1577 return false;
1578
1579 return true;
1580}
1581
Johnny Chen26863dc2011-02-09 23:43:29 +00001582// ADD <Rdn>, <Rm>
1583// where <Rdn> the destination register is also the first operand register
1584// and <Rm> is the second operand register.
1585bool
1586EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1587{
1588#if 0
1589 // ARM pseudo code...
1590 if ConditionPassed() then
1591 EncodingSpecificOperations();
1592 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1593 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1594 if d == 15 then
1595 ALUWritePC(result); // setflags is always FALSE here
1596 else
1597 R[d] = result;
1598 if setflags then
1599 APSR.N = result<31>;
1600 APSR.Z = IsZeroBit(result);
1601 APSR.C = carry;
1602 APSR.V = overflow;
1603#endif
1604
1605 bool success = false;
1606 const uint32_t opcode = OpcodeAsUnsigned (&success);
1607 if (!success)
1608 return false;
1609
1610 if (ConditionPassed())
1611 {
1612 uint32_t Rd, Rn, Rm;
1613 //bool setflags = false;
1614 switch (encoding)
1615 {
1616 case eEncodingT2:
1617 // setflags = FALSE
1618 Rd = Rn = Bits32(opcode, 7, 7) << 3 | Bits32(opcode, 2, 0);
1619 Rm = Bits32(opcode, 6, 3);
1620 if (Rn == 15 && Rm == 15)
1621 return false;
1622 break;
1623 default:
1624 return false;
1625 }
1626
1627 int32_t result, val1, val2;
1628 // Read the first operand.
1629 if (Rn == 15)
1630 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1631 else
1632 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1633 if (!success)
1634 return false;
1635
1636 // Read the second operand.
1637 if (Rm == 15)
1638 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1639 else
1640 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1641 if (!success)
1642 return false;
1643
1644 result = val1 + val2;
1645 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1646 result,
1647 0,
1648 0 };
1649
1650 if (Rd == 15)
1651 {
1652 if (!ALUWritePC (context, result))
1653 return false;
1654 }
1655 else
1656 {
1657 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1658 return false;
1659 }
1660 }
1661 return true;
1662}
1663
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001664// LDM loads multiple registers from consecutive memory locations, using an
1665// address from a base register. Optionally the addres just above the highest of those locations
1666// can be written back to the base register.
1667bool
1668EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1669{
1670#if 0
1671 // ARM pseudo code...
1672 if ConditionPassed()
1673 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1674 address = R[n];
1675
1676 for i = 0 to 14
1677 if registers<i> == '1' then
1678 R[i] = MemA[address, 4]; address = address + 4;
1679 if registers<15> == '1' then
1680 LoadWritePC (MemA[address, 4]);
1681
1682 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1683 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1684
1685#endif
1686
1687 bool success = false;
1688 const uint32_t opcode = OpcodeAsUnsigned (&success);
1689 if (!success)
1690 return false;
1691
1692 if (ConditionPassed())
1693 {
1694 uint32_t n;
1695 uint32_t registers = 0;
1696 bool wback;
1697 const uint32_t addr_byte_size = GetAddressByteSize();
1698 switch (encoding)
1699 {
1700 case eEncodingT1:
1701 n = Bits32 (opcode, 10, 8);
1702 registers = Bits32 (opcode, 7, 0);
1703 wback = BitIsClear (registers, n);
1704 // if BitCount(registers) < 1 then UNPREDICTABLE;
1705 if (BitCount(registers) < 1)
1706 return false;
1707 break;
1708 case eEncodingT2:
1709 n = Bits32 (opcode, 19, 16);
1710 registers = Bits32 (opcode, 15, 0);
1711 wback = BitIsSet (opcode, 21);
1712 if ((n == 15)
1713 || (BitCount (registers) < 2)
1714 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1715 return false;
1716 if (BitIsSet (registers, 15)
1717 && m_it_session.InITBlock()
1718 && !m_it_session.LastInITBlock())
1719 return false;
1720 if (wback
1721 && BitIsSet (registers, n))
1722 return false;
1723 break;
1724 case eEncodingA1:
1725 n = Bits32 (opcode, 19, 16);
1726 registers = Bits32 (opcode, 15, 0);
1727 wback = BitIsSet (opcode, 21);
1728 if ((n == 15)
1729 || (BitCount (registers) < 1))
1730 return false;
1731 break;
1732 default:
1733 return false;
1734 }
1735
1736 int32_t offset = 0;
1737 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1738 if (!success)
1739 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001740
1741 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1742 eRegisterKindDWARF,
1743 dwarf_r0 + n,
1744 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001745
1746 for (int i = 0; i < 14; ++i)
1747 {
1748 if (BitIsSet (registers, i))
1749 {
Caroline Tice85aab332011-02-08 23:56:10 +00001750 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1751 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001752 if (wback && (n == 13)) // Pop Instruction
1753 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1754
1755 // R[i] = MemA [address, 4]; address = address + 4;
1756 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1757 if (!success)
1758 return false;
1759
1760 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1761 return false;
1762
1763 offset += addr_byte_size;
1764 }
1765 }
1766
1767 if (BitIsSet (registers, 15))
1768 {
1769 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001770 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1771 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001772 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1773 if (!success)
1774 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001775 // In ARMv5T and above, this is an interworking branch.
1776 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001777 return false;
1778 }
1779
1780 if (wback && BitIsClear (registers, n))
1781 {
1782 addr_t offset = addr_byte_size * BitCount (registers);
Caroline Tice85aab332011-02-08 23:56:10 +00001783 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1784 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001785
1786 // R[n] = R[n] + 4 * BitCount (registers)
1787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1788 return false;
1789 }
1790 if (wback && BitIsSet (registers, n))
1791 // R[n] bits(32) UNKNOWN;
1792 return false; //I'm not convinced this is the right thing to do here...
1793 }
1794 return true;
1795}
1796
Caroline Tice0b29e242011-02-08 23:16:02 +00001797bool
1798EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1799{
1800#if 0
1801 // ARM pseudo code...
1802 if ConditionPassed() then
1803 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1804 address = R[n] - 4*BitCount(registers);
1805
1806 for i = 0 to 14
1807 if registers<i> == ’1’ then
1808 R[i] = MemA[address,4]; address = address + 4;
1809 if registers<15> == ’1’ then
1810 LoadWritePC(MemA[address,4]);
1811
1812 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1813 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1814#endif
1815
1816 bool success = false;
1817 const uint32_t opcode = OpcodeAsUnsigned (&success);
1818 if (!success)
1819 return false;
1820
1821 if (ConditionPassed())
1822 {
1823 uint32_t n;
1824 uint32_t registers = 0;
1825 bool wback;
1826 const uint32_t addr_byte_size = GetAddressByteSize();
1827 switch (encoding)
1828 {
1829 case eEncodingT1:
1830 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1831 n = Bits32 (opcode, 19, 16);
1832 registers = Bits32 (opcode, 15, 0);
1833 wback = BitIsSet (opcode, 21);
1834
1835 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1836 if ((n == 15)
1837 || (BitCount (registers) < 2)
1838 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1839 return false;
1840
1841 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1842 if (BitIsSet (registers, 15)
1843 && m_it_session.InITBlock()
1844 && !m_it_session.LastInITBlock())
1845 return false;
1846
1847 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1848 if (wback && BitIsSet (registers, n))
1849 return false;
1850
1851 break;
1852
1853 case eEncodingA1:
1854 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1855 n = Bits32 (opcode, 19, 16);
1856 registers = Bits32 (opcode, 15, 0);
1857 wback = BitIsSet (opcode, 21);
1858
1859 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1860 if ((n == 15) || (BitCount (registers) < 1))
1861 return false;
1862
1863 break;
1864
1865 default:
1866 return false;
1867 }
1868
1869 int32_t offset = 0;
1870 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1871 - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00001872 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1873 eRegisterKindDWARF,
1874 dwarf_r0 + n,
1875 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00001876
1877 for (int i = 0; i < 14; ++i)
1878 {
1879 if (BitIsSet (registers, i))
1880 {
1881 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00001882 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001883 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1884 if (!success)
1885 return false;
1886
1887 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1888 return false;
1889
1890 offset += addr_byte_size;
1891 }
1892 }
1893
1894 // if registers<15> == ’1’ then
1895 // LoadWritePC(MemA[address,4]);
1896 if (BitIsSet (registers, 15))
1897 {
Caroline Tice85aab332011-02-08 23:56:10 +00001898 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001899 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1900 if (!success)
1901 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00001902 // In ARMv5T and above, this is an interworking branch.
1903 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00001904 return false;
1905 }
1906
1907 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1908 if (wback && BitIsClear (registers, n))
1909 {
Caroline Tice85aab332011-02-08 23:56:10 +00001910 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001911 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1912 if (!success)
1913 return false;
1914 addr = addr - (addr_byte_size * BitCount (registers));
1915 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1916 return false;
1917 }
1918
1919 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1920 if (wback && BitIsSet (registers, n))
1921 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1922 }
1923 return true;
1924}
Caroline Tice85aab332011-02-08 23:56:10 +00001925
1926bool
1927EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
1928{
1929#if 0
1930 if ConditionPassed() then
1931 EncodingSpecificOperations();
1932 address = R[n] + 4;
1933
1934 for i = 0 to 14
1935 if registers<i> == ’1’ then
1936 R[i] = MemA[address,4]; address = address + 4;
1937 if registers<15> == ’1’ then
1938 LoadWritePC(MemA[address,4]);
1939
1940 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1941 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
1942#endif
1943
1944 bool success = false;
1945 const uint32_t opcode = OpcodeAsUnsigned (&success);
1946 if (!success)
1947 return false;
1948
1949 if (ConditionPassed())
1950 {
1951 uint32_t n;
1952 uint32_t registers = 0;
1953 bool wback;
1954 const uint32_t addr_byte_size = GetAddressByteSize();
1955 switch (encoding)
1956 {
1957 case eEncodingA1:
1958 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1959 n = Bits32 (opcode, 19, 16);
1960 registers = Bits32 (opcode, 15, 0);
1961 wback = BitIsSet (opcode, 21);
1962
1963 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1964 if ((n == 15) || (BitCount (registers) < 1))
1965 return false;
1966
1967 break;
1968 default:
1969 return false;
1970 }
1971 // address = R[n] + 4;
1972
1973 int32_t offset = 0;
1974 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success) + addr_byte_size;
1975
1976 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1977 eRegisterKindDWARF,
1978 dwarf_r0 + n,
1979 offset };
1980
1981 for (int i = 0; i < 14; ++i)
1982 {
1983 if (BitIsSet (registers, i))
1984 {
1985 // R[i] = MemA[address,4]; address = address + 4;
1986
1987 context.arg2 = offset;
1988 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1989 if (!success)
1990 return false;
1991
1992 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1993 return false;
1994
1995 offset += addr_byte_size;
1996 }
1997 }
1998
1999 // if registers<15> == ’1’ then
2000 // LoadWritePC(MemA[address,4]);
2001 if (BitIsSet (registers, 15))
2002 {
2003 context.arg2 = offset;
2004 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2005 if (!success)
2006 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002007 // In ARMv5T and above, this is an interworking branch.
2008 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002009 return false;
2010 }
2011
2012 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2013 if (wback && BitIsClear (registers, n))
2014 {
2015 context.arg2 = offset;
2016 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2017 if (!success)
2018 return false;
2019 addr = addr + (addr_byte_size * BitCount (registers));
2020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2021 return false;
2022 }
2023
2024 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2025 if (wback && BitIsSet (registers, n))
2026 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
2027 }
2028 return true;
2029}
Caroline Tice0b29e242011-02-08 23:16:02 +00002030
Johnny Chenef21b592011-02-10 01:52:38 +00002031// Load Register (immediate) calculates an address from a base register value and
2032// an immediate offset, loads a word from memory, and writes to a register.
2033// LDR (immediate, Thumb)
2034bool
2035EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2036{
2037#if 0
2038 // ARM pseudo code...
2039 if (ConditionPassed())
2040 {
2041 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2042 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2043 address = if index then offset_addr else R[n];
2044 data = MemU[address,4];
2045 if wback then R[n] = offset_addr;
2046 if t == 15 then
2047 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2048 elsif UnalignedSupport() || address<1:0> = '00' then
2049 R[t] = data;
2050 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2051 }
2052#endif
2053
2054 bool success = false;
2055 const uint32_t opcode = OpcodeAsUnsigned (&success);
2056 if (!success)
2057 return false;
2058
2059 if (ConditionPassed())
2060 {
2061 uint32_t Rt; // the destination register
2062 uint32_t Rn; // the base register
2063 uint32_t imm32; // the immediate offset used to form the address
2064 addr_t offset_addr; // the offset address
2065 addr_t address; // the calculated address
2066 uint32_t data; // the literal data value from memory load
2067 bool add, index, wback;
2068 switch (encoding) {
2069 case eEncodingT1:
2070 Rt = Bits32(opcode, 5, 3);
2071 Rn = Bits32(opcode, 2, 0);
2072 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2073 // index = TRUE; add = TRUE; wback = FALSE
2074 add = true;
2075 index = true;
2076 wback = false;
2077 break;
2078 default:
2079 return false;
2080 }
2081 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2082 if (!success)
2083 return false;
2084 if (add)
2085 offset_addr = base + imm32;
2086 else
2087 offset_addr = base - imm32;
2088
2089 address = (index ? offset_addr : base);
2090
2091 if (wback)
2092 {
2093 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2094 eRegisterKindDWARF,
2095 dwarf_r0 + Rn,
2096 (int32_t) (offset_addr - base)};
2097 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2098 return false;
2099 }
2100
2101 // Prepare to write to the Rt register.
2102 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2103 0,
2104 0,
2105 0};
2106
2107 // Read memory from the address.
2108 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2109 if (!success)
2110 return false;
2111 context.arg0 = data;
2112
2113 if (Rt == 15)
2114 {
2115 if (Bits32(address, 1, 0) == 0)
2116 {
2117 if (!LoadWritePC(context, data))
2118 return false;
2119 }
2120 else
2121 return false;
2122 }
2123 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2124 {
2125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2126 return false;
2127 }
2128 else
2129 return false;
2130 }
2131 return true;
2132}
2133
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002134EmulateInstructionARM::ARMOpcode*
2135EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002136{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002137 static ARMOpcode
2138 g_arm_opcodes[] =
2139 {
2140 //----------------------------------------------------------------------
2141 // Prologue instructions
2142 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002144 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002145 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2146 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002147
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002148 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002149 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2150 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002151 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002152 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2153 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2154 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002155
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002156 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002157 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002158
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002159 // push one register
2160 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002161 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002162
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002163 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002164 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2165 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002166
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002167 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002168 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002169 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002170
Johnny Chen9b8d7832011-02-02 01:13:56 +00002171 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2172 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2173 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2174 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002175 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2176 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002177 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002178 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2179
2180 //----------------------------------------------------------------------
2181 // Supervisor Call (previously Software Interrupt)
2182 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002183 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2184
2185 //----------------------------------------------------------------------
2186 // Branch instructions
2187 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002188 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00002189
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002190 //----------------------------------------------------------------------
2191 // Load instructions
2192 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002193 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002194 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
2195 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002196
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002197 };
2198 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2199
2200 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2201 {
2202 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2203 return &g_arm_opcodes[i];
2204 }
2205 return NULL;
2206}
Greg Clayton64c84432011-01-21 22:02:52 +00002207
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002208
2209EmulateInstructionARM::ARMOpcode*
2210EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002211{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002212
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002213 static ARMOpcode
2214 g_thumb_opcodes[] =
2215 {
2216 //----------------------------------------------------------------------
2217 // Prologue instructions
2218 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002219
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002220 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002221 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002222 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2223 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002224
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002225 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002226 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002227 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002228 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002229 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2230 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002231
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002232 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002233 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002234
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002235 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002236 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2237 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002238 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2239 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002240
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002241 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002242 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2243 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002244
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002245 //----------------------------------------------------------------------
2246 // Epilogue instructions
2247 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002248
Johnny Chenc28a76d2011-02-01 18:51:48 +00002249 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002250 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
2251 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00002252 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2253 // J1 == J2 == 1
2254 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002255 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002256 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2257 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2258 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2259 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002260
2261 //----------------------------------------------------------------------
2262 // Supervisor Call (previously Software Interrupt)
2263 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002264 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2265
2266 //----------------------------------------------------------------------
2267 // If Then makes up to four following instructions conditional.
2268 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002269 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2270
2271 //----------------------------------------------------------------------
2272 // Branch instructions
2273 //----------------------------------------------------------------------
2274 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2275 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2276 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002277 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002278 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002279 // compare and branch
2280 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002281
2282 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002283 // Data-processing instructions
2284 //----------------------------------------------------------------------
2285 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2286 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002287 // move from high register to high register
2288 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2289 // move from low register to low register
2290 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002291
2292 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002293 // Load instructions
2294 //----------------------------------------------------------------------
2295 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002296 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002297 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
2298 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002299
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002300 };
2301
2302 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2303 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2304 {
2305 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2306 return &g_thumb_opcodes[i];
2307 }
2308 return NULL;
2309}
Greg Clayton64c84432011-01-21 22:02:52 +00002310
Greg Clayton31e2a382011-01-30 20:03:56 +00002311bool
2312EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2313{
2314 m_arm_isa = 0;
2315 const char *triple_cstr = triple.GetCString();
2316 if (triple_cstr)
2317 {
2318 const char *dash = ::strchr (triple_cstr, '-');
2319 if (dash)
2320 {
2321 std::string arch (triple_cstr, dash);
2322 const char *arch_cstr = arch.c_str();
2323 if (strcasecmp(arch_cstr, "armv4t") == 0)
2324 m_arm_isa = ARMv4T;
2325 else if (strcasecmp(arch_cstr, "armv4") == 0)
2326 m_arm_isa = ARMv4;
2327 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2328 m_arm_isa = ARMv5TEJ;
2329 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2330 m_arm_isa = ARMv5TE;
2331 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2332 m_arm_isa = ARMv5T;
2333 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2334 m_arm_isa = ARMv6K;
2335 else if (strcasecmp(arch_cstr, "armv6") == 0)
2336 m_arm_isa = ARMv6;
2337 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2338 m_arm_isa = ARMv6T2;
2339 else if (strcasecmp(arch_cstr, "armv7") == 0)
2340 m_arm_isa = ARMv7;
2341 else if (strcasecmp(arch_cstr, "armv8") == 0)
2342 m_arm_isa = ARMv8;
2343 }
2344 }
2345 return m_arm_isa != 0;
2346}
2347
2348
Greg Clayton64c84432011-01-21 22:02:52 +00002349bool
2350EmulateInstructionARM::ReadInstruction ()
2351{
2352 bool success = false;
2353 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2354 if (success)
2355 {
2356 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2357 if (success)
2358 {
2359 Context read_inst_context = {eContextReadOpcode, 0, 0};
2360 if (m_inst_cpsr & MASK_CPSR_T)
2361 {
2362 m_inst_mode = eModeThumb;
2363 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2364
2365 if (success)
2366 {
2367 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2368 {
2369 m_inst.opcode_type = eOpcode16;
2370 m_inst.opcode.inst16 = thumb_opcode;
2371 }
2372 else
2373 {
2374 m_inst.opcode_type = eOpcode32;
2375 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2376 }
2377 }
2378 }
2379 else
2380 {
2381 m_inst_mode = eModeARM;
2382 m_inst.opcode_type = eOpcode32;
2383 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2384 }
2385 }
2386 }
2387 if (!success)
2388 {
2389 m_inst_mode = eModeInvalid;
2390 m_inst_pc = LLDB_INVALID_ADDRESS;
2391 }
2392 return success;
2393}
2394
Johnny Chenee9b1f72011-02-09 01:00:31 +00002395uint32_t
2396EmulateInstructionARM::ArchVersion ()
2397{
2398 return m_arm_isa;
2399}
2400
Greg Clayton64c84432011-01-21 22:02:52 +00002401bool
2402EmulateInstructionARM::ConditionPassed ()
2403{
2404 if (m_inst_cpsr == 0)
2405 return false;
2406
2407 const uint32_t cond = CurrentCond ();
2408
2409 if (cond == UINT32_MAX)
2410 return false;
2411
2412 bool result = false;
2413 switch (UnsignedBits(cond, 3, 1))
2414 {
2415 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2416 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2417 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2418 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2419 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2420 case 5:
2421 {
2422 bool n = (m_inst_cpsr & MASK_CPSR_N);
2423 bool v = (m_inst_cpsr & MASK_CPSR_V);
2424 result = n == v;
2425 }
2426 break;
2427 case 6:
2428 {
2429 bool n = (m_inst_cpsr & MASK_CPSR_N);
2430 bool v = (m_inst_cpsr & MASK_CPSR_V);
2431 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2432 }
2433 break;
2434 case 7:
2435 result = true;
2436 break;
2437 }
2438
2439 if (cond & 1)
2440 result = !result;
2441 return result;
2442}
2443
Johnny Chen9ee056b2011-02-08 00:06:35 +00002444uint32_t
2445EmulateInstructionARM::CurrentCond ()
2446{
2447 switch (m_inst_mode)
2448 {
2449 default:
2450 case eModeInvalid:
2451 break;
2452
2453 case eModeARM:
2454 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2455
2456 case eModeThumb:
2457 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2458 // 'cond' field of the encoding.
2459 if (m_inst.opcode_type == eOpcode16 &&
2460 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2461 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2462 {
2463 return Bits32(m_inst.opcode.inst16, 11, 7);
2464 }
2465 else if (m_inst.opcode_type == eOpcode32 &&
2466 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2467 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2468 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2469 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2470 {
2471 return Bits32(m_inst.opcode.inst32, 25, 22);
2472 }
2473
2474 return m_it_session.GetCond();
2475 }
2476 return UINT32_MAX; // Return invalid value
2477}
2478
Johnny Chen9ee056b2011-02-08 00:06:35 +00002479bool
2480EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2481{
2482 addr_t target;
2483
Johnny Chenee9b1f72011-02-09 01:00:31 +00002484 // Check the current instruction set.
2485 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00002486 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002487 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00002488 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002489
Johnny Chen9ee056b2011-02-08 00:06:35 +00002490 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002491 return false;
2492
2493 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002494}
2495
2496// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2497bool
2498EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2499{
2500 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00002501 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
2502 // we want to record it and issue a WriteRegister callback so the clients
2503 // can track the mode changes accordingly.
2504 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002505
2506 if (BitIsSet(addr, 0))
2507 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002508 if (CurrentInstrSet() != eModeThumb)
2509 {
2510 SelectInstrSet(eModeThumb);
2511 cpsr_changed = true;
2512 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002513 target = addr & 0xfffffffe;
2514 context.arg2 = eModeThumb;
2515 }
2516 else if (BitIsClear(addr, 1))
2517 {
Johnny Chen0f309db2011-02-09 19:11:32 +00002518 if (CurrentInstrSet() != eModeARM)
2519 {
2520 SelectInstrSet(eModeARM);
2521 cpsr_changed = true;
2522 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002523 target = addr & 0xfffffffc;
2524 context.arg2 = eModeARM;
2525 }
2526 else
2527 return false; // address<1:0> == '10' => UNPREDICTABLE
2528
Johnny Chen0f309db2011-02-09 19:11:32 +00002529 if (cpsr_changed)
2530 {
Johnny Chen558133b2011-02-09 23:59:17 +00002531 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00002532 return false;
2533 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00002534 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002535 return false;
2536
2537 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002538}
Greg Clayton64c84432011-01-21 22:02:52 +00002539
Johnny Chenee9b1f72011-02-09 01:00:31 +00002540// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
2541bool
2542EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
2543{
2544 if (ArchVersion() >= ARMv5T)
2545 return BXWritePC(context, addr);
2546 else
2547 return BranchWritePC((const Context)context, addr);
2548}
2549
Johnny Chen26863dc2011-02-09 23:43:29 +00002550// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
2551bool
2552EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
2553{
2554 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
2555 return BXWritePC(context, addr);
2556 else
2557 return BranchWritePC((const Context)context, addr);
2558}
2559
Johnny Chenee9b1f72011-02-09 01:00:31 +00002560EmulateInstructionARM::Mode
2561EmulateInstructionARM::CurrentInstrSet ()
2562{
2563 return m_inst_mode;
2564}
2565
2566// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00002567// ReadInstruction() is performed. This function has a side effect of updating
2568// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00002569bool
2570EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
2571{
Johnny Chen558133b2011-02-09 23:59:17 +00002572 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002573 switch (arm_or_thumb)
2574 {
2575 default:
2576 return false;
2577 eModeARM:
2578 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002579 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002580 break;
2581 eModeThumb:
2582 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00002583 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002584 break;
2585 }
2586 return true;
2587}
2588
Johnny Chenef21b592011-02-10 01:52:38 +00002589// This function returns TRUE if the processor currently provides support for
2590// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
2591// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
2592bool
2593EmulateInstructionARM::UnalignedSupport()
2594{
2595 return (ArchVersion() >= ARMv7);
2596}
2597
Greg Clayton64c84432011-01-21 22:02:52 +00002598bool
2599EmulateInstructionARM::EvaluateInstruction ()
2600{
Johnny Chenc315f862011-02-05 00:46:10 +00002601 // Advance the ITSTATE bits to their values for the next instruction.
2602 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2603 m_it_session.ITAdvance();
2604
Greg Clayton64c84432011-01-21 22:02:52 +00002605 return false;
2606}