blob: af81223a39f01e1b9f20e606bf098425988a5e1a [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
Johnny Chen8584c922011-01-26 01:18:52 +000013#include "ARMDefines.h"
Johnny Chen4baf2e32011-01-24 18:24:53 +000014#include "ARMUtils.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000015#include "ARM_DWARF_Registers.h"
Johnny Chen9b8d7832011-02-02 01:13:56 +000016#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000017 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000018
19using namespace lldb;
20using namespace lldb_private;
21
Johnny Chen93070472011-02-04 23:02:47 +000022// A8.6.50
23// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
24static unsigned short CountITSize(unsigned ITMask) {
25 // First count the trailing zeros of the IT mask.
26 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
27 if (TZ > 3)
28 {
29 printf("Encoding error: IT Mask '0000'\n");
30 return 0;
31 }
32 return (4 - TZ);
33}
34
35// Init ITState. Note that at least one bit is always 1 in mask.
36bool ITSession::InitIT(unsigned short bits7_0)
37{
38 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
39 if (ITCounter == 0)
40 return false;
41
42 // A8.6.50 IT
43 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
44 if (FirstCond == 0xF)
45 {
46 printf("Encoding error: IT FirstCond '1111'\n");
47 return false;
48 }
49 if (FirstCond == 0xE && ITCounter != 1)
50 {
51 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
52 return false;
53 }
54
55 ITState = bits7_0;
56 return true;
57}
58
59// Update ITState if necessary.
60void ITSession::ITAdvance()
61{
62 assert(ITCounter);
63 --ITCounter;
64 if (ITCounter == 0)
65 ITState = 0;
66 else
67 {
68 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
69 SetBits32(ITState, 4, 0, NewITState4_0);
70 }
71}
72
73// Return true if we're inside an IT Block.
74bool ITSession::InITBlock()
75{
76 return ITCounter != 0;
77}
78
79// Get condition bits for the current thumb instruction.
80uint32_t ITSession::GetCond()
81{
82 return Bits32(ITState, 7, 4);
83}
84
Greg Clayton64c84432011-01-21 22:02:52 +000085// ARM constants used during decoding
86#define REG_RD 0
87#define LDM_REGLIST 1
88#define PC_REG 15
89#define PC_REGLIST_BIT 0x8000
90
Johnny Chen251af6a2011-01-21 22:47:25 +000091#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +000092#define ARMv4T (1u << 1)
93#define ARMv5T (1u << 2)
94#define ARMv5TE (1u << 3)
95#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +000096#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +000097#define ARMv6K (1u << 6)
98#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +000099#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000100#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000101#define ARMvAll (0xffffffffu)
102
Johnny Chen9b8d7832011-02-02 01:13:56 +0000103#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
104#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
105#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000106
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000107void
108EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000109{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000110}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000111
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000112void
113EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000114{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000115}
116
Greg Clayton64c84432011-01-21 22:02:52 +0000117
Johnny Chen08c25e82011-01-31 18:02:28 +0000118// Push Multiple Registers stores multiple registers to the stack, storing to
119// consecutive memory locations ending just below the address in SP, and updates
120// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000121bool
122EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000123{
124#if 0
125 // ARM pseudo code...
126 if (ConditionPassed())
127 {
128 EncodingSpecificOperations();
129 NullCheckIfThumbEE(13);
130 address = SP - 4*BitCount(registers);
131
132 for (i = 0 to 14)
133 {
134 if (registers<i> == ’1’)
135 {
136 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
137 MemA[address,4] = bits(32) UNKNOWN;
138 else
139 MemA[address,4] = R[i];
140 address = address + 4;
141 }
142 }
143
144 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
145 MemA[address,4] = PCStoreValue();
146
147 SP = SP - 4*BitCount(registers);
148 }
149#endif
150
151 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000152 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000153 if (!success)
154 return false;
155
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000156 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000157 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000158 const uint32_t addr_byte_size = GetAddressByteSize();
159 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000160 if (!success)
161 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000162 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000163 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000164 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000165 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000166 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000167 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000168 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000169 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000170 // if BitCount(registers) < 1 then UNPREDICTABLE;
171 if (BitCount(registers) < 1)
172 return false;
173 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000174 case eEncodingT2:
175 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000176 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000177 // if BitCount(registers) < 2 then UNPREDICTABLE;
178 if (BitCount(registers) < 2)
179 return false;
180 break;
181 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000182 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000183 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000184 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000185 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000186 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000187 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000188 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000189 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000190 // Instead of return false, let's handle the following case as well,
191 // which amounts to pushing one reg onto the full descending stacks.
192 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000193 break;
194 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000195 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000196 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000197 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000198 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000199 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000200 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000201 default:
202 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000203 }
Johnny Chence1ca772011-01-25 01:13:00 +0000204 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000205 addr_t addr = sp - sp_offset;
206 uint32_t i;
207
208 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
209 for (i=0; i<15; ++i)
210 {
Johnny Chen108d5aa2011-01-26 01:00:55 +0000211 if (BitIsSet (registers, 1u << i))
Greg Clayton64c84432011-01-21 22:02:52 +0000212 {
213 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
214 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000215 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000216 if (!success)
217 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000218 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000219 return false;
220 addr += addr_byte_size;
221 }
222 }
223
Johnny Chen108d5aa2011-01-26 01:00:55 +0000224 if (BitIsSet (registers, 1u << 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000225 {
226 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000227 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000231 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000232 return false;
233 }
234
235 context.type = EmulateInstruction::eContextAdjustStackPointer;
236 context.arg0 = eRegisterKindGeneric;
237 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000238 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000239
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000240 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000241 return false;
242 }
243 return true;
244}
245
Johnny Chenef85e912011-01-31 23:07:40 +0000246// Pop Multiple Registers loads multiple registers from the stack, loading from
247// consecutive memory locations staring at the address in SP, and updates
248// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000249bool
250EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000251{
252#if 0
253 // ARM pseudo code...
254 if (ConditionPassed())
255 {
256 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
257 address = SP;
258 for i = 0 to 14
259 if registers<i> == ‘1’ then
260 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
261 if registers<15> == ‘1’ then
262 if UnalignedAllowed then
263 LoadWritePC(MemU[address,4]);
264 else
265 LoadWritePC(MemA[address,4]);
266 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
267 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
268 }
269#endif
270
271 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000272 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000273 if (!success)
274 return false;
275
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000276 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000277 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000278 const uint32_t addr_byte_size = GetAddressByteSize();
279 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000280 if (!success)
281 return false;
282 uint32_t registers = 0;
283 uint32_t Rt; // the destination register
284 switch (encoding) {
285 case eEncodingT1:
286 registers = Bits32(opcode, 7, 0);
287 // The P bit represents PC.
288 if (Bits32(opcode, 8, 8))
289 registers |= (1u << 15);
290 // if BitCount(registers) < 1 then UNPREDICTABLE;
291 if (BitCount(registers) < 1)
292 return false;
293 break;
294 case eEncodingT2:
295 // Ignore bit 13.
296 registers = Bits32(opcode, 15, 0) & ~0x2000;
297 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
298 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
299 return false;
300 break;
301 case eEncodingT3:
302 Rt = Bits32(opcode, 15, 12);
303 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
304 if (Rt == dwarf_sp)
305 return false;
306 registers = (1u << Rt);
307 break;
308 case eEncodingA1:
309 registers = Bits32(opcode, 15, 0);
310 // Instead of return false, let's handle the following case as well,
311 // which amounts to popping one reg from the full descending stacks.
312 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
313
314 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
315 if (Bits32(opcode, 13, 13))
316 return false;
317 break;
318 case eEncodingA2:
319 Rt = Bits32(opcode, 15, 12);
320 // if t == 13 then UNPREDICTABLE;
321 if (Rt == dwarf_sp)
322 return false;
323 registers = (1u << Rt);
324 break;
325 default:
326 return false;
327 }
328 addr_t sp_offset = addr_byte_size * BitCount (registers);
329 addr_t addr = sp;
330 uint32_t i, data;
331
332 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
333 for (i=0; i<15; ++i)
334 {
335 if (BitIsSet (registers, 1u << i))
336 {
337 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
338 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000339 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000340 if (!success)
341 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000343 return false;
344 addr += addr_byte_size;
345 }
346 }
347
348 if (BitIsSet (registers, 1u << 15))
349 {
350 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
351 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000353 if (!success)
354 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000355 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 return false;
357 addr += addr_byte_size;
358 }
359
360 context.type = EmulateInstruction::eContextAdjustStackPointer;
361 context.arg0 = eRegisterKindGeneric;
362 context.arg1 = LLDB_REGNUM_GENERIC_SP;
363 context.arg2 = sp_offset;
364
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000365 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
367 }
368 return true;
369}
370
Johnny Chen5b442b72011-01-27 19:34:30 +0000371// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000372// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000373bool
374EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000375{
376#if 0
377 // ARM pseudo code...
378 if (ConditionPassed())
379 {
380 EncodingSpecificOperations();
381 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
382 if d == 15 then
383 ALUWritePC(result); // setflags is always FALSE here
384 else
385 R[d] = result;
386 if setflags then
387 APSR.N = result<31>;
388 APSR.Z = IsZeroBit(result);
389 APSR.C = carry;
390 APSR.V = overflow;
391 }
392#endif
393
394 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000395 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000396 if (!success)
397 return false;
398
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000399 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000400 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000401 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000402 if (!success)
403 return false;
404 uint32_t Rd; // the destination register
405 uint32_t imm32;
406 switch (encoding) {
407 case eEncodingT1:
408 Rd = 7;
409 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
410 break;
411 case eEncodingA1:
412 Rd = Bits32(opcode, 15, 12);
413 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
414 break;
415 default:
416 return false;
417 }
418 addr_t sp_offset = imm32;
419 addr_t addr = sp + sp_offset; // a pointer to the stack area
420
421 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
422 eRegisterKindGeneric,
423 LLDB_REGNUM_GENERIC_SP,
424 sp_offset };
425
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000427 return false;
428 }
429 return true;
430}
431
Johnny Chen2ccad832011-01-28 19:57:25 +0000432// Set r7 or ip to the current stack pointer.
433// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000434bool
435EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000436{
437#if 0
438 // ARM pseudo code...
439 if (ConditionPassed())
440 {
441 EncodingSpecificOperations();
442 result = R[m];
443 if d == 15 then
444 ALUWritePC(result); // setflags is always FALSE here
445 else
446 R[d] = result;
447 if setflags then
448 APSR.N = result<31>;
449 APSR.Z = IsZeroBit(result);
450 // APSR.C unchanged
451 // APSR.V unchanged
452 }
453#endif
454
455 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000456 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000457 //if (!success)
458 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000459
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000460 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000461 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000462 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000463 if (!success)
464 return false;
465 uint32_t Rd; // the destination register
466 switch (encoding) {
467 case eEncodingT1:
468 Rd = 7;
469 break;
470 case eEncodingA1:
471 Rd = 12;
472 break;
473 default:
474 return false;
475 }
476 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
477 eRegisterKindGeneric,
478 LLDB_REGNUM_GENERIC_SP,
479 0 };
480
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000481 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000482 return false;
483 }
484 return true;
485}
486
Johnny Chen1c13b622011-01-29 00:11:15 +0000487// Move from high register (r8-r15) to low register (r0-r7).
488// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000489bool
490EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000491{
492#if 0
493 // ARM pseudo code...
494 if (ConditionPassed())
495 {
496 EncodingSpecificOperations();
497 result = R[m];
498 if d == 15 then
499 ALUWritePC(result); // setflags is always FALSE here
500 else
501 R[d] = result;
502 if setflags then
503 APSR.N = result<31>;
504 APSR.Z = IsZeroBit(result);
505 // APSR.C unchanged
506 // APSR.V unchanged
507 }
508#endif
509
510 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000511 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000512 if (!success)
513 return false;
514
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000515 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000516 {
517 uint32_t Rm; // the source register
518 uint32_t Rd; // the destination register
519 switch (encoding) {
520 case eEncodingT1:
521 Rm = Bits32(opcode, 6, 3);
522 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
523 break;
524 default:
525 return false;
526 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000527 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000528 if (!success)
529 return false;
530
531 // The context specifies that Rm is to be moved into Rd.
532 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
533 eRegisterKindDWARF,
534 dwarf_r0 + Rm,
535 0 };
536
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000537 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000538 return false;
539 }
540 return true;
541}
542
Johnny Chen788e0552011-01-27 22:52:23 +0000543// PC relative immediate load into register, possibly followed by ADD (SP plus register).
544// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000545bool
546EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000547{
548#if 0
549 // ARM pseudo code...
550 if (ConditionPassed())
551 {
552 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
553 base = Align(PC,4);
554 address = if add then (base + imm32) else (base - imm32);
555 data = MemU[address,4];
556 if t == 15 then
557 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
558 elsif UnalignedSupport() || address<1:0> = ‘00’ then
559 R[t] = data;
560 else // Can only apply before ARMv7
561 if CurrentInstrSet() == InstrSet_ARM then
562 R[t] = ROR(data, 8*UInt(address<1:0>));
563 else
564 R[t] = bits(32) UNKNOWN;
565 }
566#endif
567
568 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000570 if (!success)
571 return false;
572
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000573 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000574 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000575 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000576 if (!success)
577 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000578
579 // PC relative immediate load context
580 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
581 eRegisterKindGeneric,
582 LLDB_REGNUM_GENERIC_PC,
583 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000584 uint32_t Rd; // the destination register
585 uint32_t imm32; // immediate offset from the PC
586 addr_t addr; // the PC relative address
587 uint32_t data; // the literal data value from the PC relative load
588 switch (encoding) {
589 case eEncodingT1:
590 Rd = Bits32(opcode, 10, 8);
591 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
592 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000593 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000594 break;
595 default:
596 return false;
597 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000598 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000599 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000600 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000601 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000602 return false;
603 }
604 return true;
605}
606
Johnny Chen5b442b72011-01-27 19:34:30 +0000607// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000608// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000609bool
610EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000611{
612#if 0
613 // ARM pseudo code...
614 if (ConditionPassed())
615 {
616 EncodingSpecificOperations();
617 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
618 if d == 15 then // Can only occur for ARM encoding
619 ALUWritePC(result); // setflags is always FALSE here
620 else
621 R[d] = result;
622 if setflags then
623 APSR.N = result<31>;
624 APSR.Z = IsZeroBit(result);
625 APSR.C = carry;
626 APSR.V = overflow;
627 }
628#endif
629
630 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000631 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000632 if (!success)
633 return false;
634
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000635 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000636 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000637 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000638 if (!success)
639 return false;
640 uint32_t imm32; // the immediate operand
641 switch (encoding) {
642 case eEncodingT2:
643 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
644 break;
645 default:
646 return false;
647 }
648 addr_t sp_offset = imm32;
649 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
650
651 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
652 eRegisterKindGeneric,
653 LLDB_REGNUM_GENERIC_SP,
654 sp_offset };
655
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000656 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000657 return false;
658 }
659 return true;
660}
661
662// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000663// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000664bool
665EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000666{
667#if 0
668 // ARM pseudo code...
669 if (ConditionPassed())
670 {
671 EncodingSpecificOperations();
672 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
673 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
674 if d == 15 then
675 ALUWritePC(result); // setflags is always FALSE here
676 else
677 R[d] = result;
678 if setflags then
679 APSR.N = result<31>;
680 APSR.Z = IsZeroBit(result);
681 APSR.C = carry;
682 APSR.V = overflow;
683 }
684#endif
685
686 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000687 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000688 if (!success)
689 return false;
690
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000691 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000692 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000693 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000694 if (!success)
695 return false;
696 uint32_t Rm; // the second operand
697 switch (encoding) {
698 case eEncodingT2:
699 Rm = Bits32(opcode, 6, 3);
700 break;
701 default:
702 return false;
703 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000704 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000705 if (!success)
706 return false;
707
708 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
709
710 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
711 eRegisterKindGeneric,
712 LLDB_REGNUM_GENERIC_SP,
713 reg_value };
714
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000715 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000716 return false;
717 }
718 return true;
719}
720
Johnny Chen9b8d7832011-02-02 01:13:56 +0000721// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
722// at a PC-relative address, and changes instruction set from ARM to Thumb, or
723// from Thumb to ARM.
724// BLX (immediate)
725bool
726EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
727{
728#if 0
729 // ARM pseudo code...
730 if (ConditionPassed())
731 {
732 EncodingSpecificOperations();
733 if CurrentInstrSet() == InstrSet_ARM then
734 LR = PC - 4;
735 else
736 LR = PC<31:1> : '1';
737 if targetInstrSet == InstrSet_ARM then
738 targetAddress = Align(PC,4) + imm32;
739 else
740 targetAddress = PC + imm32;
741 SelectInstrSet(targetInstrSet);
742 BranchWritePC(targetAddress);
743 }
744#endif
745
746 bool success = false;
747 const uint32_t opcode = OpcodeAsUnsigned (&success);
748 if (!success)
749 return false;
750
751 if (ConditionPassed())
752 {
753 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
754 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
755 addr_t lr; // next instruction address
756 addr_t target; // target address
757 if (!success)
758 return false;
759 int32_t imm32; // PC-relative offset
760 switch (encoding) {
761 case eEncodingT2:
762 {
763 lr = (pc + 4) | 1u; // return address
764 uint32_t S = Bits32(opcode, 26, 26);
765 uint32_t imm10H = Bits32(opcode, 25, 16);
766 uint32_t J1 = Bits32(opcode, 13, 13);
767 uint32_t J2 = Bits32(opcode, 11, 11);
768 uint32_t imm10L = Bits32(opcode, 10, 1);
769 uint32_t I1 = !(J1 ^ S);
770 uint32_t I2 = !(J2 ^ S);
771 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
772 imm32 = llvm::SignExtend32<25>(imm25);
773 target = (pc & 0xfffffffc) + 4 + imm32;
774 context.arg1 = eModeARM; // target instruction set
775 context.arg2 = 4 + imm32; // signed offset
776 break;
777 }
778 case eEncodingA2:
779 lr = pc + 4; // return address
780 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
781 target = pc + 8 + imm32;
782 context.arg1 = eModeThumb; // target instruction set
783 context.arg2 = 8 + imm32; // signed offset
784 break;
785 default:
786 return false;
787 }
788 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
789 return false;
790 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
791 return false;
792 }
793 return true;
794}
795
796// Branch with Link and Exchange (register) calls a subroutine at an address and
797// instruction set specified by a register.
798// BLX (register)
799bool
800EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
801{
802#if 0
803 // ARM pseudo code...
804 if (ConditionPassed())
805 {
806 EncodingSpecificOperations();
807 target = R[m];
808 if CurrentInstrSet() == InstrSet_ARM then
809 next_instr_addr = PC - 4;
810 LR = next_instr_addr;
811 else
812 next_instr_addr = PC - 2;
813 LR = next_instr_addr<31:1> : ‘1’;
814 BXWritePC(target);
815 }
816#endif
817
818 bool success = false;
819 const uint32_t opcode = OpcodeAsUnsigned (&success);
820 if (!success)
821 return false;
822
823 if (ConditionPassed())
824 {
825 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
826 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
827 addr_t lr; // next instruction address
828 addr_t target; // target address
829 if (!success)
830 return false;
831 uint32_t Rm; // the register with the target address
832 switch (encoding) {
833 case eEncodingT1:
834 lr = (pc + 2) | 1u; // return address
835 Rm = Bits32(opcode, 6, 3);
836 // if m == 15 then UNPREDICTABLE;
837 if (Rm == 15)
838 return false;
839 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
840 break;
841 case eEncodingA1:
842 lr = pc + 4; // return address
843 Rm = Bits32(opcode, 3, 0);
844 // if m == 15 then UNPREDICTABLE;
845 if (Rm == 15)
846 return false;
847 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000848 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000849 default:
850 return false;
851 }
852 bool toThumb;
853 if (BitIsSet(target, 0))
854 toThumb = true;
855 else if (BitIsClear(target, 1))
856 toThumb = false;
857 else
858 return false; // address<1:0> == ‘10’ => UNPREDICTABLE
859 context.arg0 = eRegisterKindDWARF;
860 context.arg1 = dwarf_r0 + Rm;
861 context.arg2 = toThumb ? eModeThumb : eModeARM;
862 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
863 return false;
864 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
865 return false;
866 }
867 return true;
868}
869
Johnny Chen0d0148e2011-01-28 02:26:08 +0000870// Set r7 to point to some ip offset.
871// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000872bool
873EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000874{
875#if 0
876 // ARM pseudo code...
877 if (ConditionPassed())
878 {
879 EncodingSpecificOperations();
880 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
881 if d == 15 then // Can only occur for ARM encoding
882 ALUWritePC(result); // setflags is always FALSE here
883 else
884 R[d] = result;
885 if setflags then
886 APSR.N = result<31>;
887 APSR.Z = IsZeroBit(result);
888 APSR.C = carry;
889 APSR.V = overflow;
890 }
891#endif
892
893 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000894 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000895 if (!success)
896 return false;
897
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000898 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000899 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000900 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000901 if (!success)
902 return false;
903 uint32_t imm32;
904 switch (encoding) {
905 case eEncodingA1:
906 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
907 break;
908 default:
909 return false;
910 }
911 addr_t ip_offset = imm32;
912 addr_t addr = ip - ip_offset; // the adjusted ip value
913
914 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
915 eRegisterKindDWARF,
916 dwarf_r12,
917 -ip_offset };
918
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000919 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000920 return false;
921 }
922 return true;
923}
924
925// Set ip to point to some stack offset.
926// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927bool
928EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000929{
930#if 0
931 // ARM pseudo code...
932 if (ConditionPassed())
933 {
934 EncodingSpecificOperations();
935 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
936 if d == 15 then // Can only occur for ARM encoding
937 ALUWritePC(result); // setflags is always FALSE here
938 else
939 R[d] = result;
940 if setflags then
941 APSR.N = result<31>;
942 APSR.Z = IsZeroBit(result);
943 APSR.C = carry;
944 APSR.V = overflow;
945 }
946#endif
947
948 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000949 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000950 if (!success)
951 return false;
952
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000953 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000954 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000955 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000956 if (!success)
957 return false;
958 uint32_t imm32;
959 switch (encoding) {
960 case eEncodingA1:
961 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
962 break;
963 default:
964 return false;
965 }
966 addr_t sp_offset = imm32;
967 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
968
969 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
970 eRegisterKindGeneric,
971 LLDB_REGNUM_GENERIC_SP,
972 -sp_offset };
973
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000975 return false;
976 }
977 return true;
978}
979
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000980// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000981bool
982EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000983{
984#if 0
985 // ARM pseudo code...
986 if (ConditionPassed())
987 {
988 EncodingSpecificOperations();
989 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
990 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +0000991 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000992 else
993 R[d] = result;
994 if setflags then
995 APSR.N = result<31>;
996 APSR.Z = IsZeroBit(result);
997 APSR.C = carry;
998 APSR.V = overflow;
999 }
1000#endif
1001
1002 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001003 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001004 if (!success)
1005 return false;
1006
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001007 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001008 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001009 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001010 if (!success)
1011 return false;
1012 uint32_t imm32;
1013 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001014 case eEncodingT1:
1015 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001016 case eEncodingT2:
1017 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1018 break;
1019 case eEncodingT3:
1020 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1021 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001022 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001023 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001024 break;
1025 default:
1026 return false;
1027 }
1028 addr_t sp_offset = imm32;
1029 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1030
1031 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1032 eRegisterKindGeneric,
1033 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001034 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001037 return false;
1038 }
1039 return true;
1040}
1041
Johnny Chen08c25e82011-01-31 18:02:28 +00001042// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001043bool
1044EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001045{
1046#if 0
1047 // ARM pseudo code...
1048 if (ConditionPassed())
1049 {
1050 EncodingSpecificOperations();
1051 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1052 address = if index then offset_addr else R[n];
1053 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1054 if wback then R[n] = offset_addr;
1055 }
1056#endif
1057
1058 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001059 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001060 if (!success)
1061 return false;
1062
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001063 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001064 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001065 const uint32_t addr_byte_size = GetAddressByteSize();
1066 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001067 if (!success)
1068 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001069 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001070 uint32_t imm12;
1071 switch (encoding) {
1072 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001073 Rt = Bits32(opcode, 15, 12);
1074 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001075 break;
1076 default:
1077 return false;
1078 }
1079 addr_t sp_offset = imm12;
1080 addr_t addr = sp - sp_offset;
1081
1082 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001083 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001084 {
Johnny Chen91d99862011-01-25 19:07:04 +00001085 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1086 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001087 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001088 if (!success)
1089 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001090 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001091 return false;
1092 }
1093 else
1094 {
1095 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1096 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001097 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001098 if (!success)
1099 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001100 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001101 return false;
1102 }
1103
1104 context.type = EmulateInstruction::eContextAdjustStackPointer;
1105 context.arg0 = eRegisterKindGeneric;
1106 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001107 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001108
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001109 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001110 return false;
1111 }
1112 return true;
1113}
1114
Johnny Chen08c25e82011-01-31 18:02:28 +00001115// Vector Push stores multiple extension registers to the stack.
1116// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001117bool
1118EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001119{
1120#if 0
1121 // ARM pseudo code...
1122 if (ConditionPassed())
1123 {
1124 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1125 address = SP - imm32;
1126 SP = SP - imm32;
1127 if single_regs then
1128 for r = 0 to regs-1
1129 MemA[address,4] = S[d+r]; address = address+4;
1130 else
1131 for r = 0 to regs-1
1132 // Store as two word-aligned words in the correct order for current endianness.
1133 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1134 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1135 address = address+8;
1136 }
1137#endif
1138
1139 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001141 if (!success)
1142 return false;
1143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001144 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001145 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001146 const uint32_t addr_byte_size = GetAddressByteSize();
1147 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001148 if (!success)
1149 return false;
1150 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001151 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001152 uint32_t imm32; // stack offset
1153 uint32_t regs; // number of registers
1154 switch (encoding) {
1155 case eEncodingT1:
1156 case eEncodingA1:
1157 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001158 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001159 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1160 // If UInt(imm8) is odd, see "FSTMX".
1161 regs = Bits32(opcode, 7, 0) / 2;
1162 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1163 if (regs == 0 || regs > 16 || (d + regs) > 32)
1164 return false;
1165 break;
1166 case eEncodingT2:
1167 case eEncodingA2:
1168 single_regs = true;
1169 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1170 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1171 regs = Bits32(opcode, 7, 0);
1172 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1173 if (regs == 0 || regs > 16 || (d + regs) > 32)
1174 return false;
1175 break;
1176 default:
1177 return false;
1178 }
1179 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1180 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1181 addr_t sp_offset = imm32;
1182 addr_t addr = sp - sp_offset;
1183 uint32_t i;
1184
1185 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1186 for (i=d; i<regs; ++i)
1187 {
1188 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1189 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1190 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001191 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001192 if (!success)
1193 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001194 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001195 return false;
1196 addr += reg_byte_size;
1197 }
1198
1199 context.type = EmulateInstruction::eContextAdjustStackPointer;
1200 context.arg0 = eRegisterKindGeneric;
1201 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001202 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001203
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001204 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001205 return false;
1206 }
1207 return true;
1208}
1209
Johnny Chen587a0a42011-02-01 18:35:28 +00001210// Vector Pop loads multiple extension registers from the stack.
1211// It also updates SP to point just above the loaded data.
1212bool
1213EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1214{
1215#if 0
1216 // ARM pseudo code...
1217 if (ConditionPassed())
1218 {
1219 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1220 address = SP;
1221 SP = SP + imm32;
1222 if single_regs then
1223 for r = 0 to regs-1
1224 S[d+r] = MemA[address,4]; address = address+4;
1225 else
1226 for r = 0 to regs-1
1227 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1228 // Combine the word-aligned words in the correct order for current endianness.
1229 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1230 }
1231#endif
1232
1233 bool success = false;
1234 const uint32_t opcode = OpcodeAsUnsigned (&success);
1235 if (!success)
1236 return false;
1237
1238 if (ConditionPassed())
1239 {
1240 const uint32_t addr_byte_size = GetAddressByteSize();
1241 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1242 if (!success)
1243 return false;
1244 bool single_regs;
1245 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1246 uint32_t imm32; // stack offset
1247 uint32_t regs; // number of registers
1248 switch (encoding) {
1249 case eEncodingT1:
1250 case eEncodingA1:
1251 single_regs = false;
1252 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1253 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1254 // If UInt(imm8) is odd, see "FLDMX".
1255 regs = Bits32(opcode, 7, 0) / 2;
1256 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1257 if (regs == 0 || regs > 16 || (d + regs) > 32)
1258 return false;
1259 break;
1260 case eEncodingT2:
1261 case eEncodingA2:
1262 single_regs = true;
1263 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1264 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1265 regs = Bits32(opcode, 7, 0);
1266 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1267 if (regs == 0 || regs > 16 || (d + regs) > 32)
1268 return false;
1269 break;
1270 default:
1271 return false;
1272 }
1273 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1274 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1275 addr_t sp_offset = imm32;
1276 addr_t addr = sp;
1277 uint32_t i;
1278 uint64_t data; // uint64_t to accomodate 64-bit registers.
1279
1280 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1281 for (i=d; i<regs; ++i)
1282 {
1283 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1284 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1285 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1286 if (!success)
1287 return false;
1288 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1289 return false;
1290 addr += reg_byte_size;
1291 }
1292
1293 context.type = EmulateInstruction::eContextAdjustStackPointer;
1294 context.arg0 = eRegisterKindGeneric;
1295 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1296 context.arg2 = sp_offset;
1297
1298 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1299 return false;
1300 }
1301 return true;
1302}
1303
Johnny Chenb77be412011-02-04 00:40:18 +00001304// SVC (previously SWI)
1305bool
1306EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1307{
1308#if 0
1309 // ARM pseudo code...
1310 if (ConditionPassed())
1311 {
1312 EncodingSpecificOperations();
1313 CallSupervisor();
1314 }
1315#endif
1316
1317 bool success = false;
1318 const uint32_t opcode = OpcodeAsUnsigned (&success);
1319 if (!success)
1320 return false;
1321
1322 if (ConditionPassed())
1323 {
1324 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1325 addr_t lr; // next instruction address
1326 if (!success)
1327 return false;
1328 uint32_t imm32; // the immediate constant
1329 uint32_t mode; // ARM or Thumb mode
1330 switch (encoding) {
1331 case eEncodingT1:
1332 lr = (pc + 2) | 1u; // return address
1333 imm32 = Bits32(opcode, 7, 0);
1334 mode = eModeThumb;
1335 break;
1336 case eEncodingA1:
1337 lr = pc + 4; // return address
1338 imm32 = Bits32(opcode, 23, 0);
1339 mode = eModeARM;
1340 break;
1341 default:
1342 return false;
1343 }
1344 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1345 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1346 return false;
1347 }
1348 return true;
1349}
1350
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001351EmulateInstructionARM::ARMOpcode*
1352EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001353{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001354 static ARMOpcode
1355 g_arm_opcodes[] =
1356 {
1357 //----------------------------------------------------------------------
1358 // Prologue instructions
1359 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001360
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001361 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001362 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1363 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001364
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001365 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001366 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1367 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001368 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001369 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1370 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1371 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001372
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001373 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001374 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001375
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001376 // push one register
1377 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001378 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001379
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001380 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1382 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001383
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001384 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001385 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001386 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001387
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1389 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1390 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1391 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001392 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1393 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001394 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001395 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1396
1397 //----------------------------------------------------------------------
1398 // Supervisor Call (previously Software Interrupt)
1399 //----------------------------------------------------------------------
1400 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}
1401
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001402 };
1403 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1404
1405 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1406 {
1407 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1408 return &g_arm_opcodes[i];
1409 }
1410 return NULL;
1411}
Greg Clayton64c84432011-01-21 22:02:52 +00001412
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001413
1414EmulateInstructionARM::ARMOpcode*
1415EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001416{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001417
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001418 static ARMOpcode
1419 g_thumb_opcodes[] =
1420 {
1421 //----------------------------------------------------------------------
1422 // Prologue instructions
1423 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001424
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001425 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001426 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1427 { 0xffff0000, 0xe92d0000, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1428 { 0xffff0fff, 0xf84d0d04, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001429 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001430 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001431
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001432 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001433 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1434 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001435
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001436 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001437 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001438
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001439 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001440 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1441 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
1442 { 0xfbef8f00, 0xf1ad0d00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1443 { 0xfbff8f00, 0xf2ad0d00, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001444
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001445 // vector push consecutive extension register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001446 { 0xffbf0f00, 0xed2d0b00, ARMv6T2|ARMv7, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1447 { 0xffbf0f00, 0xed2d0a00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001448
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001449 //----------------------------------------------------------------------
1450 // Epilogue instructions
1451 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001452
Johnny Chenc28a76d2011-02-01 18:51:48 +00001453 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001454 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1455 // J1 == J2 == 1
1456 { 0xf800e801, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001457 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1458 { 0xffff0000, 0xe8bd0000, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1459 { 0xffff0fff, 0xf85d0d04, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1460 { 0xffbf0f00, 0xecbd0b00, ARMv6T2|ARMv7, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001461 { 0xffbf0f00, 0xecbd0a00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1462
1463 //----------------------------------------------------------------------
1464 // Supervisor Call (previously Software Interrupt)
1465 //----------------------------------------------------------------------
1466 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}
1467
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001468 };
1469
1470 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1471 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1472 {
1473 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1474 return &g_thumb_opcodes[i];
1475 }
1476 return NULL;
1477}
Greg Clayton64c84432011-01-21 22:02:52 +00001478
Greg Clayton31e2a382011-01-30 20:03:56 +00001479bool
1480EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1481{
1482 m_arm_isa = 0;
1483 const char *triple_cstr = triple.GetCString();
1484 if (triple_cstr)
1485 {
1486 const char *dash = ::strchr (triple_cstr, '-');
1487 if (dash)
1488 {
1489 std::string arch (triple_cstr, dash);
1490 const char *arch_cstr = arch.c_str();
1491 if (strcasecmp(arch_cstr, "armv4t") == 0)
1492 m_arm_isa = ARMv4T;
1493 else if (strcasecmp(arch_cstr, "armv4") == 0)
1494 m_arm_isa = ARMv4;
1495 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1496 m_arm_isa = ARMv5TEJ;
1497 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1498 m_arm_isa = ARMv5TE;
1499 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1500 m_arm_isa = ARMv5T;
1501 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1502 m_arm_isa = ARMv6K;
1503 else if (strcasecmp(arch_cstr, "armv6") == 0)
1504 m_arm_isa = ARMv6;
1505 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1506 m_arm_isa = ARMv6T2;
1507 else if (strcasecmp(arch_cstr, "armv7") == 0)
1508 m_arm_isa = ARMv7;
1509 else if (strcasecmp(arch_cstr, "armv8") == 0)
1510 m_arm_isa = ARMv8;
1511 }
1512 }
1513 return m_arm_isa != 0;
1514}
1515
1516
Greg Clayton64c84432011-01-21 22:02:52 +00001517bool
1518EmulateInstructionARM::ReadInstruction ()
1519{
1520 bool success = false;
1521 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1522 if (success)
1523 {
1524 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1525 if (success)
1526 {
1527 Context read_inst_context = {eContextReadOpcode, 0, 0};
1528 if (m_inst_cpsr & MASK_CPSR_T)
1529 {
1530 m_inst_mode = eModeThumb;
1531 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
1532
1533 if (success)
1534 {
1535 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
1536 {
1537 m_inst.opcode_type = eOpcode16;
1538 m_inst.opcode.inst16 = thumb_opcode;
1539 }
1540 else
1541 {
1542 m_inst.opcode_type = eOpcode32;
1543 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
1544 }
1545 }
1546 }
1547 else
1548 {
1549 m_inst_mode = eModeARM;
1550 m_inst.opcode_type = eOpcode32;
1551 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
1552 }
1553 }
1554 }
1555 if (!success)
1556 {
1557 m_inst_mode = eModeInvalid;
1558 m_inst_pc = LLDB_INVALID_ADDRESS;
1559 }
1560 return success;
1561}
1562
1563uint32_t
1564EmulateInstructionARM::CurrentCond ()
1565{
1566 switch (m_inst_mode)
1567 {
1568 default:
1569 case eModeInvalid:
1570 break;
1571
1572 case eModeARM:
1573 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
1574
1575 case eModeThumb:
1576 return 0x0000000Eu; // Return always for now, we need to handl IT instructions later
1577 }
1578 return UINT32_MAX; // Return invalid value
1579}
1580bool
1581EmulateInstructionARM::ConditionPassed ()
1582{
1583 if (m_inst_cpsr == 0)
1584 return false;
1585
1586 const uint32_t cond = CurrentCond ();
1587
1588 if (cond == UINT32_MAX)
1589 return false;
1590
1591 bool result = false;
1592 switch (UnsignedBits(cond, 3, 1))
1593 {
1594 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
1595 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
1596 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
1597 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
1598 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
1599 case 5:
1600 {
1601 bool n = (m_inst_cpsr & MASK_CPSR_N);
1602 bool v = (m_inst_cpsr & MASK_CPSR_V);
1603 result = n == v;
1604 }
1605 break;
1606 case 6:
1607 {
1608 bool n = (m_inst_cpsr & MASK_CPSR_N);
1609 bool v = (m_inst_cpsr & MASK_CPSR_V);
1610 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
1611 }
1612 break;
1613 case 7:
1614 result = true;
1615 break;
1616 }
1617
1618 if (cond & 1)
1619 result = !result;
1620 return result;
1621}
1622
1623
1624bool
1625EmulateInstructionARM::EvaluateInstruction ()
1626{
1627 return false;
1628}