blob: dae0e9abfb3f527bb30f3cca77ac303329b5a63b [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
Greg Clayton64c84432011-01-21 22:02:52 +0000131
Johnny Chen08c25e82011-01-31 18:02:28 +0000132// Push Multiple Registers stores multiple registers to the stack, storing to
133// consecutive memory locations ending just below the address in SP, and updates
134// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000135bool
136EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000137{
138#if 0
139 // ARM pseudo code...
140 if (ConditionPassed())
141 {
142 EncodingSpecificOperations();
143 NullCheckIfThumbEE(13);
144 address = SP - 4*BitCount(registers);
145
146 for (i = 0 to 14)
147 {
148 if (registers<i> == ’1’)
149 {
150 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
151 MemA[address,4] = bits(32) UNKNOWN;
152 else
153 MemA[address,4] = R[i];
154 address = address + 4;
155 }
156 }
157
158 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
159 MemA[address,4] = PCStoreValue();
160
161 SP = SP - 4*BitCount(registers);
162 }
163#endif
164
165 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000167 if (!success)
168 return false;
169
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000170 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000171 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000172 const uint32_t addr_byte_size = GetAddressByteSize();
173 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000174 if (!success)
175 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000176 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000177 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000178 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000179 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000180 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000181 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000182 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000183 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000184 // if BitCount(registers) < 1 then UNPREDICTABLE;
185 if (BitCount(registers) < 1)
186 return false;
187 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000188 case eEncodingT2:
189 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000190 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000191 // if BitCount(registers) < 2 then UNPREDICTABLE;
192 if (BitCount(registers) < 2)
193 return false;
194 break;
195 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000196 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000197 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000198 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000199 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000200 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000201 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000202 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000203 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000204 // Instead of return false, let's handle the following case as well,
205 // which amounts to pushing one reg onto the full descending stacks.
206 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000207 break;
208 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000209 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000210 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000211 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000212 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000213 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000214 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000215 default:
216 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000217 }
Johnny Chence1ca772011-01-25 01:13:00 +0000218 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000219 addr_t addr = sp - sp_offset;
220 uint32_t i;
221
222 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
223 for (i=0; i<15; ++i)
224 {
Johnny Chen108d5aa2011-01-26 01:00:55 +0000225 if (BitIsSet (registers, 1u << i))
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
227 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
228 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000229 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000230 if (!success)
231 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000232 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000233 return false;
234 addr += addr_byte_size;
235 }
236 }
237
Johnny Chen108d5aa2011-01-26 01:00:55 +0000238 if (BitIsSet (registers, 1u << 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000239 {
240 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000241 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000242 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000243 if (!success)
244 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000245 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000246 return false;
247 }
248
249 context.type = EmulateInstruction::eContextAdjustStackPointer;
250 context.arg0 = eRegisterKindGeneric;
251 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000252 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000253
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000254 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000255 return false;
256 }
257 return true;
258}
259
Johnny Chenef85e912011-01-31 23:07:40 +0000260// Pop Multiple Registers loads multiple registers from the stack, loading from
261// consecutive memory locations staring at the address in SP, and updates
262// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000263bool
264EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000265{
266#if 0
267 // ARM pseudo code...
268 if (ConditionPassed())
269 {
270 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
271 address = SP;
272 for i = 0 to 14
273 if registers<i> == ‘1’ then
274 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
275 if registers<15> == ‘1’ then
276 if UnalignedAllowed then
277 LoadWritePC(MemU[address,4]);
278 else
279 LoadWritePC(MemA[address,4]);
280 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
281 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
282 }
283#endif
284
285 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000286 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000287 if (!success)
288 return false;
289
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000290 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000291 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000292 const uint32_t addr_byte_size = GetAddressByteSize();
293 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000294 if (!success)
295 return false;
296 uint32_t registers = 0;
297 uint32_t Rt; // the destination register
298 switch (encoding) {
299 case eEncodingT1:
300 registers = Bits32(opcode, 7, 0);
301 // The P bit represents PC.
302 if (Bits32(opcode, 8, 8))
303 registers |= (1u << 15);
304 // if BitCount(registers) < 1 then UNPREDICTABLE;
305 if (BitCount(registers) < 1)
306 return false;
307 break;
308 case eEncodingT2:
309 // Ignore bit 13.
310 registers = Bits32(opcode, 15, 0) & ~0x2000;
311 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
312 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
313 return false;
314 break;
315 case eEncodingT3:
316 Rt = Bits32(opcode, 15, 12);
317 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
318 if (Rt == dwarf_sp)
319 return false;
320 registers = (1u << Rt);
321 break;
322 case eEncodingA1:
323 registers = Bits32(opcode, 15, 0);
324 // Instead of return false, let's handle the following case as well,
325 // which amounts to popping one reg from the full descending stacks.
326 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
327
328 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
329 if (Bits32(opcode, 13, 13))
330 return false;
331 break;
332 case eEncodingA2:
333 Rt = Bits32(opcode, 15, 12);
334 // if t == 13 then UNPREDICTABLE;
335 if (Rt == dwarf_sp)
336 return false;
337 registers = (1u << Rt);
338 break;
339 default:
340 return false;
341 }
342 addr_t sp_offset = addr_byte_size * BitCount (registers);
343 addr_t addr = sp;
344 uint32_t i, data;
345
346 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
347 for (i=0; i<15; ++i)
348 {
349 if (BitIsSet (registers, 1u << i))
350 {
351 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
352 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000353 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000354 if (!success)
355 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000356 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000357 return false;
358 addr += addr_byte_size;
359 }
360 }
361
362 if (BitIsSet (registers, 1u << 15))
363 {
364 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
365 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000366 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000367 if (!success)
368 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000369 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000370 return false;
371 addr += addr_byte_size;
372 }
373
374 context.type = EmulateInstruction::eContextAdjustStackPointer;
375 context.arg0 = eRegisterKindGeneric;
376 context.arg1 = LLDB_REGNUM_GENERIC_SP;
377 context.arg2 = sp_offset;
378
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000379 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000380 return false;
381 }
382 return true;
383}
384
Johnny Chen5b442b72011-01-27 19:34:30 +0000385// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000386// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000387bool
388EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000389{
390#if 0
391 // ARM pseudo code...
392 if (ConditionPassed())
393 {
394 EncodingSpecificOperations();
395 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
396 if d == 15 then
397 ALUWritePC(result); // setflags is always FALSE here
398 else
399 R[d] = result;
400 if setflags then
401 APSR.N = result<31>;
402 APSR.Z = IsZeroBit(result);
403 APSR.C = carry;
404 APSR.V = overflow;
405 }
406#endif
407
408 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000409 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000410 if (!success)
411 return false;
412
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000413 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000414 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000415 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000416 if (!success)
417 return false;
418 uint32_t Rd; // the destination register
419 uint32_t imm32;
420 switch (encoding) {
421 case eEncodingT1:
422 Rd = 7;
423 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
424 break;
425 case eEncodingA1:
426 Rd = Bits32(opcode, 15, 12);
427 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
428 break;
429 default:
430 return false;
431 }
432 addr_t sp_offset = imm32;
433 addr_t addr = sp + sp_offset; // a pointer to the stack area
434
435 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
436 eRegisterKindGeneric,
437 LLDB_REGNUM_GENERIC_SP,
438 sp_offset };
439
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000440 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000441 return false;
442 }
443 return true;
444}
445
Johnny Chen2ccad832011-01-28 19:57:25 +0000446// Set r7 or ip to the current stack pointer.
447// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448bool
449EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000450{
451#if 0
452 // ARM pseudo code...
453 if (ConditionPassed())
454 {
455 EncodingSpecificOperations();
456 result = R[m];
457 if d == 15 then
458 ALUWritePC(result); // setflags is always FALSE here
459 else
460 R[d] = result;
461 if setflags then
462 APSR.N = result<31>;
463 APSR.Z = IsZeroBit(result);
464 // APSR.C unchanged
465 // APSR.V unchanged
466 }
467#endif
468
469 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000470 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000471 //if (!success)
472 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000473
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000475 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000477 if (!success)
478 return false;
479 uint32_t Rd; // the destination register
480 switch (encoding) {
481 case eEncodingT1:
482 Rd = 7;
483 break;
484 case eEncodingA1:
485 Rd = 12;
486 break;
487 default:
488 return false;
489 }
490 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
491 eRegisterKindGeneric,
492 LLDB_REGNUM_GENERIC_SP,
493 0 };
494
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000495 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000496 return false;
497 }
498 return true;
499}
500
Johnny Chen1c13b622011-01-29 00:11:15 +0000501// Move from high register (r8-r15) to low register (r0-r7).
502// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000503bool
504EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000505{
506#if 0
507 // ARM pseudo code...
508 if (ConditionPassed())
509 {
510 EncodingSpecificOperations();
511 result = R[m];
512 if d == 15 then
513 ALUWritePC(result); // setflags is always FALSE here
514 else
515 R[d] = result;
516 if setflags then
517 APSR.N = result<31>;
518 APSR.Z = IsZeroBit(result);
519 // APSR.C unchanged
520 // APSR.V unchanged
521 }
522#endif
523
524 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000525 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000526 if (!success)
527 return false;
528
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000529 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000530 {
531 uint32_t Rm; // the source register
532 uint32_t Rd; // the destination register
533 switch (encoding) {
534 case eEncodingT1:
535 Rm = Bits32(opcode, 6, 3);
536 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
537 break;
538 default:
539 return false;
540 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000541 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000542 if (!success)
543 return false;
544
545 // The context specifies that Rm is to be moved into Rd.
546 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
547 eRegisterKindDWARF,
548 dwarf_r0 + Rm,
549 0 };
550
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000551 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000552 return false;
553 }
554 return true;
555}
556
Johnny Chen788e0552011-01-27 22:52:23 +0000557// PC relative immediate load into register, possibly followed by ADD (SP plus register).
558// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000559bool
560EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000561{
562#if 0
563 // ARM pseudo code...
564 if (ConditionPassed())
565 {
566 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
567 base = Align(PC,4);
568 address = if add then (base + imm32) else (base - imm32);
569 data = MemU[address,4];
570 if t == 15 then
571 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
572 elsif UnalignedSupport() || address<1:0> = ‘00’ then
573 R[t] = data;
574 else // Can only apply before ARMv7
575 if CurrentInstrSet() == InstrSet_ARM then
576 R[t] = ROR(data, 8*UInt(address<1:0>));
577 else
578 R[t] = bits(32) UNKNOWN;
579 }
580#endif
581
582 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000583 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000584 if (!success)
585 return false;
586
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000587 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000588 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000589 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000590 if (!success)
591 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000592
593 // PC relative immediate load context
594 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
595 eRegisterKindGeneric,
596 LLDB_REGNUM_GENERIC_PC,
597 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000598 uint32_t Rd; // the destination register
599 uint32_t imm32; // immediate offset from the PC
600 addr_t addr; // the PC relative address
601 uint32_t data; // the literal data value from the PC relative load
602 switch (encoding) {
603 case eEncodingT1:
604 Rd = Bits32(opcode, 10, 8);
605 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
606 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000607 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000608 break;
609 default:
610 return false;
611 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000612 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000613 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000614 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000616 return false;
617 }
618 return true;
619}
620
Johnny Chen5b442b72011-01-27 19:34:30 +0000621// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000622// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000623bool
624EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000625{
626#if 0
627 // ARM pseudo code...
628 if (ConditionPassed())
629 {
630 EncodingSpecificOperations();
631 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
632 if d == 15 then // Can only occur for ARM encoding
633 ALUWritePC(result); // setflags is always FALSE here
634 else
635 R[d] = result;
636 if setflags then
637 APSR.N = result<31>;
638 APSR.Z = IsZeroBit(result);
639 APSR.C = carry;
640 APSR.V = overflow;
641 }
642#endif
643
644 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000645 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000646 if (!success)
647 return false;
648
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000649 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000650 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000651 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000652 if (!success)
653 return false;
654 uint32_t imm32; // the immediate operand
655 switch (encoding) {
656 case eEncodingT2:
657 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
658 break;
659 default:
660 return false;
661 }
662 addr_t sp_offset = imm32;
663 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
664
665 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
666 eRegisterKindGeneric,
667 LLDB_REGNUM_GENERIC_SP,
668 sp_offset };
669
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000670 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000671 return false;
672 }
673 return true;
674}
675
676// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000677// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000678bool
679EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000680{
681#if 0
682 // ARM pseudo code...
683 if (ConditionPassed())
684 {
685 EncodingSpecificOperations();
686 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
687 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
688 if d == 15 then
689 ALUWritePC(result); // setflags is always FALSE here
690 else
691 R[d] = result;
692 if setflags then
693 APSR.N = result<31>;
694 APSR.Z = IsZeroBit(result);
695 APSR.C = carry;
696 APSR.V = overflow;
697 }
698#endif
699
700 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000701 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000702 if (!success)
703 return false;
704
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000705 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000706 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000707 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000708 if (!success)
709 return false;
710 uint32_t Rm; // the second operand
711 switch (encoding) {
712 case eEncodingT2:
713 Rm = Bits32(opcode, 6, 3);
714 break;
715 default:
716 return false;
717 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000718 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000719 if (!success)
720 return false;
721
722 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
723
724 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
725 eRegisterKindGeneric,
726 LLDB_REGNUM_GENERIC_SP,
727 reg_value };
728
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000729 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000730 return false;
731 }
732 return true;
733}
734
Johnny Chen9b8d7832011-02-02 01:13:56 +0000735// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
736// at a PC-relative address, and changes instruction set from ARM to Thumb, or
737// from Thumb to ARM.
738// BLX (immediate)
739bool
740EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
741{
742#if 0
743 // ARM pseudo code...
744 if (ConditionPassed())
745 {
746 EncodingSpecificOperations();
747 if CurrentInstrSet() == InstrSet_ARM then
748 LR = PC - 4;
749 else
750 LR = PC<31:1> : '1';
751 if targetInstrSet == InstrSet_ARM then
752 targetAddress = Align(PC,4) + imm32;
753 else
754 targetAddress = PC + imm32;
755 SelectInstrSet(targetInstrSet);
756 BranchWritePC(targetAddress);
757 }
758#endif
759
760 bool success = false;
761 const uint32_t opcode = OpcodeAsUnsigned (&success);
762 if (!success)
763 return false;
764
765 if (ConditionPassed())
766 {
767 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
768 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
769 addr_t lr; // next instruction address
770 addr_t target; // target address
771 if (!success)
772 return false;
773 int32_t imm32; // PC-relative offset
774 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000775 case eEncodingT1:
776 {
777 lr = (pc + 4) | 1u; // return address
778 uint32_t S = Bits32(opcode, 26, 26);
779 uint32_t imm10 = Bits32(opcode, 25, 16);
780 uint32_t J1 = Bits32(opcode, 13, 13);
781 uint32_t J2 = Bits32(opcode, 11, 11);
782 uint32_t imm11 = Bits32(opcode, 10, 0);
783 uint32_t I1 = !(J1 ^ S);
784 uint32_t I2 = !(J2 ^ S);
785 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
786 imm32 = llvm::SignExtend32<25>(imm25);
787 target = pc + 4 + imm32;
788 context.arg1 = 4 + imm32; // signed offset
789 context.arg2 = eModeThumb; // target instruction set
790 break;
791 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000792 case eEncodingT2:
793 {
794 lr = (pc + 4) | 1u; // return address
795 uint32_t S = Bits32(opcode, 26, 26);
796 uint32_t imm10H = Bits32(opcode, 25, 16);
797 uint32_t J1 = Bits32(opcode, 13, 13);
798 uint32_t J2 = Bits32(opcode, 11, 11);
799 uint32_t imm10L = Bits32(opcode, 10, 1);
800 uint32_t I1 = !(J1 ^ S);
801 uint32_t I2 = !(J2 ^ S);
802 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
803 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000804 target = Align(pc + 4, 4) + imm32;
805 context.arg1 = 4 + imm32; // signed offset
806 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000807 break;
808 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000809 case eEncodingA1:
810 lr = pc + 4; // return address
811 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000812 target = Align(pc + 8, 4) + imm32;
813 context.arg1 = 8 + imm32; // signed offset
814 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000815 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000816 case eEncodingA2:
817 lr = pc + 4; // return address
818 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
819 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000820 context.arg1 = 8 + imm32; // signed offset
821 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000822 break;
823 default:
824 return false;
825 }
826 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
827 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000828 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000829 return false;
830 }
831 return true;
832}
833
834// Branch with Link and Exchange (register) calls a subroutine at an address and
835// instruction set specified by a register.
836// BLX (register)
837bool
838EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
839{
840#if 0
841 // ARM pseudo code...
842 if (ConditionPassed())
843 {
844 EncodingSpecificOperations();
845 target = R[m];
846 if CurrentInstrSet() == InstrSet_ARM then
847 next_instr_addr = PC - 4;
848 LR = next_instr_addr;
849 else
850 next_instr_addr = PC - 2;
851 LR = next_instr_addr<31:1> : ‘1’;
852 BXWritePC(target);
853 }
854#endif
855
856 bool success = false;
857 const uint32_t opcode = OpcodeAsUnsigned (&success);
858 if (!success)
859 return false;
860
861 if (ConditionPassed())
862 {
863 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
864 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
865 addr_t lr; // next instruction address
866 addr_t target; // target address
867 if (!success)
868 return false;
869 uint32_t Rm; // the register with the target address
870 switch (encoding) {
871 case eEncodingT1:
872 lr = (pc + 2) | 1u; // return address
873 Rm = Bits32(opcode, 6, 3);
874 // if m == 15 then UNPREDICTABLE;
875 if (Rm == 15)
876 return false;
877 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
878 break;
879 case eEncodingA1:
880 lr = pc + 4; // return address
881 Rm = Bits32(opcode, 3, 0);
882 // if m == 15 then UNPREDICTABLE;
883 if (Rm == 15)
884 return false;
885 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000886 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000887 default:
888 return false;
889 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000890 context.arg0 = eRegisterKindDWARF;
891 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000892 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
893 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000894 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000895 return false;
896 }
897 return true;
898}
899
Johnny Chen0d0148e2011-01-28 02:26:08 +0000900// Set r7 to point to some ip offset.
901// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000902bool
903EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000904{
905#if 0
906 // ARM pseudo code...
907 if (ConditionPassed())
908 {
909 EncodingSpecificOperations();
910 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
911 if d == 15 then // Can only occur for ARM encoding
912 ALUWritePC(result); // setflags is always FALSE here
913 else
914 R[d] = result;
915 if setflags then
916 APSR.N = result<31>;
917 APSR.Z = IsZeroBit(result);
918 APSR.C = carry;
919 APSR.V = overflow;
920 }
921#endif
922
923 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000924 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000925 if (!success)
926 return false;
927
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000928 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000929 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000930 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000931 if (!success)
932 return false;
933 uint32_t imm32;
934 switch (encoding) {
935 case eEncodingA1:
936 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
937 break;
938 default:
939 return false;
940 }
941 addr_t ip_offset = imm32;
942 addr_t addr = ip - ip_offset; // the adjusted ip value
943
944 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
945 eRegisterKindDWARF,
946 dwarf_r12,
947 -ip_offset };
948
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000950 return false;
951 }
952 return true;
953}
954
955// Set ip to point to some stack offset.
956// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000957bool
958EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000959{
960#if 0
961 // ARM pseudo code...
962 if (ConditionPassed())
963 {
964 EncodingSpecificOperations();
965 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
966 if d == 15 then // Can only occur for ARM encoding
967 ALUWritePC(result); // setflags is always FALSE here
968 else
969 R[d] = result;
970 if setflags then
971 APSR.N = result<31>;
972 APSR.Z = IsZeroBit(result);
973 APSR.C = carry;
974 APSR.V = overflow;
975 }
976#endif
977
978 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000979 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000980 if (!success)
981 return false;
982
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000983 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000984 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000985 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000986 if (!success)
987 return false;
988 uint32_t imm32;
989 switch (encoding) {
990 case eEncodingA1:
991 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
992 break;
993 default:
994 return false;
995 }
996 addr_t sp_offset = imm32;
997 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
998
999 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1000 eRegisterKindGeneric,
1001 LLDB_REGNUM_GENERIC_SP,
1002 -sp_offset };
1003
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001004 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001005 return false;
1006 }
1007 return true;
1008}
1009
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001010// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011bool
1012EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001013{
1014#if 0
1015 // ARM pseudo code...
1016 if (ConditionPassed())
1017 {
1018 EncodingSpecificOperations();
1019 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1020 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001021 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001022 else
1023 R[d] = result;
1024 if setflags then
1025 APSR.N = result<31>;
1026 APSR.Z = IsZeroBit(result);
1027 APSR.C = carry;
1028 APSR.V = overflow;
1029 }
1030#endif
1031
1032 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001033 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001034 if (!success)
1035 return false;
1036
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001037 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001038 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001039 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001040 if (!success)
1041 return false;
1042 uint32_t imm32;
1043 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001044 case eEncodingT1:
1045 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001046 case eEncodingT2:
1047 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1048 break;
1049 case eEncodingT3:
1050 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1051 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001052 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001053 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001054 break;
1055 default:
1056 return false;
1057 }
1058 addr_t sp_offset = imm32;
1059 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1060
1061 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1062 eRegisterKindGeneric,
1063 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001064 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001065
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001066 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001067 return false;
1068 }
1069 return true;
1070}
1071
Johnny Chen08c25e82011-01-31 18:02:28 +00001072// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001073bool
1074EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001075{
1076#if 0
1077 // ARM pseudo code...
1078 if (ConditionPassed())
1079 {
1080 EncodingSpecificOperations();
1081 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1082 address = if index then offset_addr else R[n];
1083 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1084 if wback then R[n] = offset_addr;
1085 }
1086#endif
1087
1088 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001089 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001090 if (!success)
1091 return false;
1092
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001093 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001094 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001095 const uint32_t addr_byte_size = GetAddressByteSize();
1096 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001097 if (!success)
1098 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001099 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001100 uint32_t imm12;
1101 switch (encoding) {
1102 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001103 Rt = Bits32(opcode, 15, 12);
1104 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001105 break;
1106 default:
1107 return false;
1108 }
1109 addr_t sp_offset = imm12;
1110 addr_t addr = sp - sp_offset;
1111
1112 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001113 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001114 {
Johnny Chen91d99862011-01-25 19:07:04 +00001115 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1116 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001117 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001118 if (!success)
1119 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001120 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001121 return false;
1122 }
1123 else
1124 {
1125 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1126 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001127 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001128 if (!success)
1129 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001130 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001131 return false;
1132 }
1133
1134 context.type = EmulateInstruction::eContextAdjustStackPointer;
1135 context.arg0 = eRegisterKindGeneric;
1136 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001137 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001138
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001139 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001140 return false;
1141 }
1142 return true;
1143}
1144
Johnny Chen08c25e82011-01-31 18:02:28 +00001145// Vector Push stores multiple extension registers to the stack.
1146// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001147bool
1148EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001149{
1150#if 0
1151 // ARM pseudo code...
1152 if (ConditionPassed())
1153 {
1154 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1155 address = SP - imm32;
1156 SP = SP - imm32;
1157 if single_regs then
1158 for r = 0 to regs-1
1159 MemA[address,4] = S[d+r]; address = address+4;
1160 else
1161 for r = 0 to regs-1
1162 // Store as two word-aligned words in the correct order for current endianness.
1163 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1164 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1165 address = address+8;
1166 }
1167#endif
1168
1169 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001170 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001171 if (!success)
1172 return false;
1173
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001174 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001175 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001176 const uint32_t addr_byte_size = GetAddressByteSize();
1177 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001178 if (!success)
1179 return false;
1180 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001181 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001182 uint32_t imm32; // stack offset
1183 uint32_t regs; // number of registers
1184 switch (encoding) {
1185 case eEncodingT1:
1186 case eEncodingA1:
1187 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001188 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001189 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1190 // If UInt(imm8) is odd, see "FSTMX".
1191 regs = Bits32(opcode, 7, 0) / 2;
1192 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1193 if (regs == 0 || regs > 16 || (d + regs) > 32)
1194 return false;
1195 break;
1196 case eEncodingT2:
1197 case eEncodingA2:
1198 single_regs = true;
1199 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1200 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1201 regs = Bits32(opcode, 7, 0);
1202 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1203 if (regs == 0 || regs > 16 || (d + regs) > 32)
1204 return false;
1205 break;
1206 default:
1207 return false;
1208 }
1209 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1210 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1211 addr_t sp_offset = imm32;
1212 addr_t addr = sp - sp_offset;
1213 uint32_t i;
1214
1215 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1216 for (i=d; i<regs; ++i)
1217 {
1218 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1219 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1220 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001221 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001222 if (!success)
1223 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001224 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001225 return false;
1226 addr += reg_byte_size;
1227 }
1228
1229 context.type = EmulateInstruction::eContextAdjustStackPointer;
1230 context.arg0 = eRegisterKindGeneric;
1231 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001232 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001233
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001234 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001235 return false;
1236 }
1237 return true;
1238}
1239
Johnny Chen587a0a42011-02-01 18:35:28 +00001240// Vector Pop loads multiple extension registers from the stack.
1241// It also updates SP to point just above the loaded data.
1242bool
1243EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1244{
1245#if 0
1246 // ARM pseudo code...
1247 if (ConditionPassed())
1248 {
1249 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1250 address = SP;
1251 SP = SP + imm32;
1252 if single_regs then
1253 for r = 0 to regs-1
1254 S[d+r] = MemA[address,4]; address = address+4;
1255 else
1256 for r = 0 to regs-1
1257 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1258 // Combine the word-aligned words in the correct order for current endianness.
1259 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1260 }
1261#endif
1262
1263 bool success = false;
1264 const uint32_t opcode = OpcodeAsUnsigned (&success);
1265 if (!success)
1266 return false;
1267
1268 if (ConditionPassed())
1269 {
1270 const uint32_t addr_byte_size = GetAddressByteSize();
1271 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1272 if (!success)
1273 return false;
1274 bool single_regs;
1275 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1276 uint32_t imm32; // stack offset
1277 uint32_t regs; // number of registers
1278 switch (encoding) {
1279 case eEncodingT1:
1280 case eEncodingA1:
1281 single_regs = false;
1282 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1283 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1284 // If UInt(imm8) is odd, see "FLDMX".
1285 regs = Bits32(opcode, 7, 0) / 2;
1286 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1287 if (regs == 0 || regs > 16 || (d + regs) > 32)
1288 return false;
1289 break;
1290 case eEncodingT2:
1291 case eEncodingA2:
1292 single_regs = true;
1293 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1294 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1295 regs = Bits32(opcode, 7, 0);
1296 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1297 if (regs == 0 || regs > 16 || (d + regs) > 32)
1298 return false;
1299 break;
1300 default:
1301 return false;
1302 }
1303 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1304 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1305 addr_t sp_offset = imm32;
1306 addr_t addr = sp;
1307 uint32_t i;
1308 uint64_t data; // uint64_t to accomodate 64-bit registers.
1309
1310 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1311 for (i=d; i<regs; ++i)
1312 {
1313 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1314 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1315 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1316 if (!success)
1317 return false;
1318 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1319 return false;
1320 addr += reg_byte_size;
1321 }
1322
1323 context.type = EmulateInstruction::eContextAdjustStackPointer;
1324 context.arg0 = eRegisterKindGeneric;
1325 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1326 context.arg2 = sp_offset;
1327
1328 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1329 return false;
1330 }
1331 return true;
1332}
1333
Johnny Chenb77be412011-02-04 00:40:18 +00001334// SVC (previously SWI)
1335bool
1336EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1337{
1338#if 0
1339 // ARM pseudo code...
1340 if (ConditionPassed())
1341 {
1342 EncodingSpecificOperations();
1343 CallSupervisor();
1344 }
1345#endif
1346
1347 bool success = false;
1348 const uint32_t opcode = OpcodeAsUnsigned (&success);
1349 if (!success)
1350 return false;
1351
1352 if (ConditionPassed())
1353 {
1354 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1355 addr_t lr; // next instruction address
1356 if (!success)
1357 return false;
1358 uint32_t imm32; // the immediate constant
1359 uint32_t mode; // ARM or Thumb mode
1360 switch (encoding) {
1361 case eEncodingT1:
1362 lr = (pc + 2) | 1u; // return address
1363 imm32 = Bits32(opcode, 7, 0);
1364 mode = eModeThumb;
1365 break;
1366 case eEncodingA1:
1367 lr = pc + 4; // return address
1368 imm32 = Bits32(opcode, 23, 0);
1369 mode = eModeARM;
1370 break;
1371 default:
1372 return false;
1373 }
1374 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1375 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1376 return false;
1377 }
1378 return true;
1379}
1380
Johnny Chenc315f862011-02-05 00:46:10 +00001381// If Then makes up to four following instructions (the IT block) conditional.
1382bool
1383EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1384{
1385#if 0
1386 // ARM pseudo code...
1387 EncodingSpecificOperations();
1388 ITSTATE.IT<7:0> = firstcond:mask;
1389#endif
1390
1391 bool success = false;
1392 const uint32_t opcode = OpcodeAsUnsigned (&success);
1393 if (!success)
1394 return false;
1395
1396 m_it_session.InitIT(Bits32(opcode, 7, 0));
1397 return true;
1398}
1399
Johnny Chen3b620b32011-02-07 20:11:47 +00001400// Branch causes a branch to a target address.
1401bool
1402EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1403{
1404#if 0
1405 // ARM pseudo code...
1406 if (ConditionPassed())
1407 {
1408 EncodingSpecificOperations();
1409 BranchWritePC(PC + imm32);
1410 }
1411#endif
1412
1413 bool success = false;
1414 const uint32_t opcode = OpcodeAsUnsigned (&success);
1415 if (!success)
1416 return false;
1417
Johnny Chen9ee056b2011-02-08 00:06:35 +00001418 if (ConditionPassed())
1419 {
1420 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1421 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1422 addr_t target; // target address
1423 if (!success)
1424 return false;
1425 int32_t imm32; // PC-relative offset
1426 switch (encoding) {
1427 case eEncodingT1:
1428 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1429 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1430 target = pc + 4 + imm32;
1431 context.arg1 = 4 + imm32; // signed offset
1432 context.arg2 = eModeThumb; // target instruction set
1433 break;
1434 case eEncodingT2:
1435 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1436 target = pc + 4 + imm32;
1437 context.arg1 = 4 + imm32; // signed offset
1438 context.arg2 = eModeThumb; // target instruction set
1439 break;
1440 case eEncodingT3:
1441 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1442 {
1443 uint32_t S = Bits32(opcode, 26, 26);
1444 uint32_t imm6 = Bits32(opcode, 21, 16);
1445 uint32_t J1 = Bits32(opcode, 13, 13);
1446 uint32_t J2 = Bits32(opcode, 11, 11);
1447 uint32_t imm11 = Bits32(opcode, 10, 0);
1448 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) + (imm11 << 1);
1449 imm32 = llvm::SignExtend32<21>(imm21);
1450 target = pc + 4 + imm32;
1451 context.arg1 = eModeThumb; // target instruction set
1452 context.arg2 = 4 + imm32; // signed offset
1453 break;
1454 }
1455 case eEncodingT4:
1456 {
1457 uint32_t S = Bits32(opcode, 26, 26);
1458 uint32_t imm10 = Bits32(opcode, 25, 16);
1459 uint32_t J1 = Bits32(opcode, 13, 13);
1460 uint32_t J2 = Bits32(opcode, 11, 11);
1461 uint32_t imm11 = Bits32(opcode, 10, 0);
1462 uint32_t I1 = !(J1 ^ S);
1463 uint32_t I2 = !(J2 ^ S);
1464 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
1465 imm32 = llvm::SignExtend32<25>(imm25);
1466 target = pc + 4 + imm32;
1467 context.arg1 = eModeThumb; // target instruction set
1468 context.arg2 = 4 + imm32; // signed offset
1469 break;
1470 }
1471 case eEncodingA1:
1472 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1473 target = pc + 8 + imm32;
1474 context.arg1 = eModeARM; // target instruction set
1475 context.arg2 = 8 + imm32; // signed offset
1476 break;
1477 default:
1478 return false;
1479 }
1480 if (!BranchWritePC(context, target))
1481 return false;
1482 }
1483 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001484}
1485
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001486EmulateInstructionARM::ARMOpcode*
1487EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001488{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001489 static ARMOpcode
1490 g_arm_opcodes[] =
1491 {
1492 //----------------------------------------------------------------------
1493 // Prologue instructions
1494 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001495
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001496 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001497 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1498 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001499
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001500 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001501 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1502 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001503 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001504 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1505 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1506 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001507
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001508 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001509 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001510
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001511 // push one register
1512 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001513 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001514
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001515 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001516 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1517 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001518
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001519 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001520 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001521 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001522
Johnny Chen9b8d7832011-02-02 01:13:56 +00001523 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1524 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1525 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1526 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001527 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1528 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001529 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001530 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1531
1532 //----------------------------------------------------------------------
1533 // Supervisor Call (previously Software Interrupt)
1534 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001535 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1536
1537 //----------------------------------------------------------------------
1538 // Branch instructions
1539 //----------------------------------------------------------------------
1540 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"}
Johnny Chenb77be412011-02-04 00:40:18 +00001541
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001542 };
1543 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1544
1545 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1546 {
1547 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1548 return &g_arm_opcodes[i];
1549 }
1550 return NULL;
1551}
Greg Clayton64c84432011-01-21 22:02:52 +00001552
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001553
1554EmulateInstructionARM::ARMOpcode*
1555EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001556{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001557
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001558 static ARMOpcode
1559 g_thumb_opcodes[] =
1560 {
1561 //----------------------------------------------------------------------
1562 // Prologue instructions
1563 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001564
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001565 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001566 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001567 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1568 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001569 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001570 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001571
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001572 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001573 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1574 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001575
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001576 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001577 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001578
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001579 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001580 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
1581 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001582 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
1583 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001584
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001585 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00001586 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1587 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00001588
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001589 //----------------------------------------------------------------------
1590 // Epilogue instructions
1591 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00001592
Johnny Chenc28a76d2011-02-01 18:51:48 +00001593 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001594 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
1595 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00001596 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1597 // J1 == J2 == 1
1598 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001599 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00001600 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
1601 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
1602 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
1603 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001604
1605 //----------------------------------------------------------------------
1606 // Supervisor Call (previously Software Interrupt)
1607 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00001608 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
1609
1610 //----------------------------------------------------------------------
1611 // If Then makes up to four following instructions conditional.
1612 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001613 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
1614
1615 //----------------------------------------------------------------------
1616 // Branch instructions
1617 //----------------------------------------------------------------------
1618 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
1619 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
1620 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00001621 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
1622 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"}
Johnny Chenb77be412011-02-04 00:40:18 +00001623
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001624 };
1625
1626 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
1627 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
1628 {
1629 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
1630 return &g_thumb_opcodes[i];
1631 }
1632 return NULL;
1633}
Greg Clayton64c84432011-01-21 22:02:52 +00001634
Greg Clayton31e2a382011-01-30 20:03:56 +00001635bool
1636EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
1637{
1638 m_arm_isa = 0;
1639 const char *triple_cstr = triple.GetCString();
1640 if (triple_cstr)
1641 {
1642 const char *dash = ::strchr (triple_cstr, '-');
1643 if (dash)
1644 {
1645 std::string arch (triple_cstr, dash);
1646 const char *arch_cstr = arch.c_str();
1647 if (strcasecmp(arch_cstr, "armv4t") == 0)
1648 m_arm_isa = ARMv4T;
1649 else if (strcasecmp(arch_cstr, "armv4") == 0)
1650 m_arm_isa = ARMv4;
1651 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
1652 m_arm_isa = ARMv5TEJ;
1653 else if (strcasecmp(arch_cstr, "armv5te") == 0)
1654 m_arm_isa = ARMv5TE;
1655 else if (strcasecmp(arch_cstr, "armv5t") == 0)
1656 m_arm_isa = ARMv5T;
1657 else if (strcasecmp(arch_cstr, "armv6k") == 0)
1658 m_arm_isa = ARMv6K;
1659 else if (strcasecmp(arch_cstr, "armv6") == 0)
1660 m_arm_isa = ARMv6;
1661 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
1662 m_arm_isa = ARMv6T2;
1663 else if (strcasecmp(arch_cstr, "armv7") == 0)
1664 m_arm_isa = ARMv7;
1665 else if (strcasecmp(arch_cstr, "armv8") == 0)
1666 m_arm_isa = ARMv8;
1667 }
1668 }
1669 return m_arm_isa != 0;
1670}
1671
1672
Greg Clayton64c84432011-01-21 22:02:52 +00001673bool
1674EmulateInstructionARM::ReadInstruction ()
1675{
1676 bool success = false;
1677 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1678 if (success)
1679 {
1680 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1681 if (success)
1682 {
1683 Context read_inst_context = {eContextReadOpcode, 0, 0};
1684 if (m_inst_cpsr & MASK_CPSR_T)
1685 {
1686 m_inst_mode = eModeThumb;
1687 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
1688
1689 if (success)
1690 {
1691 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
1692 {
1693 m_inst.opcode_type = eOpcode16;
1694 m_inst.opcode.inst16 = thumb_opcode;
1695 }
1696 else
1697 {
1698 m_inst.opcode_type = eOpcode32;
1699 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
1700 }
1701 }
1702 }
1703 else
1704 {
1705 m_inst_mode = eModeARM;
1706 m_inst.opcode_type = eOpcode32;
1707 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
1708 }
1709 }
1710 }
1711 if (!success)
1712 {
1713 m_inst_mode = eModeInvalid;
1714 m_inst_pc = LLDB_INVALID_ADDRESS;
1715 }
1716 return success;
1717}
1718
Greg Clayton64c84432011-01-21 22:02:52 +00001719bool
1720EmulateInstructionARM::ConditionPassed ()
1721{
1722 if (m_inst_cpsr == 0)
1723 return false;
1724
1725 const uint32_t cond = CurrentCond ();
1726
1727 if (cond == UINT32_MAX)
1728 return false;
1729
1730 bool result = false;
1731 switch (UnsignedBits(cond, 3, 1))
1732 {
1733 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
1734 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
1735 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
1736 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
1737 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
1738 case 5:
1739 {
1740 bool n = (m_inst_cpsr & MASK_CPSR_N);
1741 bool v = (m_inst_cpsr & MASK_CPSR_V);
1742 result = n == v;
1743 }
1744 break;
1745 case 6:
1746 {
1747 bool n = (m_inst_cpsr & MASK_CPSR_N);
1748 bool v = (m_inst_cpsr & MASK_CPSR_V);
1749 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
1750 }
1751 break;
1752 case 7:
1753 result = true;
1754 break;
1755 }
1756
1757 if (cond & 1)
1758 result = !result;
1759 return result;
1760}
1761
Johnny Chen9ee056b2011-02-08 00:06:35 +00001762uint32_t
1763EmulateInstructionARM::CurrentCond ()
1764{
1765 switch (m_inst_mode)
1766 {
1767 default:
1768 case eModeInvalid:
1769 break;
1770
1771 case eModeARM:
1772 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
1773
1774 case eModeThumb:
1775 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
1776 // 'cond' field of the encoding.
1777 if (m_inst.opcode_type == eOpcode16 &&
1778 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
1779 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
1780 {
1781 return Bits32(m_inst.opcode.inst16, 11, 7);
1782 }
1783 else if (m_inst.opcode_type == eOpcode32 &&
1784 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
1785 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
1786 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
1787 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
1788 {
1789 return Bits32(m_inst.opcode.inst32, 25, 22);
1790 }
1791
1792 return m_it_session.GetCond();
1793 }
1794 return UINT32_MAX; // Return invalid value
1795}
1796
1797// API client must pass in a context whose arg2 field contains the target instruction set.
1798bool
1799EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
1800{
1801 addr_t target;
1802
1803 // Chech the target instruction set.
1804 switch (context.arg2)
1805 {
1806 default:
1807 assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
1808 return false;
1809 case eModeARM:
1810 target = addr & 0xfffffffc;
1811 break;
1812 case eModeThumb:
1813 target = addr & 0xfffffffe;
1814 break;
1815 }
1816 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1817 return false;
1818 return false;
1819}
1820
1821// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
1822bool
1823EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
1824{
1825 addr_t target;
1826
1827 if (BitIsSet(addr, 0))
1828 {
1829 target = addr & 0xfffffffe;
1830 context.arg2 = eModeThumb;
1831 }
1832 else if (BitIsClear(addr, 1))
1833 {
1834 target = addr & 0xfffffffc;
1835 context.arg2 = eModeARM;
1836 }
1837 else
1838 return false; // address<1:0> == '10' => UNPREDICTABLE
1839
1840 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1841 return false;
1842 return false;
1843}
Greg Clayton64c84432011-01-21 22:02:52 +00001844
1845bool
1846EmulateInstructionARM::EvaluateInstruction ()
1847{
Johnny Chenc315f862011-02-05 00:46:10 +00001848 // Advance the ITSTATE bits to their values for the next instruction.
1849 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
1850 m_it_session.ITAdvance();
1851
Greg Clayton64c84432011-01-21 22:02:52 +00001852 return false;
1853}