blob: 8ab253597549a84a9c46d49f73f5e5dfa36e1e9e [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 Chend6c13f02011-02-08 20:36:34 +000022static inline uint32_t Align(uint32_t val, uint32_t alignment)
23{
24 return alignment * (val / alignment);
25}
26
Johnny Chen93070472011-02-04 23:02:47 +000027// A8.6.50
28// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
29static unsigned short CountITSize(unsigned ITMask) {
30 // First count the trailing zeros of the IT mask.
31 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
32 if (TZ > 3)
33 {
34 printf("Encoding error: IT Mask '0000'\n");
35 return 0;
36 }
37 return (4 - TZ);
38}
39
40// Init ITState. Note that at least one bit is always 1 in mask.
41bool ITSession::InitIT(unsigned short bits7_0)
42{
43 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
44 if (ITCounter == 0)
45 return false;
46
47 // A8.6.50 IT
48 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
49 if (FirstCond == 0xF)
50 {
51 printf("Encoding error: IT FirstCond '1111'\n");
52 return false;
53 }
54 if (FirstCond == 0xE && ITCounter != 1)
55 {
56 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
57 return false;
58 }
59
60 ITState = bits7_0;
61 return true;
62}
63
64// Update ITState if necessary.
65void ITSession::ITAdvance()
66{
67 assert(ITCounter);
68 --ITCounter;
69 if (ITCounter == 0)
70 ITState = 0;
71 else
72 {
73 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
74 SetBits32(ITState, 4, 0, NewITState4_0);
75 }
76}
77
78// Return true if we're inside an IT Block.
79bool ITSession::InITBlock()
80{
81 return ITCounter != 0;
82}
83
Johnny Chenc315f862011-02-05 00:46:10 +000084// Return true if we're the last instruction inside an IT Block.
85bool ITSession::LastInITBlock()
86{
87 return ITCounter == 1;
88}
89
Johnny Chen93070472011-02-04 23:02:47 +000090// Get condition bits for the current thumb instruction.
91uint32_t ITSession::GetCond()
92{
Johnny Chenc315f862011-02-05 00:46:10 +000093 if (InITBlock())
94 return Bits32(ITState, 7, 4);
95 else
96 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000097}
98
Greg Clayton64c84432011-01-21 22:02:52 +000099// ARM constants used during decoding
100#define REG_RD 0
101#define LDM_REGLIST 1
102#define PC_REG 15
103#define PC_REGLIST_BIT 0x8000
104
Johnny Chen251af6a2011-01-21 22:47:25 +0000105#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000106#define ARMv4T (1u << 1)
107#define ARMv5T (1u << 2)
108#define ARMv5TE (1u << 3)
109#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000110#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000111#define ARMv6K (1u << 6)
112#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000113#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000114#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMvAll (0xffffffffu)
116
Johnny Chen9b8d7832011-02-02 01:13:56 +0000117#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
118#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
119#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000120
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000121void
122EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000123{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000124}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000125
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000126void
127EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000128{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000129}
130
Johnny Chen08c25e82011-01-31 18:02:28 +0000131// Push Multiple Registers stores multiple registers to the stack, storing to
132// consecutive memory locations ending just below the address in SP, and updates
133// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000134bool
135EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000136{
137#if 0
138 // ARM pseudo code...
139 if (ConditionPassed())
140 {
141 EncodingSpecificOperations();
142 NullCheckIfThumbEE(13);
143 address = SP - 4*BitCount(registers);
144
145 for (i = 0 to 14)
146 {
147 if (registers<i> == ’1’)
148 {
149 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
150 MemA[address,4] = bits(32) UNKNOWN;
151 else
152 MemA[address,4] = R[i];
153 address = address + 4;
154 }
155 }
156
157 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
158 MemA[address,4] = PCStoreValue();
159
160 SP = SP - 4*BitCount(registers);
161 }
162#endif
163
164 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000165 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000166 if (!success)
167 return false;
168
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000169 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000170 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000171 const uint32_t addr_byte_size = GetAddressByteSize();
172 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000173 if (!success)
174 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000175 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000176 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000177 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000178 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000179 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000180 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000181 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000182 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000183 // if BitCount(registers) < 1 then UNPREDICTABLE;
184 if (BitCount(registers) < 1)
185 return false;
186 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000187 case eEncodingT2:
188 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000189 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000190 // if BitCount(registers) < 2 then UNPREDICTABLE;
191 if (BitCount(registers) < 2)
192 return false;
193 break;
194 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000195 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000196 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000197 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000198 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000199 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000200 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000201 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000202 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000203 // Instead of return false, let's handle the following case as well,
204 // which amounts to pushing one reg onto the full descending stacks.
205 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000206 break;
207 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000208 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000209 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000210 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000211 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000212 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000213 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000214 default:
215 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000216 }
Johnny Chence1ca772011-01-25 01:13:00 +0000217 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 addr_t addr = sp - sp_offset;
219 uint32_t i;
220
221 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
222 for (i=0; i<15; ++i)
223 {
Johnny Chen108d5aa2011-01-26 01:00:55 +0000224 if (BitIsSet (registers, 1u << i))
Greg Clayton64c84432011-01-21 22:02:52 +0000225 {
226 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
227 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 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, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000232 return false;
233 addr += addr_byte_size;
234 }
235 }
236
Johnny Chen108d5aa2011-01-26 01:00:55 +0000237 if (BitIsSet (registers, 1u << 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000238 {
239 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000240 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000241 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 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, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000245 return false;
246 }
247
248 context.type = EmulateInstruction::eContextAdjustStackPointer;
249 context.arg0 = eRegisterKindGeneric;
250 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000251 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000252
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000253 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000254 return false;
255 }
256 return true;
257}
258
Johnny Chenef85e912011-01-31 23:07:40 +0000259// Pop Multiple Registers loads multiple registers from the stack, loading from
260// consecutive memory locations staring at the address in SP, and updates
261// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000262bool
263EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000264{
265#if 0
266 // ARM pseudo code...
267 if (ConditionPassed())
268 {
269 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
270 address = SP;
271 for i = 0 to 14
272 if registers<i> == ‘1’ then
273 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
274 if registers<15> == ‘1’ then
275 if UnalignedAllowed then
276 LoadWritePC(MemU[address,4]);
277 else
278 LoadWritePC(MemA[address,4]);
279 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
280 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
281 }
282#endif
283
284 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000286 if (!success)
287 return false;
288
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000289 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000290 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000291 const uint32_t addr_byte_size = GetAddressByteSize();
292 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000293 if (!success)
294 return false;
295 uint32_t registers = 0;
296 uint32_t Rt; // the destination register
297 switch (encoding) {
298 case eEncodingT1:
299 registers = Bits32(opcode, 7, 0);
300 // The P bit represents PC.
301 if (Bits32(opcode, 8, 8))
302 registers |= (1u << 15);
303 // if BitCount(registers) < 1 then UNPREDICTABLE;
304 if (BitCount(registers) < 1)
305 return false;
306 break;
307 case eEncodingT2:
308 // Ignore bit 13.
309 registers = Bits32(opcode, 15, 0) & ~0x2000;
310 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
311 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
312 return false;
313 break;
314 case eEncodingT3:
315 Rt = Bits32(opcode, 15, 12);
316 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
317 if (Rt == dwarf_sp)
318 return false;
319 registers = (1u << Rt);
320 break;
321 case eEncodingA1:
322 registers = Bits32(opcode, 15, 0);
323 // Instead of return false, let's handle the following case as well,
324 // which amounts to popping one reg from the full descending stacks.
325 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
326
327 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
328 if (Bits32(opcode, 13, 13))
329 return false;
330 break;
331 case eEncodingA2:
332 Rt = Bits32(opcode, 15, 12);
333 // if t == 13 then UNPREDICTABLE;
334 if (Rt == dwarf_sp)
335 return false;
336 registers = (1u << Rt);
337 break;
338 default:
339 return false;
340 }
341 addr_t sp_offset = addr_byte_size * BitCount (registers);
342 addr_t addr = sp;
343 uint32_t i, data;
344
345 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
346 for (i=0; i<15; ++i)
347 {
348 if (BitIsSet (registers, 1u << i))
349 {
350 context.arg1 = dwarf_r0 + i; // 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, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 return false;
357 addr += addr_byte_size;
358 }
359 }
360
361 if (BitIsSet (registers, 1u << 15))
362 {
363 context.arg1 = dwarf_pc; // 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, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
370 addr += addr_byte_size;
371 }
372
373 context.type = EmulateInstruction::eContextAdjustStackPointer;
374 context.arg0 = eRegisterKindGeneric;
375 context.arg1 = LLDB_REGNUM_GENERIC_SP;
376 context.arg2 = sp_offset;
377
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000378 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000379 return false;
380 }
381 return true;
382}
383
Johnny Chen5b442b72011-01-27 19:34:30 +0000384// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000385// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000386bool
387EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000388{
389#if 0
390 // ARM pseudo code...
391 if (ConditionPassed())
392 {
393 EncodingSpecificOperations();
394 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
395 if d == 15 then
396 ALUWritePC(result); // setflags is always FALSE here
397 else
398 R[d] = result;
399 if setflags then
400 APSR.N = result<31>;
401 APSR.Z = IsZeroBit(result);
402 APSR.C = carry;
403 APSR.V = overflow;
404 }
405#endif
406
407 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000408 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000409 if (!success)
410 return false;
411
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000412 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000413 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000415 if (!success)
416 return false;
417 uint32_t Rd; // the destination register
418 uint32_t imm32;
419 switch (encoding) {
420 case eEncodingT1:
421 Rd = 7;
422 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
423 break;
424 case eEncodingA1:
425 Rd = Bits32(opcode, 15, 12);
426 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
427 break;
428 default:
429 return false;
430 }
431 addr_t sp_offset = imm32;
432 addr_t addr = sp + sp_offset; // a pointer to the stack area
433
434 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
435 eRegisterKindGeneric,
436 LLDB_REGNUM_GENERIC_SP,
437 sp_offset };
438
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000440 return false;
441 }
442 return true;
443}
444
Johnny Chen2ccad832011-01-28 19:57:25 +0000445// Set r7 or ip to the current stack pointer.
446// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000447bool
448EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000449{
450#if 0
451 // ARM pseudo code...
452 if (ConditionPassed())
453 {
454 EncodingSpecificOperations();
455 result = R[m];
456 if d == 15 then
457 ALUWritePC(result); // setflags is always FALSE here
458 else
459 R[d] = result;
460 if setflags then
461 APSR.N = result<31>;
462 APSR.Z = IsZeroBit(result);
463 // APSR.C unchanged
464 // APSR.V unchanged
465 }
466#endif
467
468 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000470 //if (!success)
471 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000472
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000474 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000475 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000476 if (!success)
477 return false;
478 uint32_t Rd; // the destination register
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 break;
483 case eEncodingA1:
484 Rd = 12;
485 break;
486 default:
487 return false;
488 }
489 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
490 eRegisterKindGeneric,
491 LLDB_REGNUM_GENERIC_SP,
492 0 };
493
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000495 return false;
496 }
497 return true;
498}
499
Johnny Chen1c13b622011-01-29 00:11:15 +0000500// Move from high register (r8-r15) to low register (r0-r7).
501// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502bool
503EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000504{
505#if 0
506 // ARM pseudo code...
507 if (ConditionPassed())
508 {
509 EncodingSpecificOperations();
510 result = R[m];
511 if d == 15 then
512 ALUWritePC(result); // setflags is always FALSE here
513 else
514 R[d] = result;
515 if setflags then
516 APSR.N = result<31>;
517 APSR.Z = IsZeroBit(result);
518 // APSR.C unchanged
519 // APSR.V unchanged
520 }
521#endif
522
523 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 if (!success)
526 return false;
527
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000528 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000529 {
530 uint32_t Rm; // the source register
531 uint32_t Rd; // the destination register
532 switch (encoding) {
533 case eEncodingT1:
534 Rm = Bits32(opcode, 6, 3);
535 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
536 break;
537 default:
538 return false;
539 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 if (!success)
542 return false;
543
544 // The context specifies that Rm is to be moved into Rd.
545 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
546 eRegisterKindDWARF,
547 dwarf_r0 + Rm,
548 0 };
549
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000551 return false;
552 }
553 return true;
554}
555
Johnny Chen788e0552011-01-27 22:52:23 +0000556// PC relative immediate load into register, possibly followed by ADD (SP plus register).
557// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000558bool
559EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000560{
561#if 0
562 // ARM pseudo code...
563 if (ConditionPassed())
564 {
565 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
566 base = Align(PC,4);
567 address = if add then (base + imm32) else (base - imm32);
568 data = MemU[address,4];
569 if t == 15 then
570 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
571 elsif UnalignedSupport() || address<1:0> = ‘00’ then
572 R[t] = data;
573 else // Can only apply before ARMv7
574 if CurrentInstrSet() == InstrSet_ARM then
575 R[t] = ROR(data, 8*UInt(address<1:0>));
576 else
577 R[t] = bits(32) UNKNOWN;
578 }
579#endif
580
581 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000582 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000583 if (!success)
584 return false;
585
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000586 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000587 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000588 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000589 if (!success)
590 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000591
592 // PC relative immediate load context
593 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
594 eRegisterKindGeneric,
595 LLDB_REGNUM_GENERIC_PC,
596 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000597 uint32_t Rd; // the destination register
598 uint32_t imm32; // immediate offset from the PC
599 addr_t addr; // the PC relative address
600 uint32_t data; // the literal data value from the PC relative load
601 switch (encoding) {
602 case eEncodingT1:
603 Rd = Bits32(opcode, 10, 8);
604 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
605 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000606 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000607 break;
608 default:
609 return false;
610 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000611 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000612 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000613 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000615 return false;
616 }
617 return true;
618}
619
Johnny Chen5b442b72011-01-27 19:34:30 +0000620// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000621// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000622bool
623EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000624{
625#if 0
626 // ARM pseudo code...
627 if (ConditionPassed())
628 {
629 EncodingSpecificOperations();
630 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
631 if d == 15 then // Can only occur for ARM encoding
632 ALUWritePC(result); // setflags is always FALSE here
633 else
634 R[d] = result;
635 if setflags then
636 APSR.N = result<31>;
637 APSR.Z = IsZeroBit(result);
638 APSR.C = carry;
639 APSR.V = overflow;
640 }
641#endif
642
643 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000644 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000645 if (!success)
646 return false;
647
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000648 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000649 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000650 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000651 if (!success)
652 return false;
653 uint32_t imm32; // the immediate operand
654 switch (encoding) {
655 case eEncodingT2:
656 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
657 break;
658 default:
659 return false;
660 }
661 addr_t sp_offset = imm32;
662 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
663
664 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
665 eRegisterKindGeneric,
666 LLDB_REGNUM_GENERIC_SP,
667 sp_offset };
668
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000669 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000670 return false;
671 }
672 return true;
673}
674
675// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000676// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000677bool
678EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000679{
680#if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
686 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
687 if d == 15 then
688 ALUWritePC(result); // setflags is always FALSE here
689 else
690 R[d] = result;
691 if setflags then
692 APSR.N = result<31>;
693 APSR.Z = IsZeroBit(result);
694 APSR.C = carry;
695 APSR.V = overflow;
696 }
697#endif
698
699 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000700 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000701 if (!success)
702 return false;
703
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000704 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000705 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000706 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000707 if (!success)
708 return false;
709 uint32_t Rm; // the second operand
710 switch (encoding) {
711 case eEncodingT2:
712 Rm = Bits32(opcode, 6, 3);
713 break;
714 default:
715 return false;
716 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000717 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000718 if (!success)
719 return false;
720
721 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
722
723 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
724 eRegisterKindGeneric,
725 LLDB_REGNUM_GENERIC_SP,
726 reg_value };
727
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000729 return false;
730 }
731 return true;
732}
733
Johnny Chen9b8d7832011-02-02 01:13:56 +0000734// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
735// at a PC-relative address, and changes instruction set from ARM to Thumb, or
736// from Thumb to ARM.
737// BLX (immediate)
738bool
739EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
740{
741#if 0
742 // ARM pseudo code...
743 if (ConditionPassed())
744 {
745 EncodingSpecificOperations();
746 if CurrentInstrSet() == InstrSet_ARM then
747 LR = PC - 4;
748 else
749 LR = PC<31:1> : '1';
750 if targetInstrSet == InstrSet_ARM then
751 targetAddress = Align(PC,4) + imm32;
752 else
753 targetAddress = PC + imm32;
754 SelectInstrSet(targetInstrSet);
755 BranchWritePC(targetAddress);
756 }
757#endif
758
759 bool success = false;
760 const uint32_t opcode = OpcodeAsUnsigned (&success);
761 if (!success)
762 return false;
763
764 if (ConditionPassed())
765 {
766 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
767 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
768 addr_t lr; // next instruction address
769 addr_t target; // target address
770 if (!success)
771 return false;
772 int32_t imm32; // PC-relative offset
773 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000774 case eEncodingT1:
775 {
776 lr = (pc + 4) | 1u; // return address
777 uint32_t S = Bits32(opcode, 26, 26);
778 uint32_t imm10 = Bits32(opcode, 25, 16);
779 uint32_t J1 = Bits32(opcode, 13, 13);
780 uint32_t J2 = Bits32(opcode, 11, 11);
781 uint32_t imm11 = Bits32(opcode, 10, 0);
782 uint32_t I1 = !(J1 ^ S);
783 uint32_t I2 = !(J2 ^ S);
784 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
785 imm32 = llvm::SignExtend32<25>(imm25);
786 target = pc + 4 + imm32;
787 context.arg1 = 4 + imm32; // signed offset
788 context.arg2 = eModeThumb; // target instruction set
789 break;
790 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000791 case eEncodingT2:
792 {
793 lr = (pc + 4) | 1u; // return address
794 uint32_t S = Bits32(opcode, 26, 26);
795 uint32_t imm10H = Bits32(opcode, 25, 16);
796 uint32_t J1 = Bits32(opcode, 13, 13);
797 uint32_t J2 = Bits32(opcode, 11, 11);
798 uint32_t imm10L = Bits32(opcode, 10, 1);
799 uint32_t I1 = !(J1 ^ S);
800 uint32_t I2 = !(J2 ^ S);
801 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
802 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000803 target = Align(pc + 4, 4) + imm32;
804 context.arg1 = 4 + imm32; // signed offset
805 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000806 break;
807 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000808 case eEncodingA1:
809 lr = pc + 4; // return address
810 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000811 target = Align(pc + 8, 4) + imm32;
812 context.arg1 = 8 + imm32; // signed offset
813 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000814 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000815 case eEncodingA2:
816 lr = pc + 4; // return address
817 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
818 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000819 context.arg1 = 8 + imm32; // signed offset
820 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000821 break;
822 default:
823 return false;
824 }
825 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
826 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000827 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000828 return false;
829 }
830 return true;
831}
832
833// Branch with Link and Exchange (register) calls a subroutine at an address and
834// instruction set specified by a register.
835// BLX (register)
836bool
837EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
838{
839#if 0
840 // ARM pseudo code...
841 if (ConditionPassed())
842 {
843 EncodingSpecificOperations();
844 target = R[m];
845 if CurrentInstrSet() == InstrSet_ARM then
846 next_instr_addr = PC - 4;
847 LR = next_instr_addr;
848 else
849 next_instr_addr = PC - 2;
850 LR = next_instr_addr<31:1> : ‘1’;
851 BXWritePC(target);
852 }
853#endif
854
855 bool success = false;
856 const uint32_t opcode = OpcodeAsUnsigned (&success);
857 if (!success)
858 return false;
859
860 if (ConditionPassed())
861 {
862 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
863 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
864 addr_t lr; // next instruction address
865 addr_t target; // target address
866 if (!success)
867 return false;
868 uint32_t Rm; // the register with the target address
869 switch (encoding) {
870 case eEncodingT1:
871 lr = (pc + 2) | 1u; // return address
872 Rm = Bits32(opcode, 6, 3);
873 // if m == 15 then UNPREDICTABLE;
874 if (Rm == 15)
875 return false;
876 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
877 break;
878 case eEncodingA1:
879 lr = pc + 4; // return address
880 Rm = Bits32(opcode, 3, 0);
881 // if m == 15 then UNPREDICTABLE;
882 if (Rm == 15)
883 return false;
884 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000885 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000886 default:
887 return false;
888 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000889 context.arg0 = eRegisterKindDWARF;
890 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000891 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
892 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000893 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000894 return false;
895 }
896 return true;
897}
898
Johnny Chen0d0148e2011-01-28 02:26:08 +0000899// Set r7 to point to some ip offset.
900// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000901bool
902EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000903{
904#if 0
905 // ARM pseudo code...
906 if (ConditionPassed())
907 {
908 EncodingSpecificOperations();
909 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
910 if d == 15 then // Can only occur for ARM encoding
911 ALUWritePC(result); // setflags is always FALSE here
912 else
913 R[d] = result;
914 if setflags then
915 APSR.N = result<31>;
916 APSR.Z = IsZeroBit(result);
917 APSR.C = carry;
918 APSR.V = overflow;
919 }
920#endif
921
922 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000923 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000924 if (!success)
925 return false;
926
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000928 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000929 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000930 if (!success)
931 return false;
932 uint32_t imm32;
933 switch (encoding) {
934 case eEncodingA1:
935 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
936 break;
937 default:
938 return false;
939 }
940 addr_t ip_offset = imm32;
941 addr_t addr = ip - ip_offset; // the adjusted ip value
942
943 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
944 eRegisterKindDWARF,
945 dwarf_r12,
946 -ip_offset };
947
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000948 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000949 return false;
950 }
951 return true;
952}
953
954// Set ip to point to some stack offset.
955// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956bool
957EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000958{
959#if 0
960 // ARM pseudo code...
961 if (ConditionPassed())
962 {
963 EncodingSpecificOperations();
964 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
965 if d == 15 then // Can only occur for ARM encoding
966 ALUWritePC(result); // setflags is always FALSE here
967 else
968 R[d] = result;
969 if setflags then
970 APSR.N = result<31>;
971 APSR.Z = IsZeroBit(result);
972 APSR.C = carry;
973 APSR.V = overflow;
974 }
975#endif
976
977 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000978 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000979 if (!success)
980 return false;
981
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000982 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000983 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000984 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000985 if (!success)
986 return false;
987 uint32_t imm32;
988 switch (encoding) {
989 case eEncodingA1:
990 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
991 break;
992 default:
993 return false;
994 }
995 addr_t sp_offset = imm32;
996 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
997
998 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
999 eRegisterKindGeneric,
1000 LLDB_REGNUM_GENERIC_SP,
1001 -sp_offset };
1002
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001004 return false;
1005 }
1006 return true;
1007}
1008
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001009// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001010bool
1011EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001012{
1013#if 0
1014 // ARM pseudo code...
1015 if (ConditionPassed())
1016 {
1017 EncodingSpecificOperations();
1018 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1019 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001020 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001021 else
1022 R[d] = result;
1023 if setflags then
1024 APSR.N = result<31>;
1025 APSR.Z = IsZeroBit(result);
1026 APSR.C = carry;
1027 APSR.V = overflow;
1028 }
1029#endif
1030
1031 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001032 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001033 if (!success)
1034 return false;
1035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001037 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001039 if (!success)
1040 return false;
1041 uint32_t imm32;
1042 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001043 case eEncodingT1:
1044 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001045 case eEncodingT2:
1046 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1047 break;
1048 case eEncodingT3:
1049 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1050 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001051 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001052 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001053 break;
1054 default:
1055 return false;
1056 }
1057 addr_t sp_offset = imm32;
1058 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1059
1060 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1061 eRegisterKindGeneric,
1062 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001063 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001064
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001065 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001066 return false;
1067 }
1068 return true;
1069}
1070
Johnny Chen08c25e82011-01-31 18:02:28 +00001071// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001072bool
1073EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001074{
1075#if 0
1076 // ARM pseudo code...
1077 if (ConditionPassed())
1078 {
1079 EncodingSpecificOperations();
1080 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1081 address = if index then offset_addr else R[n];
1082 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1083 if wback then R[n] = offset_addr;
1084 }
1085#endif
1086
1087 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001088 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001089 if (!success)
1090 return false;
1091
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001092 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001093 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001094 const uint32_t addr_byte_size = GetAddressByteSize();
1095 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001096 if (!success)
1097 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001098 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001099 uint32_t imm12;
1100 switch (encoding) {
1101 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001102 Rt = Bits32(opcode, 15, 12);
1103 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001104 break;
1105 default:
1106 return false;
1107 }
1108 addr_t sp_offset = imm12;
1109 addr_t addr = sp - sp_offset;
1110
1111 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001112 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001113 {
Johnny Chen91d99862011-01-25 19:07:04 +00001114 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1115 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001116 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001117 if (!success)
1118 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001119 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001120 return false;
1121 }
1122 else
1123 {
1124 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1125 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001126 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001127 if (!success)
1128 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001129 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001130 return false;
1131 }
1132
1133 context.type = EmulateInstruction::eContextAdjustStackPointer;
1134 context.arg0 = eRegisterKindGeneric;
1135 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001136 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001137
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001139 return false;
1140 }
1141 return true;
1142}
1143
Johnny Chen08c25e82011-01-31 18:02:28 +00001144// Vector Push stores multiple extension registers to the stack.
1145// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001146bool
1147EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001148{
1149#if 0
1150 // ARM pseudo code...
1151 if (ConditionPassed())
1152 {
1153 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1154 address = SP - imm32;
1155 SP = SP - imm32;
1156 if single_regs then
1157 for r = 0 to regs-1
1158 MemA[address,4] = S[d+r]; address = address+4;
1159 else
1160 for r = 0 to regs-1
1161 // Store as two word-aligned words in the correct order for current endianness.
1162 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1163 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1164 address = address+8;
1165 }
1166#endif
1167
1168 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001169 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001170 if (!success)
1171 return false;
1172
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001173 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001174 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001175 const uint32_t addr_byte_size = GetAddressByteSize();
1176 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001177 if (!success)
1178 return false;
1179 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001180 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001181 uint32_t imm32; // stack offset
1182 uint32_t regs; // number of registers
1183 switch (encoding) {
1184 case eEncodingT1:
1185 case eEncodingA1:
1186 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001187 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001188 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1189 // If UInt(imm8) is odd, see "FSTMX".
1190 regs = Bits32(opcode, 7, 0) / 2;
1191 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1192 if (regs == 0 || regs > 16 || (d + regs) > 32)
1193 return false;
1194 break;
1195 case eEncodingT2:
1196 case eEncodingA2:
1197 single_regs = true;
1198 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1199 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1200 regs = Bits32(opcode, 7, 0);
1201 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1202 if (regs == 0 || regs > 16 || (d + regs) > 32)
1203 return false;
1204 break;
1205 default:
1206 return false;
1207 }
1208 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1209 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1210 addr_t sp_offset = imm32;
1211 addr_t addr = sp - sp_offset;
1212 uint32_t i;
1213
1214 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1215 for (i=d; i<regs; ++i)
1216 {
1217 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1218 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1219 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001221 if (!success)
1222 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001223 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001224 return false;
1225 addr += reg_byte_size;
1226 }
1227
1228 context.type = EmulateInstruction::eContextAdjustStackPointer;
1229 context.arg0 = eRegisterKindGeneric;
1230 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001231 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001232
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001233 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001234 return false;
1235 }
1236 return true;
1237}
1238
Johnny Chen587a0a42011-02-01 18:35:28 +00001239// Vector Pop loads multiple extension registers from the stack.
1240// It also updates SP to point just above the loaded data.
1241bool
1242EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1243{
1244#if 0
1245 // ARM pseudo code...
1246 if (ConditionPassed())
1247 {
1248 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1249 address = SP;
1250 SP = SP + imm32;
1251 if single_regs then
1252 for r = 0 to regs-1
1253 S[d+r] = MemA[address,4]; address = address+4;
1254 else
1255 for r = 0 to regs-1
1256 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1257 // Combine the word-aligned words in the correct order for current endianness.
1258 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1259 }
1260#endif
1261
1262 bool success = false;
1263 const uint32_t opcode = OpcodeAsUnsigned (&success);
1264 if (!success)
1265 return false;
1266
1267 if (ConditionPassed())
1268 {
1269 const uint32_t addr_byte_size = GetAddressByteSize();
1270 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1271 if (!success)
1272 return false;
1273 bool single_regs;
1274 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1275 uint32_t imm32; // stack offset
1276 uint32_t regs; // number of registers
1277 switch (encoding) {
1278 case eEncodingT1:
1279 case eEncodingA1:
1280 single_regs = false;
1281 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1282 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1283 // If UInt(imm8) is odd, see "FLDMX".
1284 regs = Bits32(opcode, 7, 0) / 2;
1285 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1286 if (regs == 0 || regs > 16 || (d + regs) > 32)
1287 return false;
1288 break;
1289 case eEncodingT2:
1290 case eEncodingA2:
1291 single_regs = true;
1292 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1293 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1294 regs = Bits32(opcode, 7, 0);
1295 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1296 if (regs == 0 || regs > 16 || (d + regs) > 32)
1297 return false;
1298 break;
1299 default:
1300 return false;
1301 }
1302 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1303 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1304 addr_t sp_offset = imm32;
1305 addr_t addr = sp;
1306 uint32_t i;
1307 uint64_t data; // uint64_t to accomodate 64-bit registers.
1308
1309 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1310 for (i=d; i<regs; ++i)
1311 {
1312 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1313 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1314 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1315 if (!success)
1316 return false;
1317 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1318 return false;
1319 addr += reg_byte_size;
1320 }
1321
1322 context.type = EmulateInstruction::eContextAdjustStackPointer;
1323 context.arg0 = eRegisterKindGeneric;
1324 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1325 context.arg2 = sp_offset;
1326
1327 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1328 return false;
1329 }
1330 return true;
1331}
1332
Johnny Chenb77be412011-02-04 00:40:18 +00001333// SVC (previously SWI)
1334bool
1335EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1336{
1337#if 0
1338 // ARM pseudo code...
1339 if (ConditionPassed())
1340 {
1341 EncodingSpecificOperations();
1342 CallSupervisor();
1343 }
1344#endif
1345
1346 bool success = false;
1347 const uint32_t opcode = OpcodeAsUnsigned (&success);
1348 if (!success)
1349 return false;
1350
1351 if (ConditionPassed())
1352 {
1353 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1354 addr_t lr; // next instruction address
1355 if (!success)
1356 return false;
1357 uint32_t imm32; // the immediate constant
1358 uint32_t mode; // ARM or Thumb mode
1359 switch (encoding) {
1360 case eEncodingT1:
1361 lr = (pc + 2) | 1u; // return address
1362 imm32 = Bits32(opcode, 7, 0);
1363 mode = eModeThumb;
1364 break;
1365 case eEncodingA1:
1366 lr = pc + 4; // return address
1367 imm32 = Bits32(opcode, 23, 0);
1368 mode = eModeARM;
1369 break;
1370 default:
1371 return false;
1372 }
1373 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1374 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1375 return false;
1376 }
1377 return true;
1378}
1379
Johnny Chenc315f862011-02-05 00:46:10 +00001380// If Then makes up to four following instructions (the IT block) conditional.
1381bool
1382EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1383{
1384#if 0
1385 // ARM pseudo code...
1386 EncodingSpecificOperations();
1387 ITSTATE.IT<7:0> = firstcond:mask;
1388#endif
1389
1390 bool success = false;
1391 const uint32_t opcode = OpcodeAsUnsigned (&success);
1392 if (!success)
1393 return false;
1394
1395 m_it_session.InitIT(Bits32(opcode, 7, 0));
1396 return true;
1397}
1398
Johnny Chen3b620b32011-02-07 20:11:47 +00001399// Branch causes a branch to a target address.
1400bool
1401EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1402{
1403#if 0
1404 // ARM pseudo code...
1405 if (ConditionPassed())
1406 {
1407 EncodingSpecificOperations();
1408 BranchWritePC(PC + imm32);
1409 }
1410#endif
1411
1412 bool success = false;
1413 const uint32_t opcode = OpcodeAsUnsigned (&success);
1414 if (!success)
1415 return false;
1416
Johnny Chen9ee056b2011-02-08 00:06:35 +00001417 if (ConditionPassed())
1418 {
1419 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1420 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1421 addr_t target; // target address
1422 if (!success)
1423 return false;
1424 int32_t imm32; // PC-relative offset
1425 switch (encoding) {
1426 case eEncodingT1:
1427 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1428 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1429 target = pc + 4 + imm32;
1430 context.arg1 = 4 + imm32; // signed offset
1431 context.arg2 = eModeThumb; // target instruction set
1432 break;
1433 case eEncodingT2:
1434 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1435 target = pc + 4 + imm32;
1436 context.arg1 = 4 + imm32; // signed offset
1437 context.arg2 = eModeThumb; // target instruction set
1438 break;
1439 case eEncodingT3:
1440 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1441 {
1442 uint32_t S = Bits32(opcode, 26, 26);
1443 uint32_t imm6 = Bits32(opcode, 21, 16);
1444 uint32_t J1 = Bits32(opcode, 13, 13);
1445 uint32_t J2 = Bits32(opcode, 11, 11);
1446 uint32_t imm11 = Bits32(opcode, 10, 0);
1447 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) + (imm11 << 1);
1448 imm32 = llvm::SignExtend32<21>(imm21);
1449 target = pc + 4 + imm32;
1450 context.arg1 = eModeThumb; // target instruction set
1451 context.arg2 = 4 + imm32; // signed offset
1452 break;
1453 }
1454 case eEncodingT4:
1455 {
1456 uint32_t S = Bits32(opcode, 26, 26);
1457 uint32_t imm10 = Bits32(opcode, 25, 16);
1458 uint32_t J1 = Bits32(opcode, 13, 13);
1459 uint32_t J2 = Bits32(opcode, 11, 11);
1460 uint32_t imm11 = Bits32(opcode, 10, 0);
1461 uint32_t I1 = !(J1 ^ S);
1462 uint32_t I2 = !(J2 ^ S);
1463 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
1464 imm32 = llvm::SignExtend32<25>(imm25);
1465 target = pc + 4 + imm32;
1466 context.arg1 = eModeThumb; // target instruction set
1467 context.arg2 = 4 + imm32; // signed offset
1468 break;
1469 }
1470 case eEncodingA1:
1471 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1472 target = pc + 8 + imm32;
1473 context.arg1 = eModeARM; // target instruction set
1474 context.arg2 = 8 + imm32; // signed offset
1475 break;
1476 default:
1477 return false;
1478 }
1479 if (!BranchWritePC(context, target))
1480 return false;
1481 }
1482 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001483}
1484
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001485// LDM loads multiple registers from consecutive memory locations, using an
1486// address from a base register. Optionally the addres just above the highest of those locations
1487// can be written back to the base register.
1488bool
1489EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1490{
1491#if 0
1492 // ARM pseudo code...
1493 if ConditionPassed()
1494 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1495 address = R[n];
1496
1497 for i = 0 to 14
1498 if registers<i> == '1' then
1499 R[i] = MemA[address, 4]; address = address + 4;
1500 if registers<15> == '1' then
1501 LoadWritePC (MemA[address, 4]);
1502
1503 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1504 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1505
1506#endif
1507
1508 bool success = false;
1509 const uint32_t opcode = OpcodeAsUnsigned (&success);
1510 if (!success)
1511 return false;
1512
1513 if (ConditionPassed())
1514 {
1515 uint32_t n;
1516 uint32_t registers = 0;
1517 bool wback;
1518 const uint32_t addr_byte_size = GetAddressByteSize();
1519 switch (encoding)
1520 {
1521 case eEncodingT1:
1522 n = Bits32 (opcode, 10, 8);
1523 registers = Bits32 (opcode, 7, 0);
1524 wback = BitIsClear (registers, n);
1525 // if BitCount(registers) < 1 then UNPREDICTABLE;
1526 if (BitCount(registers) < 1)
1527 return false;
1528 break;
1529 case eEncodingT2:
1530 n = Bits32 (opcode, 19, 16);
1531 registers = Bits32 (opcode, 15, 0);
1532 wback = BitIsSet (opcode, 21);
1533 if ((n == 15)
1534 || (BitCount (registers) < 2)
1535 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1536 return false;
1537 if (BitIsSet (registers, 15)
1538 && m_it_session.InITBlock()
1539 && !m_it_session.LastInITBlock())
1540 return false;
1541 if (wback
1542 && BitIsSet (registers, n))
1543 return false;
1544 break;
1545 case eEncodingA1:
1546 n = Bits32 (opcode, 19, 16);
1547 registers = Bits32 (opcode, 15, 0);
1548 wback = BitIsSet (opcode, 21);
1549 if ((n == 15)
1550 || (BitCount (registers) < 1))
1551 return false;
1552 break;
1553 default:
1554 return false;
1555 }
1556
1557 int32_t offset = 0;
1558 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1559 if (!success)
1560 return false;
1561
1562 for (int i = 0; i < 14; ++i)
1563 {
1564 if (BitIsSet (registers, i))
1565 {
1566 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1567 eRegisterKindDWARF,
1568 dwarf_r0 + n,
1569 offset };
1570
1571 if (wback && (n == 13)) // Pop Instruction
1572 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1573
1574 // R[i] = MemA [address, 4]; address = address + 4;
1575 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1576 if (!success)
1577 return false;
1578
1579 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1580 return false;
1581
1582 offset += addr_byte_size;
1583 }
1584 }
1585
1586 if (BitIsSet (registers, 15))
1587 {
1588 //LoadWritePC (MemA [address, 4]);
1589 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1590 eRegisterKindDWARF,
1591 dwarf_r0 + n,
1592 offset };
1593
1594 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1595 if (!success)
1596 return false;
1597 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1598 return false;
1599 }
1600
1601 if (wback && BitIsClear (registers, n))
1602 {
1603 addr_t offset = addr_byte_size * BitCount (registers);
1604 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1605 eRegisterKindDWARF,
1606 dwarf_r0 + n,
1607 offset };
1608
1609 // R[n] = R[n] + 4 * BitCount (registers)
1610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1611 return false;
1612 }
1613 if (wback && BitIsSet (registers, n))
1614 // R[n] bits(32) UNKNOWN;
1615 return false; //I'm not convinced this is the right thing to do here...
1616 }
1617 return true;
1618}
1619
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001620EmulateInstructionARM::ARMOpcode*
1621EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001622{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001623 static ARMOpcode
1624 g_arm_opcodes[] =
1625 {
1626 //----------------------------------------------------------------------
1627 // Prologue instructions
1628 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001629
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001630 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001631 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1632 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001633
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001634 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001635 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1636 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001637 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001638 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1639 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1640 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001641
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001642 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001643 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001644
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001645 // push one register
1646 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001647 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001648
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001649 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001650 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1651 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001652
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001653 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001654 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001655 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001656
Johnny Chen9b8d7832011-02-02 01:13:56 +00001657 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1658 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1659 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1660 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001661 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1662 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001663 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001664 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1665
1666 //----------------------------------------------------------------------
1667 // Supervisor Call (previously Software Interrupt)
1668 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001669 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1670
1671 //----------------------------------------------------------------------
1672 // Branch instructions
1673 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001674 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00001675
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001676 //----------------------------------------------------------------------
1677 // Load instructions
1678 //----------------------------------------------------------------------
1679 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }
1680
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001681 };
1682 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1683
1684 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1685 {
1686 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1687 return &g_arm_opcodes[i];
1688 }
1689 return NULL;
1690}
Greg Clayton64c84432011-01-21 22:02:52 +00001691
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001692
1693EmulateInstructionARM::ARMOpcode*
1694EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001695{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001696
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001697 static ARMOpcode
1698 g_thumb_opcodes[] =
1699 {
1700 //----------------------------------------------------------------------
1701 // Prologue instructions
1702 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001703
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001704 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001705 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001706 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1707 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001708 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001709 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001710
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001711 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001712 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1713 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001714
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001715 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001716 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001717
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001718 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001719 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1720 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001721 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1722 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001723
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001724 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00001725 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1726 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001727
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001728 //----------------------------------------------------------------------
1729 // Epilogue instructions
1730 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001731
Johnny Chenc28a76d2011-02-01 18:51:48 +00001732 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001733 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1734 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00001735 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1736 // J1 == J2 == 1
1737 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001738 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001739 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1740 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1741 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
1742 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001743
1744 //----------------------------------------------------------------------
1745 // Supervisor Call (previously Software Interrupt)
1746 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00001747 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
1748
1749 //----------------------------------------------------------------------
1750 // If Then makes up to four following instructions conditional.
1751 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001752 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
1753
1754 //----------------------------------------------------------------------
1755 // Branch instructions
1756 //----------------------------------------------------------------------
1757 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
1758 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
1759 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00001760 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001761 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chenb77be412011-02-04 00:40:18 +00001762
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001763
1764 //----------------------------------------------------------------------
1765 // Load instructions
1766 //----------------------------------------------------------------------
1767 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
1768 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }
1769
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001770 };
1771
1772 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1773 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1774 {
1775 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1776 return &g_thumb_opcodes[i];
1777 }
1778 return NULL;
1779}
Greg Clayton64c84432011-01-21 22:02:52 +00001780
Greg Clayton31e2a382011-01-30 20:03:56 +00001781bool
1782EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1783{
1784 m_arm_isa = 0;
1785 const char *triple_cstr = triple.GetCString();
1786 if (triple_cstr)
1787 {
1788 const char *dash = ::strchr (triple_cstr, '-');
1789 if (dash)
1790 {
1791 std::string arch (triple_cstr, dash);
1792 const char *arch_cstr = arch.c_str();
1793 if (strcasecmp(arch_cstr, "armv4t") == 0)
1794 m_arm_isa = ARMv4T;
1795 else if (strcasecmp(arch_cstr, "armv4") == 0)
1796 m_arm_isa = ARMv4;
1797 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1798 m_arm_isa = ARMv5TEJ;
1799 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1800 m_arm_isa = ARMv5TE;
1801 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1802 m_arm_isa = ARMv5T;
1803 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1804 m_arm_isa = ARMv6K;
1805 else if (strcasecmp(arch_cstr, "armv6") == 0)
1806 m_arm_isa = ARMv6;
1807 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1808 m_arm_isa = ARMv6T2;
1809 else if (strcasecmp(arch_cstr, "armv7") == 0)
1810 m_arm_isa = ARMv7;
1811 else if (strcasecmp(arch_cstr, "armv8") == 0)
1812 m_arm_isa = ARMv8;
1813 }
1814 }
1815 return m_arm_isa != 0;
1816}
1817
1818
Greg Clayton64c84432011-01-21 22:02:52 +00001819bool
1820EmulateInstructionARM::ReadInstruction ()
1821{
1822 bool success = false;
1823 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1824 if (success)
1825 {
1826 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1827 if (success)
1828 {
1829 Context read_inst_context = {eContextReadOpcode, 0, 0};
1830 if (m_inst_cpsr & MASK_CPSR_T)
1831 {
1832 m_inst_mode = eModeThumb;
1833 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
1834
1835 if (success)
1836 {
1837 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
1838 {
1839 m_inst.opcode_type = eOpcode16;
1840 m_inst.opcode.inst16 = thumb_opcode;
1841 }
1842 else
1843 {
1844 m_inst.opcode_type = eOpcode32;
1845 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
1846 }
1847 }
1848 }
1849 else
1850 {
1851 m_inst_mode = eModeARM;
1852 m_inst.opcode_type = eOpcode32;
1853 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
1854 }
1855 }
1856 }
1857 if (!success)
1858 {
1859 m_inst_mode = eModeInvalid;
1860 m_inst_pc = LLDB_INVALID_ADDRESS;
1861 }
1862 return success;
1863}
1864
Greg Clayton64c84432011-01-21 22:02:52 +00001865bool
1866EmulateInstructionARM::ConditionPassed ()
1867{
1868 if (m_inst_cpsr == 0)
1869 return false;
1870
1871 const uint32_t cond = CurrentCond ();
1872
1873 if (cond == UINT32_MAX)
1874 return false;
1875
1876 bool result = false;
1877 switch (UnsignedBits(cond, 3, 1))
1878 {
1879 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
1880 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
1881 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
1882 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
1883 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
1884 case 5:
1885 {
1886 bool n = (m_inst_cpsr & MASK_CPSR_N);
1887 bool v = (m_inst_cpsr & MASK_CPSR_V);
1888 result = n == v;
1889 }
1890 break;
1891 case 6:
1892 {
1893 bool n = (m_inst_cpsr & MASK_CPSR_N);
1894 bool v = (m_inst_cpsr & MASK_CPSR_V);
1895 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
1896 }
1897 break;
1898 case 7:
1899 result = true;
1900 break;
1901 }
1902
1903 if (cond & 1)
1904 result = !result;
1905 return result;
1906}
1907
Johnny Chen9ee056b2011-02-08 00:06:35 +00001908uint32_t
1909EmulateInstructionARM::CurrentCond ()
1910{
1911 switch (m_inst_mode)
1912 {
1913 default:
1914 case eModeInvalid:
1915 break;
1916
1917 case eModeARM:
1918 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
1919
1920 case eModeThumb:
1921 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
1922 // 'cond' field of the encoding.
1923 if (m_inst.opcode_type == eOpcode16 &&
1924 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
1925 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
1926 {
1927 return Bits32(m_inst.opcode.inst16, 11, 7);
1928 }
1929 else if (m_inst.opcode_type == eOpcode32 &&
1930 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
1931 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
1932 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
1933 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
1934 {
1935 return Bits32(m_inst.opcode.inst32, 25, 22);
1936 }
1937
1938 return m_it_session.GetCond();
1939 }
1940 return UINT32_MAX; // Return invalid value
1941}
1942
1943// API client must pass in a context whose arg2 field contains the target instruction set.
1944bool
1945EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
1946{
1947 addr_t target;
1948
1949 // Chech the target instruction set.
1950 switch (context.arg2)
1951 {
1952 default:
1953 assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
1954 return false;
1955 case eModeARM:
1956 target = addr & 0xfffffffc;
1957 break;
1958 case eModeThumb:
1959 target = addr & 0xfffffffe;
1960 break;
1961 }
1962 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1963 return false;
1964 return false;
1965}
1966
1967// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
1968bool
1969EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
1970{
1971 addr_t target;
1972
1973 if (BitIsSet(addr, 0))
1974 {
1975 target = addr & 0xfffffffe;
1976 context.arg2 = eModeThumb;
1977 }
1978 else if (BitIsClear(addr, 1))
1979 {
1980 target = addr & 0xfffffffc;
1981 context.arg2 = eModeARM;
1982 }
1983 else
1984 return false; // address<1:0> == '10' => UNPREDICTABLE
1985
1986 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1987 return false;
1988 return false;
1989}
Greg Clayton64c84432011-01-21 22:02:52 +00001990
1991bool
1992EmulateInstructionARM::EvaluateInstruction ()
1993{
Johnny Chenc315f862011-02-05 00:46:10 +00001994 // Advance the ITSTATE bits to their values for the next instruction.
1995 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
1996 m_it_session.ITAdvance();
1997
Greg Clayton64c84432011-01-21 22:02:52 +00001998 return false;
1999}