blob: 93f004a1c947ddc1157352edcba10150f1177517 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000011#include "lldb/Core/ConstString.h"
12
Greg Claytonf29a08f2011-02-09 17:41:27 +000013#include "Plugins/Process/Utility/ARMDefines.h"
14#include "Plugins/Process/Utility/ARMUtils.h"
15#include "Utility/ARM_DWARF_Registers.h"
16
Johnny Chen9b8d7832011-02-02 01:13:56 +000017#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000018 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000019
20using namespace lldb;
21using namespace lldb_private;
22
Johnny Chend6c13f02011-02-08 20:36:34 +000023static inline uint32_t Align(uint32_t val, uint32_t alignment)
24{
25 return alignment * (val / alignment);
26}
27
Johnny Chen93070472011-02-04 23:02:47 +000028// A8.6.50
29// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
30static unsigned short CountITSize(unsigned ITMask) {
31 // First count the trailing zeros of the IT mask.
32 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
33 if (TZ > 3)
34 {
35 printf("Encoding error: IT Mask '0000'\n");
36 return 0;
37 }
38 return (4 - TZ);
39}
40
41// Init ITState. Note that at least one bit is always 1 in mask.
42bool ITSession::InitIT(unsigned short bits7_0)
43{
44 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
45 if (ITCounter == 0)
46 return false;
47
48 // A8.6.50 IT
49 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
50 if (FirstCond == 0xF)
51 {
52 printf("Encoding error: IT FirstCond '1111'\n");
53 return false;
54 }
55 if (FirstCond == 0xE && ITCounter != 1)
56 {
57 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
58 return false;
59 }
60
61 ITState = bits7_0;
62 return true;
63}
64
65// Update ITState if necessary.
66void ITSession::ITAdvance()
67{
68 assert(ITCounter);
69 --ITCounter;
70 if (ITCounter == 0)
71 ITState = 0;
72 else
73 {
74 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
75 SetBits32(ITState, 4, 0, NewITState4_0);
76 }
77}
78
79// Return true if we're inside an IT Block.
80bool ITSession::InITBlock()
81{
82 return ITCounter != 0;
83}
84
Johnny Chenc315f862011-02-05 00:46:10 +000085// Return true if we're the last instruction inside an IT Block.
86bool ITSession::LastInITBlock()
87{
88 return ITCounter == 1;
89}
90
Johnny Chen93070472011-02-04 23:02:47 +000091// Get condition bits for the current thumb instruction.
92uint32_t ITSession::GetCond()
93{
Johnny Chenc315f862011-02-05 00:46:10 +000094 if (InITBlock())
95 return Bits32(ITState, 7, 4);
96 else
97 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000098}
99
Greg Clayton64c84432011-01-21 22:02:52 +0000100// ARM constants used during decoding
101#define REG_RD 0
102#define LDM_REGLIST 1
103#define PC_REG 15
104#define PC_REGLIST_BIT 0x8000
105
Johnny Chen251af6a2011-01-21 22:47:25 +0000106#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000107#define ARMv4T (1u << 1)
108#define ARMv5T (1u << 2)
109#define ARMv5TE (1u << 3)
110#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000111#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000112#define ARMv6K (1u << 6)
113#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000115#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000116#define ARMvAll (0xffffffffu)
117
Johnny Chen9b8d7832011-02-02 01:13:56 +0000118#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
119#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
120#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000121
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000122void
123EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000124{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000125}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000126
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000127void
128EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000129{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000130}
131
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 Chen7c1bf922011-02-08 23:49:37 +0000225 if (BitIsSet (registers, 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 Chen7c1bf922011-02-08 23:49:37 +0000238 if (BitIsSet (registers, 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 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000349 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000350 {
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
Johnny Chen7c1bf922011-02-08 23:49:37 +0000362 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000363 {
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);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000769 if (!success)
770 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000771 addr_t lr; // next instruction address
772 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000773 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);
Johnny Chen53ebab72011-02-08 23:21:57 +0000785 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000786 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);
Johnny Chen53ebab72011-02-08 23:21:57 +0000802 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000803 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);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001422 if (!success)
1423 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001424 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001425 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);
Johnny Chen53ebab72011-02-08 23:21:57 +00001448 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001449 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);
Johnny Chen53ebab72011-02-08 23:21:57 +00001464 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001465 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
Johnny Chen53ebab72011-02-08 23:21:57 +00001486// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1487// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1488// CBNZ, CBZ
1489bool
1490EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1491{
1492#if 0
1493 // ARM pseudo code...
1494 EncodingSpecificOperations();
1495 if nonzero ^ IsZero(R[n]) then
1496 BranchWritePC(PC + imm32);
1497#endif
1498
1499 bool success = false;
1500 const uint32_t opcode = OpcodeAsUnsigned (&success);
1501 if (!success)
1502 return false;
1503
1504 // Read the register value from the operand register Rn.
1505 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1506 if (!success)
1507 return false;
1508
1509 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1510 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1511 if (!success)
1512 return false;
1513
1514 addr_t target; // target address
1515 uint32_t imm32; // PC-relative offset to branch forward
1516 bool nonzero;
1517 switch (encoding) {
1518 case eEncodingT1:
1519 imm32 = Bits32(opcode, 9, 9) << 6 | Bits32(opcode, 7, 3) << 1;
1520 nonzero = BitIsSet(opcode, 11);
1521 target = pc + 4 + imm32;
1522 context.arg1 = 4 + imm32; // signed offset
1523 context.arg2 = eModeThumb; // target instruction set
1524 break;
1525 default:
1526 return false;
1527 }
1528 if (nonzero ^ (reg_val == 0))
1529 if (!BranchWritePC(context, target))
1530 return false;
1531
1532 return true;
1533}
1534
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001535// LDM loads multiple registers from consecutive memory locations, using an
1536// address from a base register. Optionally the addres just above the highest of those locations
1537// can be written back to the base register.
1538bool
1539EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1540{
1541#if 0
1542 // ARM pseudo code...
1543 if ConditionPassed()
1544 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1545 address = R[n];
1546
1547 for i = 0 to 14
1548 if registers<i> == '1' then
1549 R[i] = MemA[address, 4]; address = address + 4;
1550 if registers<15> == '1' then
1551 LoadWritePC (MemA[address, 4]);
1552
1553 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1554 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1555
1556#endif
1557
1558 bool success = false;
1559 const uint32_t opcode = OpcodeAsUnsigned (&success);
1560 if (!success)
1561 return false;
1562
1563 if (ConditionPassed())
1564 {
1565 uint32_t n;
1566 uint32_t registers = 0;
1567 bool wback;
1568 const uint32_t addr_byte_size = GetAddressByteSize();
1569 switch (encoding)
1570 {
1571 case eEncodingT1:
1572 n = Bits32 (opcode, 10, 8);
1573 registers = Bits32 (opcode, 7, 0);
1574 wback = BitIsClear (registers, n);
1575 // if BitCount(registers) < 1 then UNPREDICTABLE;
1576 if (BitCount(registers) < 1)
1577 return false;
1578 break;
1579 case eEncodingT2:
1580 n = Bits32 (opcode, 19, 16);
1581 registers = Bits32 (opcode, 15, 0);
1582 wback = BitIsSet (opcode, 21);
1583 if ((n == 15)
1584 || (BitCount (registers) < 2)
1585 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1586 return false;
1587 if (BitIsSet (registers, 15)
1588 && m_it_session.InITBlock()
1589 && !m_it_session.LastInITBlock())
1590 return false;
1591 if (wback
1592 && BitIsSet (registers, n))
1593 return false;
1594 break;
1595 case eEncodingA1:
1596 n = Bits32 (opcode, 19, 16);
1597 registers = Bits32 (opcode, 15, 0);
1598 wback = BitIsSet (opcode, 21);
1599 if ((n == 15)
1600 || (BitCount (registers) < 1))
1601 return false;
1602 break;
1603 default:
1604 return false;
1605 }
1606
1607 int32_t offset = 0;
1608 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1609 if (!success)
1610 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001611
1612 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1613 eRegisterKindDWARF,
1614 dwarf_r0 + n,
1615 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001616
1617 for (int i = 0; i < 14; ++i)
1618 {
1619 if (BitIsSet (registers, i))
1620 {
Caroline Tice85aab332011-02-08 23:56:10 +00001621 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1622 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001623 if (wback && (n == 13)) // Pop Instruction
1624 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1625
1626 // R[i] = MemA [address, 4]; address = address + 4;
1627 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1628 if (!success)
1629 return false;
1630
1631 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1632 return false;
1633
1634 offset += addr_byte_size;
1635 }
1636 }
1637
1638 if (BitIsSet (registers, 15))
1639 {
1640 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001641 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1642 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001643 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1644 if (!success)
1645 return false;
1646 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1647 return false;
1648 }
1649
1650 if (wback && BitIsClear (registers, n))
1651 {
1652 addr_t offset = addr_byte_size * BitCount (registers);
Caroline Tice85aab332011-02-08 23:56:10 +00001653 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1654 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001655
1656 // R[n] = R[n] + 4 * BitCount (registers)
1657 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1658 return false;
1659 }
1660 if (wback && BitIsSet (registers, n))
1661 // R[n] bits(32) UNKNOWN;
1662 return false; //I'm not convinced this is the right thing to do here...
1663 }
1664 return true;
1665}
1666
Caroline Tice0b29e242011-02-08 23:16:02 +00001667bool
1668EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1669{
1670#if 0
1671 // ARM pseudo code...
1672 if ConditionPassed() then
1673 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1674 address = R[n] - 4*BitCount(registers);
1675
1676 for i = 0 to 14
1677 if registers<i> == ’1’ then
1678 R[i] = MemA[address,4]; address = address + 4;
1679 if registers<15> == ’1’ then
1680 LoadWritePC(MemA[address,4]);
1681
1682 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1683 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1684#endif
1685
1686 bool success = false;
1687 const uint32_t opcode = OpcodeAsUnsigned (&success);
1688 if (!success)
1689 return false;
1690
1691 if (ConditionPassed())
1692 {
1693 uint32_t n;
1694 uint32_t registers = 0;
1695 bool wback;
1696 const uint32_t addr_byte_size = GetAddressByteSize();
1697 switch (encoding)
1698 {
1699 case eEncodingT1:
1700 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1701 n = Bits32 (opcode, 19, 16);
1702 registers = Bits32 (opcode, 15, 0);
1703 wback = BitIsSet (opcode, 21);
1704
1705 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1706 if ((n == 15)
1707 || (BitCount (registers) < 2)
1708 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1709 return false;
1710
1711 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1712 if (BitIsSet (registers, 15)
1713 && m_it_session.InITBlock()
1714 && !m_it_session.LastInITBlock())
1715 return false;
1716
1717 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1718 if (wback && BitIsSet (registers, n))
1719 return false;
1720
1721 break;
1722
1723 case eEncodingA1:
1724 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1725 n = Bits32 (opcode, 19, 16);
1726 registers = Bits32 (opcode, 15, 0);
1727 wback = BitIsSet (opcode, 21);
1728
1729 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1730 if ((n == 15) || (BitCount (registers) < 1))
1731 return false;
1732
1733 break;
1734
1735 default:
1736 return false;
1737 }
1738
1739 int32_t offset = 0;
1740 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1741 - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00001742 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1743 eRegisterKindDWARF,
1744 dwarf_r0 + n,
1745 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00001746
1747 for (int i = 0; i < 14; ++i)
1748 {
1749 if (BitIsSet (registers, i))
1750 {
1751 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00001752 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001753 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1754 if (!success)
1755 return false;
1756
1757 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1758 return false;
1759
1760 offset += addr_byte_size;
1761 }
1762 }
1763
1764 // if registers<15> == ’1’ then
1765 // LoadWritePC(MemA[address,4]);
1766 if (BitIsSet (registers, 15))
1767 {
Caroline Tice85aab332011-02-08 23:56:10 +00001768 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001769 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1770 if (!success)
1771 return false;
1772 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1773 return false;
1774 }
1775
1776 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1777 if (wback && BitIsClear (registers, n))
1778 {
Caroline Tice85aab332011-02-08 23:56:10 +00001779 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001780 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1781 if (!success)
1782 return false;
1783 addr = addr - (addr_byte_size * BitCount (registers));
1784 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1785 return false;
1786 }
1787
1788 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1789 if (wback && BitIsSet (registers, n))
1790 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1791 }
1792 return true;
1793}
Caroline Tice85aab332011-02-08 23:56:10 +00001794
1795bool
1796EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
1797{
1798#if 0
1799 if ConditionPassed() then
1800 EncodingSpecificOperations();
1801 address = R[n] + 4;
1802
1803 for i = 0 to 14
1804 if registers<i> == ’1’ then
1805 R[i] = MemA[address,4]; address = address + 4;
1806 if registers<15> == ’1’ then
1807 LoadWritePC(MemA[address,4]);
1808
1809 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1810 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
1811#endif
1812
1813 bool success = false;
1814 const uint32_t opcode = OpcodeAsUnsigned (&success);
1815 if (!success)
1816 return false;
1817
1818 if (ConditionPassed())
1819 {
1820 uint32_t n;
1821 uint32_t registers = 0;
1822 bool wback;
1823 const uint32_t addr_byte_size = GetAddressByteSize();
1824 switch (encoding)
1825 {
1826 case eEncodingA1:
1827 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1828 n = Bits32 (opcode, 19, 16);
1829 registers = Bits32 (opcode, 15, 0);
1830 wback = BitIsSet (opcode, 21);
1831
1832 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1833 if ((n == 15) || (BitCount (registers) < 1))
1834 return false;
1835
1836 break;
1837 default:
1838 return false;
1839 }
1840 // address = R[n] + 4;
1841
1842 int32_t offset = 0;
1843 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success) + addr_byte_size;
1844
1845 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1846 eRegisterKindDWARF,
1847 dwarf_r0 + n,
1848 offset };
1849
1850 for (int i = 0; i < 14; ++i)
1851 {
1852 if (BitIsSet (registers, i))
1853 {
1854 // R[i] = MemA[address,4]; address = address + 4;
1855
1856 context.arg2 = offset;
1857 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1858 if (!success)
1859 return false;
1860
1861 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1862 return false;
1863
1864 offset += addr_byte_size;
1865 }
1866 }
1867
1868 // if registers<15> == ’1’ then
1869 // LoadWritePC(MemA[address,4]);
1870 if (BitIsSet (registers, 15))
1871 {
1872 context.arg2 = offset;
1873 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1874 if (!success)
1875 return false;
1876 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1877 return false;
1878 }
1879
1880 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1881 if (wback && BitIsClear (registers, n))
1882 {
1883 context.arg2 = offset;
1884 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1885 if (!success)
1886 return false;
1887 addr = addr + (addr_byte_size * BitCount (registers));
1888 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1889 return false;
1890 }
1891
1892 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1893 if (wback && BitIsSet (registers, n))
1894 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1895 }
1896 return true;
1897}
Caroline Tice0b29e242011-02-08 23:16:02 +00001898
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001899EmulateInstructionARM::ARMOpcode*
1900EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001901{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001902 static ARMOpcode
1903 g_arm_opcodes[] =
1904 {
1905 //----------------------------------------------------------------------
1906 // Prologue instructions
1907 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001908
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001909 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001910 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1911 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001912
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001913 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001914 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1915 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001916 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001917 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1918 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1919 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001920
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001921 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001922 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001923
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001924 // push one register
1925 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001926 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001927
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001928 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001929 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1930 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001931
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001932 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001933 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001934 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001935
Johnny Chen9b8d7832011-02-02 01:13:56 +00001936 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1937 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1938 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1939 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001940 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1941 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001942 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001943 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1944
1945 //----------------------------------------------------------------------
1946 // Supervisor Call (previously Software Interrupt)
1947 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001948 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1949
1950 //----------------------------------------------------------------------
1951 // Branch instructions
1952 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001953 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00001954
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001955 //----------------------------------------------------------------------
1956 // Load instructions
1957 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00001958 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00001959 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
1960 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001961
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001962 };
1963 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1964
1965 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1966 {
1967 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1968 return &g_arm_opcodes[i];
1969 }
1970 return NULL;
1971}
Greg Clayton64c84432011-01-21 22:02:52 +00001972
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001973
1974EmulateInstructionARM::ARMOpcode*
1975EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001976{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001977
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001978 static ARMOpcode
1979 g_thumb_opcodes[] =
1980 {
1981 //----------------------------------------------------------------------
1982 // Prologue instructions
1983 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001984
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001985 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001986 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001987 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1988 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001989 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001990 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001991
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001992 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001993 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1994 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001995
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001996 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001997 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001998
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001999 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002000 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2001 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002002 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2003 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002004
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002005 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002006 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2007 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002008
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002009 //----------------------------------------------------------------------
2010 // Epilogue instructions
2011 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002012
Johnny Chenc28a76d2011-02-01 18:51:48 +00002013 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002014 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
2015 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00002016 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2017 // J1 == J2 == 1
2018 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002019 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002020 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2021 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2022 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2023 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002024
2025 //----------------------------------------------------------------------
2026 // Supervisor Call (previously Software Interrupt)
2027 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002028 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2029
2030 //----------------------------------------------------------------------
2031 // If Then makes up to four following instructions conditional.
2032 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002033 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2034
2035 //----------------------------------------------------------------------
2036 // Branch instructions
2037 //----------------------------------------------------------------------
2038 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2039 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2040 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002041 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002042 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002043 // compare and branch
2044 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002045
2046 //----------------------------------------------------------------------
2047 // Load instructions
2048 //----------------------------------------------------------------------
2049 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002050 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
2051 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002052
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002053 };
2054
2055 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2056 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2057 {
2058 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2059 return &g_thumb_opcodes[i];
2060 }
2061 return NULL;
2062}
Greg Clayton64c84432011-01-21 22:02:52 +00002063
Greg Clayton31e2a382011-01-30 20:03:56 +00002064bool
2065EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2066{
2067 m_arm_isa = 0;
2068 const char *triple_cstr = triple.GetCString();
2069 if (triple_cstr)
2070 {
2071 const char *dash = ::strchr (triple_cstr, '-');
2072 if (dash)
2073 {
2074 std::string arch (triple_cstr, dash);
2075 const char *arch_cstr = arch.c_str();
2076 if (strcasecmp(arch_cstr, "armv4t") == 0)
2077 m_arm_isa = ARMv4T;
2078 else if (strcasecmp(arch_cstr, "armv4") == 0)
2079 m_arm_isa = ARMv4;
2080 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2081 m_arm_isa = ARMv5TEJ;
2082 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2083 m_arm_isa = ARMv5TE;
2084 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2085 m_arm_isa = ARMv5T;
2086 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2087 m_arm_isa = ARMv6K;
2088 else if (strcasecmp(arch_cstr, "armv6") == 0)
2089 m_arm_isa = ARMv6;
2090 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2091 m_arm_isa = ARMv6T2;
2092 else if (strcasecmp(arch_cstr, "armv7") == 0)
2093 m_arm_isa = ARMv7;
2094 else if (strcasecmp(arch_cstr, "armv8") == 0)
2095 m_arm_isa = ARMv8;
2096 }
2097 }
2098 return m_arm_isa != 0;
2099}
2100
2101
Greg Clayton64c84432011-01-21 22:02:52 +00002102bool
2103EmulateInstructionARM::ReadInstruction ()
2104{
2105 bool success = false;
2106 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2107 if (success)
2108 {
2109 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2110 if (success)
2111 {
2112 Context read_inst_context = {eContextReadOpcode, 0, 0};
2113 if (m_inst_cpsr & MASK_CPSR_T)
2114 {
2115 m_inst_mode = eModeThumb;
2116 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2117
2118 if (success)
2119 {
2120 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2121 {
2122 m_inst.opcode_type = eOpcode16;
2123 m_inst.opcode.inst16 = thumb_opcode;
2124 }
2125 else
2126 {
2127 m_inst.opcode_type = eOpcode32;
2128 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2129 }
2130 }
2131 }
2132 else
2133 {
2134 m_inst_mode = eModeARM;
2135 m_inst.opcode_type = eOpcode32;
2136 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2137 }
2138 }
2139 }
2140 if (!success)
2141 {
2142 m_inst_mode = eModeInvalid;
2143 m_inst_pc = LLDB_INVALID_ADDRESS;
2144 }
2145 return success;
2146}
2147
Johnny Chenee9b1f72011-02-09 01:00:31 +00002148uint32_t
2149EmulateInstructionARM::ArchVersion ()
2150{
2151 return m_arm_isa;
2152}
2153
Greg Clayton64c84432011-01-21 22:02:52 +00002154bool
2155EmulateInstructionARM::ConditionPassed ()
2156{
2157 if (m_inst_cpsr == 0)
2158 return false;
2159
2160 const uint32_t cond = CurrentCond ();
2161
2162 if (cond == UINT32_MAX)
2163 return false;
2164
2165 bool result = false;
2166 switch (UnsignedBits(cond, 3, 1))
2167 {
2168 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2169 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2170 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2171 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2172 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2173 case 5:
2174 {
2175 bool n = (m_inst_cpsr & MASK_CPSR_N);
2176 bool v = (m_inst_cpsr & MASK_CPSR_V);
2177 result = n == v;
2178 }
2179 break;
2180 case 6:
2181 {
2182 bool n = (m_inst_cpsr & MASK_CPSR_N);
2183 bool v = (m_inst_cpsr & MASK_CPSR_V);
2184 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2185 }
2186 break;
2187 case 7:
2188 result = true;
2189 break;
2190 }
2191
2192 if (cond & 1)
2193 result = !result;
2194 return result;
2195}
2196
Johnny Chen9ee056b2011-02-08 00:06:35 +00002197uint32_t
2198EmulateInstructionARM::CurrentCond ()
2199{
2200 switch (m_inst_mode)
2201 {
2202 default:
2203 case eModeInvalid:
2204 break;
2205
2206 case eModeARM:
2207 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2208
2209 case eModeThumb:
2210 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2211 // 'cond' field of the encoding.
2212 if (m_inst.opcode_type == eOpcode16 &&
2213 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2214 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2215 {
2216 return Bits32(m_inst.opcode.inst16, 11, 7);
2217 }
2218 else if (m_inst.opcode_type == eOpcode32 &&
2219 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2220 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2221 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2222 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2223 {
2224 return Bits32(m_inst.opcode.inst32, 25, 22);
2225 }
2226
2227 return m_it_session.GetCond();
2228 }
2229 return UINT32_MAX; // Return invalid value
2230}
2231
Johnny Chen9ee056b2011-02-08 00:06:35 +00002232bool
2233EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2234{
2235 addr_t target;
2236
Johnny Chenee9b1f72011-02-09 01:00:31 +00002237 // Check the current instruction set.
2238 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00002239 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002240 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00002241 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002242
Johnny Chen9ee056b2011-02-08 00:06:35 +00002243 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002244 return false;
2245
2246 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002247}
2248
2249// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2250bool
2251EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2252{
2253 addr_t target;
2254
2255 if (BitIsSet(addr, 0))
2256 {
Johnny Chenee9b1f72011-02-09 01:00:31 +00002257 SelectInstrSet(eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002258 target = addr & 0xfffffffe;
2259 context.arg2 = eModeThumb;
2260 }
2261 else if (BitIsClear(addr, 1))
2262 {
Johnny Chenee9b1f72011-02-09 01:00:31 +00002263 SelectInstrSet(eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002264 target = addr & 0xfffffffc;
2265 context.arg2 = eModeARM;
2266 }
2267 else
2268 return false; // address<1:0> == '10' => UNPREDICTABLE
2269
2270 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002271 return false;
2272
2273 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002274}
Greg Clayton64c84432011-01-21 22:02:52 +00002275
Johnny Chenee9b1f72011-02-09 01:00:31 +00002276// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
2277bool
2278EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
2279{
2280 if (ArchVersion() >= ARMv5T)
2281 return BXWritePC(context, addr);
2282 else
2283 return BranchWritePC((const Context)context, addr);
2284}
2285
2286EmulateInstructionARM::Mode
2287EmulateInstructionARM::CurrentInstrSet ()
2288{
2289 return m_inst_mode;
2290}
2291
2292// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
2293// ReadInstruction() is performed.
2294bool
2295EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
2296{
2297 switch (arm_or_thumb)
2298 {
2299 default:
2300 return false;
2301 eModeARM:
2302 // Clear the T bit.
2303 m_inst_cpsr &= ~MASK_CPSR_T;
2304 break;
2305 eModeThumb:
2306 // Set the T bit.
2307 m_inst_cpsr |= MASK_CPSR_T;
2308 break;
2309 }
2310 return true;
2311}
2312
Greg Clayton64c84432011-01-21 22:02:52 +00002313bool
2314EmulateInstructionARM::EvaluateInstruction ()
2315{
Johnny Chenc315f862011-02-05 00:46:10 +00002316 // Advance the ITSTATE bits to their values for the next instruction.
2317 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2318 m_it_session.ITAdvance();
2319
Greg Clayton64c84432011-01-21 22:02:52 +00002320 return false;
2321}