blob: 57abbc5951e710c0b23ae6a20a48042ff8aa4665 [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
Johnny Chenc315f862011-02-05 00:46:10 +000079// Return true if we're the last instruction inside an IT Block.
80bool ITSession::LastInITBlock()
81{
82 return ITCounter == 1;
83}
84
Johnny Chen93070472011-02-04 23:02:47 +000085// Get condition bits for the current thumb instruction.
86uint32_t ITSession::GetCond()
87{
Johnny Chenc315f862011-02-05 00:46:10 +000088 if (InITBlock())
89 return Bits32(ITState, 7, 4);
90 else
91 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000092}
93
Greg Clayton64c84432011-01-21 22:02:52 +000094// ARM constants used during decoding
95#define REG_RD 0
96#define LDM_REGLIST 1
97#define PC_REG 15
98#define PC_REGLIST_BIT 0x8000
99
Johnny Chen251af6a2011-01-21 22:47:25 +0000100#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000101#define ARMv4T (1u << 1)
102#define ARMv5T (1u << 2)
103#define ARMv5TE (1u << 3)
104#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000105#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000106#define ARMv6K (1u << 6)
107#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000108#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000109#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000110#define ARMvAll (0xffffffffu)
111
Johnny Chen9b8d7832011-02-02 01:13:56 +0000112#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
113#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
114#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000115
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000116void
117EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000118{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000119}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000120
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000121void
122EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000123{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000124}
125
Greg Clayton64c84432011-01-21 22:02:52 +0000126
Johnny Chen08c25e82011-01-31 18:02:28 +0000127// Push Multiple Registers stores multiple registers to the stack, storing to
128// consecutive memory locations ending just below the address in SP, and updates
129// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000130bool
131EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000132{
133#if 0
134 // ARM pseudo code...
135 if (ConditionPassed())
136 {
137 EncodingSpecificOperations();
138 NullCheckIfThumbEE(13);
139 address = SP - 4*BitCount(registers);
140
141 for (i = 0 to 14)
142 {
143 if (registers<i> == ’1’)
144 {
145 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
146 MemA[address,4] = bits(32) UNKNOWN;
147 else
148 MemA[address,4] = R[i];
149 address = address + 4;
150 }
151 }
152
153 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
154 MemA[address,4] = PCStoreValue();
155
156 SP = SP - 4*BitCount(registers);
157 }
158#endif
159
160 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000161 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000162 if (!success)
163 return false;
164
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000165 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000166 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000167 const uint32_t addr_byte_size = GetAddressByteSize();
168 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000169 if (!success)
170 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000171 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000172 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000173 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000174 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000175 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000176 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000177 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000178 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000179 // if BitCount(registers) < 1 then UNPREDICTABLE;
180 if (BitCount(registers) < 1)
181 return false;
182 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000183 case eEncodingT2:
184 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000185 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000186 // if BitCount(registers) < 2 then UNPREDICTABLE;
187 if (BitCount(registers) < 2)
188 return false;
189 break;
190 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000191 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000192 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000193 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000194 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000195 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000196 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000197 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000198 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000199 // Instead of return false, let's handle the following case as well,
200 // which amounts to pushing one reg onto the full descending stacks.
201 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000202 break;
203 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000204 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000205 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000206 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000207 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000208 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000209 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000210 default:
211 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000212 }
Johnny Chence1ca772011-01-25 01:13:00 +0000213 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000214 addr_t addr = sp - sp_offset;
215 uint32_t i;
216
217 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
218 for (i=0; i<15; ++i)
219 {
Johnny Chen108d5aa2011-01-26 01:00:55 +0000220 if (BitIsSet (registers, 1u << i))
Greg Clayton64c84432011-01-21 22:02:52 +0000221 {
222 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
223 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000224 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000225 if (!success)
226 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000228 return false;
229 addr += addr_byte_size;
230 }
231 }
232
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 if (BitIsSet (registers, 1u << 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000234 {
235 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000236 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000237 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000238 if (!success)
239 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000240 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000241 return false;
242 }
243
244 context.type = EmulateInstruction::eContextAdjustStackPointer;
245 context.arg0 = eRegisterKindGeneric;
246 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000247 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000248
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000249 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000250 return false;
251 }
252 return true;
253}
254
Johnny Chenef85e912011-01-31 23:07:40 +0000255// Pop Multiple Registers loads multiple registers from the stack, loading from
256// consecutive memory locations staring at the address in SP, and updates
257// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000258bool
259EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000260{
261#if 0
262 // ARM pseudo code...
263 if (ConditionPassed())
264 {
265 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
266 address = SP;
267 for i = 0 to 14
268 if registers<i> == ‘1’ then
269 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
270 if registers<15> == ‘1’ then
271 if UnalignedAllowed then
272 LoadWritePC(MemU[address,4]);
273 else
274 LoadWritePC(MemA[address,4]);
275 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
276 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
277 }
278#endif
279
280 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000281 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000282 if (!success)
283 return false;
284
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000286 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000287 const uint32_t addr_byte_size = GetAddressByteSize();
288 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000289 if (!success)
290 return false;
291 uint32_t registers = 0;
292 uint32_t Rt; // the destination register
293 switch (encoding) {
294 case eEncodingT1:
295 registers = Bits32(opcode, 7, 0);
296 // The P bit represents PC.
297 if (Bits32(opcode, 8, 8))
298 registers |= (1u << 15);
299 // if BitCount(registers) < 1 then UNPREDICTABLE;
300 if (BitCount(registers) < 1)
301 return false;
302 break;
303 case eEncodingT2:
304 // Ignore bit 13.
305 registers = Bits32(opcode, 15, 0) & ~0x2000;
306 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
307 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
308 return false;
309 break;
310 case eEncodingT3:
311 Rt = Bits32(opcode, 15, 12);
312 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
313 if (Rt == dwarf_sp)
314 return false;
315 registers = (1u << Rt);
316 break;
317 case eEncodingA1:
318 registers = Bits32(opcode, 15, 0);
319 // Instead of return false, let's handle the following case as well,
320 // which amounts to popping one reg from the full descending stacks.
321 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
322
323 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
324 if (Bits32(opcode, 13, 13))
325 return false;
326 break;
327 case eEncodingA2:
328 Rt = Bits32(opcode, 15, 12);
329 // if t == 13 then UNPREDICTABLE;
330 if (Rt == dwarf_sp)
331 return false;
332 registers = (1u << Rt);
333 break;
334 default:
335 return false;
336 }
337 addr_t sp_offset = addr_byte_size * BitCount (registers);
338 addr_t addr = sp;
339 uint32_t i, data;
340
341 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
342 for (i=0; i<15; ++i)
343 {
344 if (BitIsSet (registers, 1u << i))
345 {
346 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
347 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000349 if (!success)
350 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000351 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000352 return false;
353 addr += addr_byte_size;
354 }
355 }
356
357 if (BitIsSet (registers, 1u << 15))
358 {
359 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
360 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000361 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000362 if (!success)
363 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000364 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000365 return false;
366 addr += addr_byte_size;
367 }
368
369 context.type = EmulateInstruction::eContextAdjustStackPointer;
370 context.arg0 = eRegisterKindGeneric;
371 context.arg1 = LLDB_REGNUM_GENERIC_SP;
372 context.arg2 = sp_offset;
373
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000374 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000375 return false;
376 }
377 return true;
378}
379
Johnny Chen5b442b72011-01-27 19:34:30 +0000380// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000381// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000382bool
383EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000384{
385#if 0
386 // ARM pseudo code...
387 if (ConditionPassed())
388 {
389 EncodingSpecificOperations();
390 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
391 if d == 15 then
392 ALUWritePC(result); // setflags is always FALSE here
393 else
394 R[d] = result;
395 if setflags then
396 APSR.N = result<31>;
397 APSR.Z = IsZeroBit(result);
398 APSR.C = carry;
399 APSR.V = overflow;
400 }
401#endif
402
403 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000404 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000405 if (!success)
406 return false;
407
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000408 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000409 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000410 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000411 if (!success)
412 return false;
413 uint32_t Rd; // the destination register
414 uint32_t imm32;
415 switch (encoding) {
416 case eEncodingT1:
417 Rd = 7;
418 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
419 break;
420 case eEncodingA1:
421 Rd = Bits32(opcode, 15, 12);
422 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
423 break;
424 default:
425 return false;
426 }
427 addr_t sp_offset = imm32;
428 addr_t addr = sp + sp_offset; // a pointer to the stack area
429
430 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
431 eRegisterKindGeneric,
432 LLDB_REGNUM_GENERIC_SP,
433 sp_offset };
434
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000436 return false;
437 }
438 return true;
439}
440
Johnny Chen2ccad832011-01-28 19:57:25 +0000441// Set r7 or ip to the current stack pointer.
442// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000443bool
444EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000445{
446#if 0
447 // ARM pseudo code...
448 if (ConditionPassed())
449 {
450 EncodingSpecificOperations();
451 result = R[m];
452 if d == 15 then
453 ALUWritePC(result); // setflags is always FALSE here
454 else
455 R[d] = result;
456 if setflags then
457 APSR.N = result<31>;
458 APSR.Z = IsZeroBit(result);
459 // APSR.C unchanged
460 // APSR.V unchanged
461 }
462#endif
463
464 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000465 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000466 //if (!success)
467 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000468
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000470 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000471 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000472 if (!success)
473 return false;
474 uint32_t Rd; // the destination register
475 switch (encoding) {
476 case eEncodingT1:
477 Rd = 7;
478 break;
479 case eEncodingA1:
480 Rd = 12;
481 break;
482 default:
483 return false;
484 }
485 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
486 eRegisterKindGeneric,
487 LLDB_REGNUM_GENERIC_SP,
488 0 };
489
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000490 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000491 return false;
492 }
493 return true;
494}
495
Johnny Chen1c13b622011-01-29 00:11:15 +0000496// Move from high register (r8-r15) to low register (r0-r7).
497// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000498bool
499EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000500{
501#if 0
502 // ARM pseudo code...
503 if (ConditionPassed())
504 {
505 EncodingSpecificOperations();
506 result = R[m];
507 if d == 15 then
508 ALUWritePC(result); // setflags is always FALSE here
509 else
510 R[d] = result;
511 if setflags then
512 APSR.N = result<31>;
513 APSR.Z = IsZeroBit(result);
514 // APSR.C unchanged
515 // APSR.V unchanged
516 }
517#endif
518
519 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000520 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000521 if (!success)
522 return false;
523
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 {
526 uint32_t Rm; // the source register
527 uint32_t Rd; // the destination register
528 switch (encoding) {
529 case eEncodingT1:
530 Rm = Bits32(opcode, 6, 3);
531 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
532 break;
533 default:
534 return false;
535 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000537 if (!success)
538 return false;
539
540 // The context specifies that Rm is to be moved into Rd.
541 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
542 eRegisterKindDWARF,
543 dwarf_r0 + Rm,
544 0 };
545
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000546 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000547 return false;
548 }
549 return true;
550}
551
Johnny Chen788e0552011-01-27 22:52:23 +0000552// PC relative immediate load into register, possibly followed by ADD (SP plus register).
553// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554bool
555EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000556{
557#if 0
558 // ARM pseudo code...
559 if (ConditionPassed())
560 {
561 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
562 base = Align(PC,4);
563 address = if add then (base + imm32) else (base - imm32);
564 data = MemU[address,4];
565 if t == 15 then
566 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
567 elsif UnalignedSupport() || address<1:0> = ‘00’ then
568 R[t] = data;
569 else // Can only apply before ARMv7
570 if CurrentInstrSet() == InstrSet_ARM then
571 R[t] = ROR(data, 8*UInt(address<1:0>));
572 else
573 R[t] = bits(32) UNKNOWN;
574 }
575#endif
576
577 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000578 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000579 if (!success)
580 return false;
581
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000582 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000583 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000584 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000585 if (!success)
586 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000587
588 // PC relative immediate load context
589 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
590 eRegisterKindGeneric,
591 LLDB_REGNUM_GENERIC_PC,
592 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000593 uint32_t Rd; // the destination register
594 uint32_t imm32; // immediate offset from the PC
595 addr_t addr; // the PC relative address
596 uint32_t data; // the literal data value from the PC relative load
597 switch (encoding) {
598 case eEncodingT1:
599 Rd = Bits32(opcode, 10, 8);
600 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
601 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000602 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000603 break;
604 default:
605 return false;
606 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000607 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000608 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000609 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000611 return false;
612 }
613 return true;
614}
615
Johnny Chen5b442b72011-01-27 19:34:30 +0000616// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000617// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000618bool
619EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000620{
621#if 0
622 // ARM pseudo code...
623 if (ConditionPassed())
624 {
625 EncodingSpecificOperations();
626 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
627 if d == 15 then // Can only occur for ARM encoding
628 ALUWritePC(result); // setflags is always FALSE here
629 else
630 R[d] = result;
631 if setflags then
632 APSR.N = result<31>;
633 APSR.Z = IsZeroBit(result);
634 APSR.C = carry;
635 APSR.V = overflow;
636 }
637#endif
638
639 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000640 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000641 if (!success)
642 return false;
643
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000644 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000645 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000646 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000647 if (!success)
648 return false;
649 uint32_t imm32; // the immediate operand
650 switch (encoding) {
651 case eEncodingT2:
652 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
653 break;
654 default:
655 return false;
656 }
657 addr_t sp_offset = imm32;
658 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
659
660 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
661 eRegisterKindGeneric,
662 LLDB_REGNUM_GENERIC_SP,
663 sp_offset };
664
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000665 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000666 return false;
667 }
668 return true;
669}
670
671// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000672// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000673bool
674EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000675{
676#if 0
677 // ARM pseudo code...
678 if (ConditionPassed())
679 {
680 EncodingSpecificOperations();
681 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
682 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
683 if d == 15 then
684 ALUWritePC(result); // setflags is always FALSE here
685 else
686 R[d] = result;
687 if setflags then
688 APSR.N = result<31>;
689 APSR.Z = IsZeroBit(result);
690 APSR.C = carry;
691 APSR.V = overflow;
692 }
693#endif
694
695 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000696 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000697 if (!success)
698 return false;
699
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000700 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000701 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000702 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000703 if (!success)
704 return false;
705 uint32_t Rm; // the second operand
706 switch (encoding) {
707 case eEncodingT2:
708 Rm = Bits32(opcode, 6, 3);
709 break;
710 default:
711 return false;
712 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000713 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000714 if (!success)
715 return false;
716
717 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
718
719 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
720 eRegisterKindGeneric,
721 LLDB_REGNUM_GENERIC_SP,
722 reg_value };
723
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000724 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000725 return false;
726 }
727 return true;
728}
729
Johnny Chen9b8d7832011-02-02 01:13:56 +0000730// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
731// at a PC-relative address, and changes instruction set from ARM to Thumb, or
732// from Thumb to ARM.
733// BLX (immediate)
734bool
735EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
736{
737#if 0
738 // ARM pseudo code...
739 if (ConditionPassed())
740 {
741 EncodingSpecificOperations();
742 if CurrentInstrSet() == InstrSet_ARM then
743 LR = PC - 4;
744 else
745 LR = PC<31:1> : '1';
746 if targetInstrSet == InstrSet_ARM then
747 targetAddress = Align(PC,4) + imm32;
748 else
749 targetAddress = PC + imm32;
750 SelectInstrSet(targetInstrSet);
751 BranchWritePC(targetAddress);
752 }
753#endif
754
755 bool success = false;
756 const uint32_t opcode = OpcodeAsUnsigned (&success);
757 if (!success)
758 return false;
759
760 if (ConditionPassed())
761 {
762 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
763 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
764 addr_t lr; // next instruction address
765 addr_t target; // target address
766 if (!success)
767 return false;
768 int32_t imm32; // PC-relative offset
769 switch (encoding) {
770 case eEncodingT2:
771 {
772 lr = (pc + 4) | 1u; // return address
773 uint32_t S = Bits32(opcode, 26, 26);
774 uint32_t imm10H = Bits32(opcode, 25, 16);
775 uint32_t J1 = Bits32(opcode, 13, 13);
776 uint32_t J2 = Bits32(opcode, 11, 11);
777 uint32_t imm10L = Bits32(opcode, 10, 1);
778 uint32_t I1 = !(J1 ^ S);
779 uint32_t I2 = !(J2 ^ S);
780 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
781 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chen9ee056b2011-02-08 00:06:35 +0000782 target = ((pc + 4) & 0xfffffffc) + imm32;
783 context.arg1 = 4 + imm32; // signed offset
784 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000785 break;
786 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000787 case eEncodingA1:
788 lr = pc + 4; // return address
789 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
790 target = pc + 8 + imm32;
791 context.arg1 = 8 + imm32; // signed offset
792 context.arg2 = eModeARM; // target instruction set
793 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000794 case eEncodingA2:
795 lr = pc + 4; // return address
796 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
797 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000798 context.arg1 = 8 + imm32; // signed offset
799 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000800 break;
801 default:
802 return false;
803 }
804 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
805 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000806 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000807 return false;
808 }
809 return true;
810}
811
812// Branch with Link and Exchange (register) calls a subroutine at an address and
813// instruction set specified by a register.
814// BLX (register)
815bool
816EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
817{
818#if 0
819 // ARM pseudo code...
820 if (ConditionPassed())
821 {
822 EncodingSpecificOperations();
823 target = R[m];
824 if CurrentInstrSet() == InstrSet_ARM then
825 next_instr_addr = PC - 4;
826 LR = next_instr_addr;
827 else
828 next_instr_addr = PC - 2;
829 LR = next_instr_addr<31:1> : ‘1’;
830 BXWritePC(target);
831 }
832#endif
833
834 bool success = false;
835 const uint32_t opcode = OpcodeAsUnsigned (&success);
836 if (!success)
837 return false;
838
839 if (ConditionPassed())
840 {
841 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
842 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
843 addr_t lr; // next instruction address
844 addr_t target; // target address
845 if (!success)
846 return false;
847 uint32_t Rm; // the register with the target address
848 switch (encoding) {
849 case eEncodingT1:
850 lr = (pc + 2) | 1u; // return address
851 Rm = Bits32(opcode, 6, 3);
852 // if m == 15 then UNPREDICTABLE;
853 if (Rm == 15)
854 return false;
855 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
856 break;
857 case eEncodingA1:
858 lr = pc + 4; // return address
859 Rm = Bits32(opcode, 3, 0);
860 // if m == 15 then UNPREDICTABLE;
861 if (Rm == 15)
862 return false;
863 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000864 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000865 default:
866 return false;
867 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000868 context.arg0 = eRegisterKindDWARF;
869 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000870 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
871 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000872 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000873 return false;
874 }
875 return true;
876}
877
Johnny Chen0d0148e2011-01-28 02:26:08 +0000878// Set r7 to point to some ip offset.
879// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000880bool
881EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000882{
883#if 0
884 // ARM pseudo code...
885 if (ConditionPassed())
886 {
887 EncodingSpecificOperations();
888 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
889 if d == 15 then // Can only occur for ARM encoding
890 ALUWritePC(result); // setflags is always FALSE here
891 else
892 R[d] = result;
893 if setflags then
894 APSR.N = result<31>;
895 APSR.Z = IsZeroBit(result);
896 APSR.C = carry;
897 APSR.V = overflow;
898 }
899#endif
900
901 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000902 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000903 if (!success)
904 return false;
905
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000906 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000907 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000908 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000909 if (!success)
910 return false;
911 uint32_t imm32;
912 switch (encoding) {
913 case eEncodingA1:
914 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
915 break;
916 default:
917 return false;
918 }
919 addr_t ip_offset = imm32;
920 addr_t addr = ip - ip_offset; // the adjusted ip value
921
922 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
923 eRegisterKindDWARF,
924 dwarf_r12,
925 -ip_offset };
926
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000928 return false;
929 }
930 return true;
931}
932
933// Set ip to point to some stack offset.
934// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000935bool
936EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000937{
938#if 0
939 // ARM pseudo code...
940 if (ConditionPassed())
941 {
942 EncodingSpecificOperations();
943 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
944 if d == 15 then // Can only occur for ARM encoding
945 ALUWritePC(result); // setflags is always FALSE here
946 else
947 R[d] = result;
948 if setflags then
949 APSR.N = result<31>;
950 APSR.Z = IsZeroBit(result);
951 APSR.C = carry;
952 APSR.V = overflow;
953 }
954#endif
955
956 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000957 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000958 if (!success)
959 return false;
960
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000961 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000962 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000963 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000964 if (!success)
965 return false;
966 uint32_t imm32;
967 switch (encoding) {
968 case eEncodingA1:
969 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
970 break;
971 default:
972 return false;
973 }
974 addr_t sp_offset = imm32;
975 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
976
977 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
978 eRegisterKindGeneric,
979 LLDB_REGNUM_GENERIC_SP,
980 -sp_offset };
981
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000982 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000983 return false;
984 }
985 return true;
986}
987
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000988// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000989bool
990EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000991{
992#if 0
993 // ARM pseudo code...
994 if (ConditionPassed())
995 {
996 EncodingSpecificOperations();
997 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
998 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +0000999 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001000 else
1001 R[d] = result;
1002 if setflags then
1003 APSR.N = result<31>;
1004 APSR.Z = IsZeroBit(result);
1005 APSR.C = carry;
1006 APSR.V = overflow;
1007 }
1008#endif
1009
1010 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001012 if (!success)
1013 return false;
1014
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001015 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001016 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001017 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001018 if (!success)
1019 return false;
1020 uint32_t imm32;
1021 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001022 case eEncodingT1:
1023 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001024 case eEncodingT2:
1025 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1026 break;
1027 case eEncodingT3:
1028 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1029 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001030 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001031 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001032 break;
1033 default:
1034 return false;
1035 }
1036 addr_t sp_offset = imm32;
1037 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1038
1039 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1040 eRegisterKindGeneric,
1041 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001042 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001043
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001044 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001045 return false;
1046 }
1047 return true;
1048}
1049
Johnny Chen08c25e82011-01-31 18:02:28 +00001050// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001051bool
1052EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001053{
1054#if 0
1055 // ARM pseudo code...
1056 if (ConditionPassed())
1057 {
1058 EncodingSpecificOperations();
1059 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1060 address = if index then offset_addr else R[n];
1061 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1062 if wback then R[n] = offset_addr;
1063 }
1064#endif
1065
1066 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001067 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001068 if (!success)
1069 return false;
1070
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001071 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001072 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001073 const uint32_t addr_byte_size = GetAddressByteSize();
1074 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001075 if (!success)
1076 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001077 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001078 uint32_t imm12;
1079 switch (encoding) {
1080 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001081 Rt = Bits32(opcode, 15, 12);
1082 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001083 break;
1084 default:
1085 return false;
1086 }
1087 addr_t sp_offset = imm12;
1088 addr_t addr = sp - sp_offset;
1089
1090 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001091 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001092 {
Johnny Chen91d99862011-01-25 19:07:04 +00001093 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1094 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001095 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001096 if (!success)
1097 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001098 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001099 return false;
1100 }
1101 else
1102 {
1103 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1104 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001105 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001106 if (!success)
1107 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001108 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001109 return false;
1110 }
1111
1112 context.type = EmulateInstruction::eContextAdjustStackPointer;
1113 context.arg0 = eRegisterKindGeneric;
1114 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001115 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001116
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001117 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001118 return false;
1119 }
1120 return true;
1121}
1122
Johnny Chen08c25e82011-01-31 18:02:28 +00001123// Vector Push stores multiple extension registers to the stack.
1124// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001125bool
1126EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001127{
1128#if 0
1129 // ARM pseudo code...
1130 if (ConditionPassed())
1131 {
1132 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1133 address = SP - imm32;
1134 SP = SP - imm32;
1135 if single_regs then
1136 for r = 0 to regs-1
1137 MemA[address,4] = S[d+r]; address = address+4;
1138 else
1139 for r = 0 to regs-1
1140 // Store as two word-aligned words in the correct order for current endianness.
1141 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1142 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1143 address = address+8;
1144 }
1145#endif
1146
1147 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001148 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001149 if (!success)
1150 return false;
1151
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001152 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001153 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001154 const uint32_t addr_byte_size = GetAddressByteSize();
1155 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001156 if (!success)
1157 return false;
1158 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001159 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001160 uint32_t imm32; // stack offset
1161 uint32_t regs; // number of registers
1162 switch (encoding) {
1163 case eEncodingT1:
1164 case eEncodingA1:
1165 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001166 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001167 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1168 // If UInt(imm8) is odd, see "FSTMX".
1169 regs = Bits32(opcode, 7, 0) / 2;
1170 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1171 if (regs == 0 || regs > 16 || (d + regs) > 32)
1172 return false;
1173 break;
1174 case eEncodingT2:
1175 case eEncodingA2:
1176 single_regs = true;
1177 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1178 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1179 regs = Bits32(opcode, 7, 0);
1180 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1181 if (regs == 0 || regs > 16 || (d + regs) > 32)
1182 return false;
1183 break;
1184 default:
1185 return false;
1186 }
1187 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1188 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1189 addr_t sp_offset = imm32;
1190 addr_t addr = sp - sp_offset;
1191 uint32_t i;
1192
1193 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1194 for (i=d; i<regs; ++i)
1195 {
1196 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1197 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1198 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001199 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001200 if (!success)
1201 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001202 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001203 return false;
1204 addr += reg_byte_size;
1205 }
1206
1207 context.type = EmulateInstruction::eContextAdjustStackPointer;
1208 context.arg0 = eRegisterKindGeneric;
1209 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001210 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001211
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001212 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001213 return false;
1214 }
1215 return true;
1216}
1217
Johnny Chen587a0a42011-02-01 18:35:28 +00001218// Vector Pop loads multiple extension registers from the stack.
1219// It also updates SP to point just above the loaded data.
1220bool
1221EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1222{
1223#if 0
1224 // ARM pseudo code...
1225 if (ConditionPassed())
1226 {
1227 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1228 address = SP;
1229 SP = SP + imm32;
1230 if single_regs then
1231 for r = 0 to regs-1
1232 S[d+r] = MemA[address,4]; address = address+4;
1233 else
1234 for r = 0 to regs-1
1235 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1236 // Combine the word-aligned words in the correct order for current endianness.
1237 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1238 }
1239#endif
1240
1241 bool success = false;
1242 const uint32_t opcode = OpcodeAsUnsigned (&success);
1243 if (!success)
1244 return false;
1245
1246 if (ConditionPassed())
1247 {
1248 const uint32_t addr_byte_size = GetAddressByteSize();
1249 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1250 if (!success)
1251 return false;
1252 bool single_regs;
1253 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1254 uint32_t imm32; // stack offset
1255 uint32_t regs; // number of registers
1256 switch (encoding) {
1257 case eEncodingT1:
1258 case eEncodingA1:
1259 single_regs = false;
1260 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1261 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1262 // If UInt(imm8) is odd, see "FLDMX".
1263 regs = Bits32(opcode, 7, 0) / 2;
1264 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1265 if (regs == 0 || regs > 16 || (d + regs) > 32)
1266 return false;
1267 break;
1268 case eEncodingT2:
1269 case eEncodingA2:
1270 single_regs = true;
1271 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1272 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1273 regs = Bits32(opcode, 7, 0);
1274 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1275 if (regs == 0 || regs > 16 || (d + regs) > 32)
1276 return false;
1277 break;
1278 default:
1279 return false;
1280 }
1281 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1282 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1283 addr_t sp_offset = imm32;
1284 addr_t addr = sp;
1285 uint32_t i;
1286 uint64_t data; // uint64_t to accomodate 64-bit registers.
1287
1288 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1289 for (i=d; i<regs; ++i)
1290 {
1291 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1292 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1293 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1294 if (!success)
1295 return false;
1296 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1297 return false;
1298 addr += reg_byte_size;
1299 }
1300
1301 context.type = EmulateInstruction::eContextAdjustStackPointer;
1302 context.arg0 = eRegisterKindGeneric;
1303 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1304 context.arg2 = sp_offset;
1305
1306 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1307 return false;
1308 }
1309 return true;
1310}
1311
Johnny Chenb77be412011-02-04 00:40:18 +00001312// SVC (previously SWI)
1313bool
1314EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1315{
1316#if 0
1317 // ARM pseudo code...
1318 if (ConditionPassed())
1319 {
1320 EncodingSpecificOperations();
1321 CallSupervisor();
1322 }
1323#endif
1324
1325 bool success = false;
1326 const uint32_t opcode = OpcodeAsUnsigned (&success);
1327 if (!success)
1328 return false;
1329
1330 if (ConditionPassed())
1331 {
1332 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1333 addr_t lr; // next instruction address
1334 if (!success)
1335 return false;
1336 uint32_t imm32; // the immediate constant
1337 uint32_t mode; // ARM or Thumb mode
1338 switch (encoding) {
1339 case eEncodingT1:
1340 lr = (pc + 2) | 1u; // return address
1341 imm32 = Bits32(opcode, 7, 0);
1342 mode = eModeThumb;
1343 break;
1344 case eEncodingA1:
1345 lr = pc + 4; // return address
1346 imm32 = Bits32(opcode, 23, 0);
1347 mode = eModeARM;
1348 break;
1349 default:
1350 return false;
1351 }
1352 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1353 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1354 return false;
1355 }
1356 return true;
1357}
1358
Johnny Chenc315f862011-02-05 00:46:10 +00001359// If Then makes up to four following instructions (the IT block) conditional.
1360bool
1361EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1362{
1363#if 0
1364 // ARM pseudo code...
1365 EncodingSpecificOperations();
1366 ITSTATE.IT<7:0> = firstcond:mask;
1367#endif
1368
1369 bool success = false;
1370 const uint32_t opcode = OpcodeAsUnsigned (&success);
1371 if (!success)
1372 return false;
1373
1374 m_it_session.InitIT(Bits32(opcode, 7, 0));
1375 return true;
1376}
1377
Johnny Chen3b620b32011-02-07 20:11:47 +00001378// Branch causes a branch to a target address.
1379bool
1380EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1381{
1382#if 0
1383 // ARM pseudo code...
1384 if (ConditionPassed())
1385 {
1386 EncodingSpecificOperations();
1387 BranchWritePC(PC + imm32);
1388 }
1389#endif
1390
1391 bool success = false;
1392 const uint32_t opcode = OpcodeAsUnsigned (&success);
1393 if (!success)
1394 return false;
1395
Johnny Chen9ee056b2011-02-08 00:06:35 +00001396 if (ConditionPassed())
1397 {
1398 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1399 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1400 addr_t target; // target address
1401 if (!success)
1402 return false;
1403 int32_t imm32; // PC-relative offset
1404 switch (encoding) {
1405 case eEncodingT1:
1406 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1407 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1408 target = pc + 4 + imm32;
1409 context.arg1 = 4 + imm32; // signed offset
1410 context.arg2 = eModeThumb; // target instruction set
1411 break;
1412 case eEncodingT2:
1413 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1414 target = pc + 4 + imm32;
1415 context.arg1 = 4 + imm32; // signed offset
1416 context.arg2 = eModeThumb; // target instruction set
1417 break;
1418 case eEncodingT3:
1419 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1420 {
1421 uint32_t S = Bits32(opcode, 26, 26);
1422 uint32_t imm6 = Bits32(opcode, 21, 16);
1423 uint32_t J1 = Bits32(opcode, 13, 13);
1424 uint32_t J2 = Bits32(opcode, 11, 11);
1425 uint32_t imm11 = Bits32(opcode, 10, 0);
1426 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) + (imm11 << 1);
1427 imm32 = llvm::SignExtend32<21>(imm21);
1428 target = pc + 4 + imm32;
1429 context.arg1 = eModeThumb; // target instruction set
1430 context.arg2 = 4 + imm32; // signed offset
1431 break;
1432 }
1433 case eEncodingT4:
1434 {
1435 uint32_t S = Bits32(opcode, 26, 26);
1436 uint32_t imm10 = Bits32(opcode, 25, 16);
1437 uint32_t J1 = Bits32(opcode, 13, 13);
1438 uint32_t J2 = Bits32(opcode, 11, 11);
1439 uint32_t imm11 = Bits32(opcode, 10, 0);
1440 uint32_t I1 = !(J1 ^ S);
1441 uint32_t I2 = !(J2 ^ S);
1442 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
1443 imm32 = llvm::SignExtend32<25>(imm25);
1444 target = pc + 4 + imm32;
1445 context.arg1 = eModeThumb; // target instruction set
1446 context.arg2 = 4 + imm32; // signed offset
1447 break;
1448 }
1449 case eEncodingA1:
1450 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1451 target = pc + 8 + imm32;
1452 context.arg1 = eModeARM; // target instruction set
1453 context.arg2 = 8 + imm32; // signed offset
1454 break;
1455 default:
1456 return false;
1457 }
1458 if (!BranchWritePC(context, target))
1459 return false;
1460 }
1461 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001462}
1463
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001464EmulateInstructionARM::ARMOpcode*
1465EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001466{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001467 static ARMOpcode
1468 g_arm_opcodes[] =
1469 {
1470 //----------------------------------------------------------------------
1471 // Prologue instructions
1472 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001473
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001474 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001475 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1476 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001477
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001478 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001479 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1480 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001481 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001482 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1483 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1484 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001485
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001486 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001487 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001488
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001489 // push one register
1490 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001491 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001492
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001493 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001494 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1495 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001496
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001497 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001498 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001499 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001500
Johnny Chen9b8d7832011-02-02 01:13:56 +00001501 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1502 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1503 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1504 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001505 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1506 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001507 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001508 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1509
1510 //----------------------------------------------------------------------
1511 // Supervisor Call (previously Software Interrupt)
1512 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001513 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1514
1515 //----------------------------------------------------------------------
1516 // Branch instructions
1517 //----------------------------------------------------------------------
1518 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"}
Johnny Chenb77be412011-02-04 00:40:18 +00001519
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001520 };
1521 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1522
1523 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1524 {
1525 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1526 return &g_arm_opcodes[i];
1527 }
1528 return NULL;
1529}
Greg Clayton64c84432011-01-21 22:02:52 +00001530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001531
1532EmulateInstructionARM::ARMOpcode*
1533EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001534{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001535
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001536 static ARMOpcode
1537 g_thumb_opcodes[] =
1538 {
1539 //----------------------------------------------------------------------
1540 // Prologue instructions
1541 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001542
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001543 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001544 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1545 { 0xffff0000, 0xe92d0000, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1546 { 0xffff0fff, 0xf84d0d04, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001547 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001548 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001549
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001550 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001551 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1552 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001553
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001554 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001555 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001556
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001557 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001558 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1559 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
1560 { 0xfbef8f00, 0xf1ad0d00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1561 { 0xfbff8f00, 0xf2ad0d00, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001562
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001563 // vector push consecutive extension register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001564 { 0xffbf0f00, 0xed2d0b00, ARMv6T2|ARMv7, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1565 { 0xffbf0f00, 0xed2d0a00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001566
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001567 //----------------------------------------------------------------------
1568 // Epilogue instructions
1569 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001570
Johnny Chenc28a76d2011-02-01 18:51:48 +00001571 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001572 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1573 // J1 == J2 == 1
1574 { 0xf800e801, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001575 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1576 { 0xffff0000, 0xe8bd0000, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1577 { 0xffff0fff, 0xf85d0d04, ARMv6T2|ARMv7, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1578 { 0xffbf0f00, 0xecbd0b00, ARMv6T2|ARMv7, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001579 { 0xffbf0f00, 0xecbd0a00, ARMv6T2|ARMv7, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1580
1581 //----------------------------------------------------------------------
1582 // Supervisor Call (previously Software Interrupt)
1583 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00001584 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
1585
1586 //----------------------------------------------------------------------
1587 // If Then makes up to four following instructions conditional.
1588 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001589 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
1590
1591 //----------------------------------------------------------------------
1592 // Branch instructions
1593 //----------------------------------------------------------------------
1594 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
1595 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
1596 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00001597 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
1598 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"}
Johnny Chenb77be412011-02-04 00:40:18 +00001599
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001600 };
1601
1602 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1603 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1604 {
1605 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1606 return &g_thumb_opcodes[i];
1607 }
1608 return NULL;
1609}
Greg Clayton64c84432011-01-21 22:02:52 +00001610
Greg Clayton31e2a382011-01-30 20:03:56 +00001611bool
1612EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1613{
1614 m_arm_isa = 0;
1615 const char *triple_cstr = triple.GetCString();
1616 if (triple_cstr)
1617 {
1618 const char *dash = ::strchr (triple_cstr, '-');
1619 if (dash)
1620 {
1621 std::string arch (triple_cstr, dash);
1622 const char *arch_cstr = arch.c_str();
1623 if (strcasecmp(arch_cstr, "armv4t") == 0)
1624 m_arm_isa = ARMv4T;
1625 else if (strcasecmp(arch_cstr, "armv4") == 0)
1626 m_arm_isa = ARMv4;
1627 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1628 m_arm_isa = ARMv5TEJ;
1629 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1630 m_arm_isa = ARMv5TE;
1631 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1632 m_arm_isa = ARMv5T;
1633 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1634 m_arm_isa = ARMv6K;
1635 else if (strcasecmp(arch_cstr, "armv6") == 0)
1636 m_arm_isa = ARMv6;
1637 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1638 m_arm_isa = ARMv6T2;
1639 else if (strcasecmp(arch_cstr, "armv7") == 0)
1640 m_arm_isa = ARMv7;
1641 else if (strcasecmp(arch_cstr, "armv8") == 0)
1642 m_arm_isa = ARMv8;
1643 }
1644 }
1645 return m_arm_isa != 0;
1646}
1647
1648
Greg Clayton64c84432011-01-21 22:02:52 +00001649bool
1650EmulateInstructionARM::ReadInstruction ()
1651{
1652 bool success = false;
1653 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1654 if (success)
1655 {
1656 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1657 if (success)
1658 {
1659 Context read_inst_context = {eContextReadOpcode, 0, 0};
1660 if (m_inst_cpsr & MASK_CPSR_T)
1661 {
1662 m_inst_mode = eModeThumb;
1663 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
1664
1665 if (success)
1666 {
1667 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
1668 {
1669 m_inst.opcode_type = eOpcode16;
1670 m_inst.opcode.inst16 = thumb_opcode;
1671 }
1672 else
1673 {
1674 m_inst.opcode_type = eOpcode32;
1675 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
1676 }
1677 }
1678 }
1679 else
1680 {
1681 m_inst_mode = eModeARM;
1682 m_inst.opcode_type = eOpcode32;
1683 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
1684 }
1685 }
1686 }
1687 if (!success)
1688 {
1689 m_inst_mode = eModeInvalid;
1690 m_inst_pc = LLDB_INVALID_ADDRESS;
1691 }
1692 return success;
1693}
1694
Greg Clayton64c84432011-01-21 22:02:52 +00001695bool
1696EmulateInstructionARM::ConditionPassed ()
1697{
1698 if (m_inst_cpsr == 0)
1699 return false;
1700
1701 const uint32_t cond = CurrentCond ();
1702
1703 if (cond == UINT32_MAX)
1704 return false;
1705
1706 bool result = false;
1707 switch (UnsignedBits(cond, 3, 1))
1708 {
1709 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
1710 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
1711 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
1712 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
1713 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
1714 case 5:
1715 {
1716 bool n = (m_inst_cpsr & MASK_CPSR_N);
1717 bool v = (m_inst_cpsr & MASK_CPSR_V);
1718 result = n == v;
1719 }
1720 break;
1721 case 6:
1722 {
1723 bool n = (m_inst_cpsr & MASK_CPSR_N);
1724 bool v = (m_inst_cpsr & MASK_CPSR_V);
1725 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
1726 }
1727 break;
1728 case 7:
1729 result = true;
1730 break;
1731 }
1732
1733 if (cond & 1)
1734 result = !result;
1735 return result;
1736}
1737
Johnny Chen9ee056b2011-02-08 00:06:35 +00001738uint32_t
1739EmulateInstructionARM::CurrentCond ()
1740{
1741 switch (m_inst_mode)
1742 {
1743 default:
1744 case eModeInvalid:
1745 break;
1746
1747 case eModeARM:
1748 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
1749
1750 case eModeThumb:
1751 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
1752 // 'cond' field of the encoding.
1753 if (m_inst.opcode_type == eOpcode16 &&
1754 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
1755 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
1756 {
1757 return Bits32(m_inst.opcode.inst16, 11, 7);
1758 }
1759 else if (m_inst.opcode_type == eOpcode32 &&
1760 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
1761 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
1762 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
1763 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
1764 {
1765 return Bits32(m_inst.opcode.inst32, 25, 22);
1766 }
1767
1768 return m_it_session.GetCond();
1769 }
1770 return UINT32_MAX; // Return invalid value
1771}
1772
1773// API client must pass in a context whose arg2 field contains the target instruction set.
1774bool
1775EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
1776{
1777 addr_t target;
1778
1779 // Chech the target instruction set.
1780 switch (context.arg2)
1781 {
1782 default:
1783 assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
1784 return false;
1785 case eModeARM:
1786 target = addr & 0xfffffffc;
1787 break;
1788 case eModeThumb:
1789 target = addr & 0xfffffffe;
1790 break;
1791 }
1792 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1793 return false;
1794 return false;
1795}
1796
1797// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
1798bool
1799EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
1800{
1801 addr_t target;
1802
1803 if (BitIsSet(addr, 0))
1804 {
1805 target = addr & 0xfffffffe;
1806 context.arg2 = eModeThumb;
1807 }
1808 else if (BitIsClear(addr, 1))
1809 {
1810 target = addr & 0xfffffffc;
1811 context.arg2 = eModeARM;
1812 }
1813 else
1814 return false; // address<1:0> == '10' => UNPREDICTABLE
1815
1816 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1817 return false;
1818 return false;
1819}
Greg Clayton64c84432011-01-21 22:02:52 +00001820
1821bool
1822EmulateInstructionARM::EvaluateInstruction ()
1823{
Johnny Chenc315f862011-02-05 00:46:10 +00001824 // Advance the ITSTATE bits to their values for the next instruction.
1825 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
1826 m_it_session.ITAdvance();
1827
Greg Clayton64c84432011-01-21 22:02:52 +00001828 return false;
1829}