blob: af2f361d4d576655618399695b4342c60e8de66a [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000011#include "lldb/Core/ConstString.h"
12
Johnny Chen8584c922011-01-26 01:18:52 +000013#include "ARMDefines.h"
Johnny Chen4baf2e32011-01-24 18:24:53 +000014#include "ARMUtils.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000015#include "ARM_DWARF_Registers.h"
Johnny Chen9b8d7832011-02-02 01:13:56 +000016#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000017 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000018
19using namespace lldb;
20using namespace lldb_private;
21
Johnny Chend6c13f02011-02-08 20:36:34 +000022static inline uint32_t Align(uint32_t val, uint32_t alignment)
23{
24 return alignment * (val / alignment);
25}
26
Johnny Chen93070472011-02-04 23:02:47 +000027// A8.6.50
28// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
29static unsigned short CountITSize(unsigned ITMask) {
30 // First count the trailing zeros of the IT mask.
31 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
32 if (TZ > 3)
33 {
34 printf("Encoding error: IT Mask '0000'\n");
35 return 0;
36 }
37 return (4 - TZ);
38}
39
40// Init ITState. Note that at least one bit is always 1 in mask.
41bool ITSession::InitIT(unsigned short bits7_0)
42{
43 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
44 if (ITCounter == 0)
45 return false;
46
47 // A8.6.50 IT
48 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
49 if (FirstCond == 0xF)
50 {
51 printf("Encoding error: IT FirstCond '1111'\n");
52 return false;
53 }
54 if (FirstCond == 0xE && ITCounter != 1)
55 {
56 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
57 return false;
58 }
59
60 ITState = bits7_0;
61 return true;
62}
63
64// Update ITState if necessary.
65void ITSession::ITAdvance()
66{
67 assert(ITCounter);
68 --ITCounter;
69 if (ITCounter == 0)
70 ITState = 0;
71 else
72 {
73 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
74 SetBits32(ITState, 4, 0, NewITState4_0);
75 }
76}
77
78// Return true if we're inside an IT Block.
79bool ITSession::InITBlock()
80{
81 return ITCounter != 0;
82}
83
Johnny Chenc315f862011-02-05 00:46:10 +000084// Return true if we're the last instruction inside an IT Block.
85bool ITSession::LastInITBlock()
86{
87 return ITCounter == 1;
88}
89
Johnny Chen93070472011-02-04 23:02:47 +000090// Get condition bits for the current thumb instruction.
91uint32_t ITSession::GetCond()
92{
Johnny Chenc315f862011-02-05 00:46:10 +000093 if (InITBlock())
94 return Bits32(ITState, 7, 4);
95 else
96 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +000097}
98
Greg Clayton64c84432011-01-21 22:02:52 +000099// ARM constants used during decoding
100#define REG_RD 0
101#define LDM_REGLIST 1
102#define PC_REG 15
103#define PC_REGLIST_BIT 0x8000
104
Johnny Chen251af6a2011-01-21 22:47:25 +0000105#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000106#define ARMv4T (1u << 1)
107#define ARMv5T (1u << 2)
108#define ARMv5TE (1u << 3)
109#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000110#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000111#define ARMv6K (1u << 6)
112#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000113#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000114#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMvAll (0xffffffffu)
116
Johnny Chen9b8d7832011-02-02 01:13:56 +0000117#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
118#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
119#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000120
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000121void
122EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000123{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000124}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000125
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000126void
127EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000128{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000129}
130
Johnny Chen08c25e82011-01-31 18:02:28 +0000131// Push Multiple Registers stores multiple registers to the stack, storing to
132// consecutive memory locations ending just below the address in SP, and updates
133// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000134bool
135EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000136{
137#if 0
138 // ARM pseudo code...
139 if (ConditionPassed())
140 {
141 EncodingSpecificOperations();
142 NullCheckIfThumbEE(13);
143 address = SP - 4*BitCount(registers);
144
145 for (i = 0 to 14)
146 {
147 if (registers<i> == ’1’)
148 {
149 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
150 MemA[address,4] = bits(32) UNKNOWN;
151 else
152 MemA[address,4] = R[i];
153 address = address + 4;
154 }
155 }
156
157 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
158 MemA[address,4] = PCStoreValue();
159
160 SP = SP - 4*BitCount(registers);
161 }
162#endif
163
164 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000165 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000166 if (!success)
167 return false;
168
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000169 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000170 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000171 const uint32_t addr_byte_size = GetAddressByteSize();
172 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000173 if (!success)
174 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000175 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000176 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000177 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000178 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000179 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000180 // The M bit represents LR.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000181 if (Bits32(opcode, 8, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000182 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000183 // if BitCount(registers) < 1 then UNPREDICTABLE;
184 if (BitCount(registers) < 1)
185 return false;
186 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000187 case eEncodingT2:
188 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000189 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000190 // if BitCount(registers) < 2 then UNPREDICTABLE;
191 if (BitCount(registers) < 2)
192 return false;
193 break;
194 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000195 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000196 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000197 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000198 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000199 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000200 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000201 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000202 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000203 // Instead of return false, let's handle the following case as well,
204 // which amounts to pushing one reg onto the full descending stacks.
205 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000206 break;
207 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000208 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000209 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000210 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000211 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000212 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000213 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000214 default:
215 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000216 }
Johnny Chence1ca772011-01-25 01:13:00 +0000217 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 addr_t addr = sp - sp_offset;
219 uint32_t i;
220
221 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
222 for (i=0; i<15; ++i)
223 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000224 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000225 {
226 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
227 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000231 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000232 return false;
233 addr += addr_byte_size;
234 }
235 }
236
Johnny Chen7c1bf922011-02-08 23:49:37 +0000237 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000238 {
239 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000240 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000241 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000242 if (!success)
243 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000244 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000245 return false;
246 }
247
248 context.type = EmulateInstruction::eContextAdjustStackPointer;
249 context.arg0 = eRegisterKindGeneric;
250 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000251 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000252
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000253 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000254 return false;
255 }
256 return true;
257}
258
Johnny Chenef85e912011-01-31 23:07:40 +0000259// Pop Multiple Registers loads multiple registers from the stack, loading from
260// consecutive memory locations staring at the address in SP, and updates
261// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000262bool
263EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000264{
265#if 0
266 // ARM pseudo code...
267 if (ConditionPassed())
268 {
269 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
270 address = SP;
271 for i = 0 to 14
272 if registers<i> == ‘1’ then
273 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
274 if registers<15> == ‘1’ then
275 if UnalignedAllowed then
276 LoadWritePC(MemU[address,4]);
277 else
278 LoadWritePC(MemA[address,4]);
279 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
280 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
281 }
282#endif
283
284 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000286 if (!success)
287 return false;
288
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000289 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000290 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000291 const uint32_t addr_byte_size = GetAddressByteSize();
292 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000293 if (!success)
294 return false;
295 uint32_t registers = 0;
296 uint32_t Rt; // the destination register
297 switch (encoding) {
298 case eEncodingT1:
299 registers = Bits32(opcode, 7, 0);
300 // The P bit represents PC.
301 if (Bits32(opcode, 8, 8))
302 registers |= (1u << 15);
303 // if BitCount(registers) < 1 then UNPREDICTABLE;
304 if (BitCount(registers) < 1)
305 return false;
306 break;
307 case eEncodingT2:
308 // Ignore bit 13.
309 registers = Bits32(opcode, 15, 0) & ~0x2000;
310 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
311 if (BitCount(registers) < 2 || (Bits32(opcode, 15, 15) && Bits32(opcode, 14, 14)))
312 return false;
313 break;
314 case eEncodingT3:
315 Rt = Bits32(opcode, 15, 12);
316 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
317 if (Rt == dwarf_sp)
318 return false;
319 registers = (1u << Rt);
320 break;
321 case eEncodingA1:
322 registers = Bits32(opcode, 15, 0);
323 // Instead of return false, let's handle the following case as well,
324 // which amounts to popping one reg from the full descending stacks.
325 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
326
327 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
328 if (Bits32(opcode, 13, 13))
329 return false;
330 break;
331 case eEncodingA2:
332 Rt = Bits32(opcode, 15, 12);
333 // if t == 13 then UNPREDICTABLE;
334 if (Rt == dwarf_sp)
335 return false;
336 registers = (1u << Rt);
337 break;
338 default:
339 return false;
340 }
341 addr_t sp_offset = addr_byte_size * BitCount (registers);
342 addr_t addr = sp;
343 uint32_t i, data;
344
345 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
346 for (i=0; i<15; ++i)
347 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000348 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000349 {
350 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
351 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000353 if (!success)
354 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000355 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 return false;
357 addr += addr_byte_size;
358 }
359 }
360
Johnny Chen7c1bf922011-02-08 23:49:37 +0000361 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000362 {
363 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
364 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000365 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000366 if (!success)
367 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000368 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
370 addr += addr_byte_size;
371 }
372
373 context.type = EmulateInstruction::eContextAdjustStackPointer;
374 context.arg0 = eRegisterKindGeneric;
375 context.arg1 = LLDB_REGNUM_GENERIC_SP;
376 context.arg2 = sp_offset;
377
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000378 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000379 return false;
380 }
381 return true;
382}
383
Johnny Chen5b442b72011-01-27 19:34:30 +0000384// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000385// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000386bool
387EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000388{
389#if 0
390 // ARM pseudo code...
391 if (ConditionPassed())
392 {
393 EncodingSpecificOperations();
394 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
395 if d == 15 then
396 ALUWritePC(result); // setflags is always FALSE here
397 else
398 R[d] = result;
399 if setflags then
400 APSR.N = result<31>;
401 APSR.Z = IsZeroBit(result);
402 APSR.C = carry;
403 APSR.V = overflow;
404 }
405#endif
406
407 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000408 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000409 if (!success)
410 return false;
411
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000412 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000413 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000415 if (!success)
416 return false;
417 uint32_t Rd; // the destination register
418 uint32_t imm32;
419 switch (encoding) {
420 case eEncodingT1:
421 Rd = 7;
422 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
423 break;
424 case eEncodingA1:
425 Rd = Bits32(opcode, 15, 12);
426 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
427 break;
428 default:
429 return false;
430 }
431 addr_t sp_offset = imm32;
432 addr_t addr = sp + sp_offset; // a pointer to the stack area
433
434 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
435 eRegisterKindGeneric,
436 LLDB_REGNUM_GENERIC_SP,
437 sp_offset };
438
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000440 return false;
441 }
442 return true;
443}
444
Johnny Chen2ccad832011-01-28 19:57:25 +0000445// Set r7 or ip to the current stack pointer.
446// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000447bool
448EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000449{
450#if 0
451 // ARM pseudo code...
452 if (ConditionPassed())
453 {
454 EncodingSpecificOperations();
455 result = R[m];
456 if d == 15 then
457 ALUWritePC(result); // setflags is always FALSE here
458 else
459 R[d] = result;
460 if setflags then
461 APSR.N = result<31>;
462 APSR.Z = IsZeroBit(result);
463 // APSR.C unchanged
464 // APSR.V unchanged
465 }
466#endif
467
468 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000470 //if (!success)
471 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000472
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000474 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000475 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000476 if (!success)
477 return false;
478 uint32_t Rd; // the destination register
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 break;
483 case eEncodingA1:
484 Rd = 12;
485 break;
486 default:
487 return false;
488 }
489 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
490 eRegisterKindGeneric,
491 LLDB_REGNUM_GENERIC_SP,
492 0 };
493
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000495 return false;
496 }
497 return true;
498}
499
Johnny Chen1c13b622011-01-29 00:11:15 +0000500// Move from high register (r8-r15) to low register (r0-r7).
501// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502bool
503EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000504{
505#if 0
506 // ARM pseudo code...
507 if (ConditionPassed())
508 {
509 EncodingSpecificOperations();
510 result = R[m];
511 if d == 15 then
512 ALUWritePC(result); // setflags is always FALSE here
513 else
514 R[d] = result;
515 if setflags then
516 APSR.N = result<31>;
517 APSR.Z = IsZeroBit(result);
518 // APSR.C unchanged
519 // APSR.V unchanged
520 }
521#endif
522
523 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 if (!success)
526 return false;
527
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000528 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000529 {
530 uint32_t Rm; // the source register
531 uint32_t Rd; // the destination register
532 switch (encoding) {
533 case eEncodingT1:
534 Rm = Bits32(opcode, 6, 3);
535 Rd = Bits32(opcode, 2, 1); // bits(7) == 0
536 break;
537 default:
538 return false;
539 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 if (!success)
542 return false;
543
544 // The context specifies that Rm is to be moved into Rd.
545 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
546 eRegisterKindDWARF,
547 dwarf_r0 + Rm,
548 0 };
549
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
Johnny Chen1c13b622011-01-29 00:11:15 +0000551 return false;
552 }
553 return true;
554}
555
Johnny Chen788e0552011-01-27 22:52:23 +0000556// PC relative immediate load into register, possibly followed by ADD (SP plus register).
557// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000558bool
559EmulateInstructionARM::EmulateLDRRdPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000560{
561#if 0
562 // ARM pseudo code...
563 if (ConditionPassed())
564 {
565 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
566 base = Align(PC,4);
567 address = if add then (base + imm32) else (base - imm32);
568 data = MemU[address,4];
569 if t == 15 then
570 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
571 elsif UnalignedSupport() || address<1:0> = ‘00’ then
572 R[t] = data;
573 else // Can only apply before ARMv7
574 if CurrentInstrSet() == InstrSet_ARM then
575 R[t] = ROR(data, 8*UInt(address<1:0>));
576 else
577 R[t] = bits(32) UNKNOWN;
578 }
579#endif
580
581 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000582 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000583 if (!success)
584 return false;
585
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000586 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000587 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000588 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000589 if (!success)
590 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000591
592 // PC relative immediate load context
593 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
594 eRegisterKindGeneric,
595 LLDB_REGNUM_GENERIC_PC,
596 0};
Johnny Chen788e0552011-01-27 22:52:23 +0000597 uint32_t Rd; // the destination register
598 uint32_t imm32; // immediate offset from the PC
599 addr_t addr; // the PC relative address
600 uint32_t data; // the literal data value from the PC relative load
601 switch (encoding) {
602 case eEncodingT1:
603 Rd = Bits32(opcode, 10, 8);
604 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
605 addr = pc + 4 + imm32;
Johnny Chen809742e2011-01-28 00:32:27 +0000606 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000607 break;
608 default:
609 return false;
610 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000611 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000612 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000613 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000615 return false;
616 }
617 return true;
618}
619
Johnny Chen5b442b72011-01-27 19:34:30 +0000620// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000621// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000622bool
623EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000624{
625#if 0
626 // ARM pseudo code...
627 if (ConditionPassed())
628 {
629 EncodingSpecificOperations();
630 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
631 if d == 15 then // Can only occur for ARM encoding
632 ALUWritePC(result); // setflags is always FALSE here
633 else
634 R[d] = result;
635 if setflags then
636 APSR.N = result<31>;
637 APSR.Z = IsZeroBit(result);
638 APSR.C = carry;
639 APSR.V = overflow;
640 }
641#endif
642
643 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000644 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000645 if (!success)
646 return false;
647
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000648 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000649 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000650 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000651 if (!success)
652 return false;
653 uint32_t imm32; // the immediate operand
654 switch (encoding) {
655 case eEncodingT2:
656 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
657 break;
658 default:
659 return false;
660 }
661 addr_t sp_offset = imm32;
662 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
663
664 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
665 eRegisterKindGeneric,
666 LLDB_REGNUM_GENERIC_SP,
667 sp_offset };
668
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000669 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000670 return false;
671 }
672 return true;
673}
674
675// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000676// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000677bool
678EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000679{
680#if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
686 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
687 if d == 15 then
688 ALUWritePC(result); // setflags is always FALSE here
689 else
690 R[d] = result;
691 if setflags then
692 APSR.N = result<31>;
693 APSR.Z = IsZeroBit(result);
694 APSR.C = carry;
695 APSR.V = overflow;
696 }
697#endif
698
699 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000700 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000701 if (!success)
702 return false;
703
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000704 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000705 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000706 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000707 if (!success)
708 return false;
709 uint32_t Rm; // the second operand
710 switch (encoding) {
711 case eEncodingT2:
712 Rm = Bits32(opcode, 6, 3);
713 break;
714 default:
715 return false;
716 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000717 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000718 if (!success)
719 return false;
720
721 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
722
723 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
724 eRegisterKindGeneric,
725 LLDB_REGNUM_GENERIC_SP,
726 reg_value };
727
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000729 return false;
730 }
731 return true;
732}
733
Johnny Chen9b8d7832011-02-02 01:13:56 +0000734// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
735// at a PC-relative address, and changes instruction set from ARM to Thumb, or
736// from Thumb to ARM.
737// BLX (immediate)
738bool
739EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
740{
741#if 0
742 // ARM pseudo code...
743 if (ConditionPassed())
744 {
745 EncodingSpecificOperations();
746 if CurrentInstrSet() == InstrSet_ARM then
747 LR = PC - 4;
748 else
749 LR = PC<31:1> : '1';
750 if targetInstrSet == InstrSet_ARM then
751 targetAddress = Align(PC,4) + imm32;
752 else
753 targetAddress = PC + imm32;
754 SelectInstrSet(targetInstrSet);
755 BranchWritePC(targetAddress);
756 }
757#endif
758
759 bool success = false;
760 const uint32_t opcode = OpcodeAsUnsigned (&success);
761 if (!success)
762 return false;
763
764 if (ConditionPassed())
765 {
766 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
767 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000768 if (!success)
769 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000770 addr_t lr; // next instruction address
771 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000772 int32_t imm32; // PC-relative offset
773 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000774 case eEncodingT1:
775 {
776 lr = (pc + 4) | 1u; // return address
777 uint32_t S = Bits32(opcode, 26, 26);
778 uint32_t imm10 = Bits32(opcode, 25, 16);
779 uint32_t J1 = Bits32(opcode, 13, 13);
780 uint32_t J2 = Bits32(opcode, 11, 11);
781 uint32_t imm11 = Bits32(opcode, 10, 0);
782 uint32_t I1 = !(J1 ^ S);
783 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000784 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000785 imm32 = llvm::SignExtend32<25>(imm25);
786 target = pc + 4 + imm32;
787 context.arg1 = 4 + imm32; // signed offset
788 context.arg2 = eModeThumb; // target instruction set
789 break;
790 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000791 case eEncodingT2:
792 {
793 lr = (pc + 4) | 1u; // return address
794 uint32_t S = Bits32(opcode, 26, 26);
795 uint32_t imm10H = Bits32(opcode, 25, 16);
796 uint32_t J1 = Bits32(opcode, 13, 13);
797 uint32_t J2 = Bits32(opcode, 11, 11);
798 uint32_t imm10L = Bits32(opcode, 10, 1);
799 uint32_t I1 = !(J1 ^ S);
800 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000801 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000802 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000803 target = Align(pc + 4, 4) + imm32;
804 context.arg1 = 4 + imm32; // signed offset
805 context.arg2 = eModeARM; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000806 break;
807 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000808 case eEncodingA1:
809 lr = pc + 4; // return address
810 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000811 target = Align(pc + 8, 4) + imm32;
812 context.arg1 = 8 + imm32; // signed offset
813 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000814 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000815 case eEncodingA2:
816 lr = pc + 4; // return address
817 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
818 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000819 context.arg1 = 8 + imm32; // signed offset
820 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000821 break;
822 default:
823 return false;
824 }
825 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
826 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000827 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000828 return false;
829 }
830 return true;
831}
832
833// Branch with Link and Exchange (register) calls a subroutine at an address and
834// instruction set specified by a register.
835// BLX (register)
836bool
837EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
838{
839#if 0
840 // ARM pseudo code...
841 if (ConditionPassed())
842 {
843 EncodingSpecificOperations();
844 target = R[m];
845 if CurrentInstrSet() == InstrSet_ARM then
846 next_instr_addr = PC - 4;
847 LR = next_instr_addr;
848 else
849 next_instr_addr = PC - 2;
850 LR = next_instr_addr<31:1> : ‘1’;
851 BXWritePC(target);
852 }
853#endif
854
855 bool success = false;
856 const uint32_t opcode = OpcodeAsUnsigned (&success);
857 if (!success)
858 return false;
859
860 if (ConditionPassed())
861 {
862 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
863 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
864 addr_t lr; // next instruction address
865 addr_t target; // target address
866 if (!success)
867 return false;
868 uint32_t Rm; // the register with the target address
869 switch (encoding) {
870 case eEncodingT1:
871 lr = (pc + 2) | 1u; // return address
872 Rm = Bits32(opcode, 6, 3);
873 // if m == 15 then UNPREDICTABLE;
874 if (Rm == 15)
875 return false;
876 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
877 break;
878 case eEncodingA1:
879 lr = pc + 4; // return address
880 Rm = Bits32(opcode, 3, 0);
881 // if m == 15 then UNPREDICTABLE;
882 if (Rm == 15)
883 return false;
884 target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chenb77be412011-02-04 00:40:18 +0000885 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000886 default:
887 return false;
888 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000889 context.arg0 = eRegisterKindDWARF;
890 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000891 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
892 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000893 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000894 return false;
895 }
896 return true;
897}
898
Johnny Chen0d0148e2011-01-28 02:26:08 +0000899// Set r7 to point to some ip offset.
900// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000901bool
902EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000903{
904#if 0
905 // ARM pseudo code...
906 if (ConditionPassed())
907 {
908 EncodingSpecificOperations();
909 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
910 if d == 15 then // Can only occur for ARM encoding
911 ALUWritePC(result); // setflags is always FALSE here
912 else
913 R[d] = result;
914 if setflags then
915 APSR.N = result<31>;
916 APSR.Z = IsZeroBit(result);
917 APSR.C = carry;
918 APSR.V = overflow;
919 }
920#endif
921
922 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000923 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000924 if (!success)
925 return false;
926
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000927 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000928 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000929 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000930 if (!success)
931 return false;
932 uint32_t imm32;
933 switch (encoding) {
934 case eEncodingA1:
935 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
936 break;
937 default:
938 return false;
939 }
940 addr_t ip_offset = imm32;
941 addr_t addr = ip - ip_offset; // the adjusted ip value
942
943 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
944 eRegisterKindDWARF,
945 dwarf_r12,
946 -ip_offset };
947
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000948 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +0000949 return false;
950 }
951 return true;
952}
953
954// Set ip to point to some stack offset.
955// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000956bool
957EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +0000958{
959#if 0
960 // ARM pseudo code...
961 if (ConditionPassed())
962 {
963 EncodingSpecificOperations();
964 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
965 if d == 15 then // Can only occur for ARM encoding
966 ALUWritePC(result); // setflags is always FALSE here
967 else
968 R[d] = result;
969 if setflags then
970 APSR.N = result<31>;
971 APSR.Z = IsZeroBit(result);
972 APSR.C = carry;
973 APSR.V = overflow;
974 }
975#endif
976
977 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000978 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000979 if (!success)
980 return false;
981
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000982 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +0000983 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000984 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +0000985 if (!success)
986 return false;
987 uint32_t imm32;
988 switch (encoding) {
989 case eEncodingA1:
990 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
991 break;
992 default:
993 return false;
994 }
995 addr_t sp_offset = imm32;
996 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
997
998 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
999 eRegisterKindGeneric,
1000 LLDB_REGNUM_GENERIC_SP,
1001 -sp_offset };
1002
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001004 return false;
1005 }
1006 return true;
1007}
1008
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001009// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001010bool
1011EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001012{
1013#if 0
1014 // ARM pseudo code...
1015 if (ConditionPassed())
1016 {
1017 EncodingSpecificOperations();
1018 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1019 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001020 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001021 else
1022 R[d] = result;
1023 if setflags then
1024 APSR.N = result<31>;
1025 APSR.Z = IsZeroBit(result);
1026 APSR.C = carry;
1027 APSR.V = overflow;
1028 }
1029#endif
1030
1031 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001032 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001033 if (!success)
1034 return false;
1035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001037 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001039 if (!success)
1040 return false;
1041 uint32_t imm32;
1042 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001043 case eEncodingT1:
1044 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001045 case eEncodingT2:
1046 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1047 break;
1048 case eEncodingT3:
1049 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1050 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001051 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001052 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001053 break;
1054 default:
1055 return false;
1056 }
1057 addr_t sp_offset = imm32;
1058 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1059
1060 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1061 eRegisterKindGeneric,
1062 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001063 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001064
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001065 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001066 return false;
1067 }
1068 return true;
1069}
1070
Johnny Chen08c25e82011-01-31 18:02:28 +00001071// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001072bool
1073EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001074{
1075#if 0
1076 // ARM pseudo code...
1077 if (ConditionPassed())
1078 {
1079 EncodingSpecificOperations();
1080 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1081 address = if index then offset_addr else R[n];
1082 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1083 if wback then R[n] = offset_addr;
1084 }
1085#endif
1086
1087 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001088 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001089 if (!success)
1090 return false;
1091
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001092 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001093 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001094 const uint32_t addr_byte_size = GetAddressByteSize();
1095 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001096 if (!success)
1097 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001098 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001099 uint32_t imm12;
1100 switch (encoding) {
1101 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001102 Rt = Bits32(opcode, 15, 12);
1103 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001104 break;
1105 default:
1106 return false;
1107 }
1108 addr_t sp_offset = imm12;
1109 addr_t addr = sp - sp_offset;
1110
1111 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001112 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001113 {
Johnny Chen91d99862011-01-25 19:07:04 +00001114 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1115 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001116 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001117 if (!success)
1118 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001119 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001120 return false;
1121 }
1122 else
1123 {
1124 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1125 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001126 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001127 if (!success)
1128 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001129 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001130 return false;
1131 }
1132
1133 context.type = EmulateInstruction::eContextAdjustStackPointer;
1134 context.arg0 = eRegisterKindGeneric;
1135 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001136 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001137
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001139 return false;
1140 }
1141 return true;
1142}
1143
Johnny Chen08c25e82011-01-31 18:02:28 +00001144// Vector Push stores multiple extension registers to the stack.
1145// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001146bool
1147EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001148{
1149#if 0
1150 // ARM pseudo code...
1151 if (ConditionPassed())
1152 {
1153 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1154 address = SP - imm32;
1155 SP = SP - imm32;
1156 if single_regs then
1157 for r = 0 to regs-1
1158 MemA[address,4] = S[d+r]; address = address+4;
1159 else
1160 for r = 0 to regs-1
1161 // Store as two word-aligned words in the correct order for current endianness.
1162 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1163 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1164 address = address+8;
1165 }
1166#endif
1167
1168 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001169 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001170 if (!success)
1171 return false;
1172
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001173 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001174 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001175 const uint32_t addr_byte_size = GetAddressByteSize();
1176 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001177 if (!success)
1178 return false;
1179 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001180 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001181 uint32_t imm32; // stack offset
1182 uint32_t regs; // number of registers
1183 switch (encoding) {
1184 case eEncodingT1:
1185 case eEncodingA1:
1186 single_regs = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001187 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001188 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1189 // If UInt(imm8) is odd, see "FSTMX".
1190 regs = Bits32(opcode, 7, 0) / 2;
1191 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1192 if (regs == 0 || regs > 16 || (d + regs) > 32)
1193 return false;
1194 break;
1195 case eEncodingT2:
1196 case eEncodingA2:
1197 single_regs = true;
1198 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1199 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1200 regs = Bits32(opcode, 7, 0);
1201 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1202 if (regs == 0 || regs > 16 || (d + regs) > 32)
1203 return false;
1204 break;
1205 default:
1206 return false;
1207 }
1208 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1209 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1210 addr_t sp_offset = imm32;
1211 addr_t addr = sp - sp_offset;
1212 uint32_t i;
1213
1214 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1215 for (i=d; i<regs; ++i)
1216 {
1217 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1218 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1219 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001221 if (!success)
1222 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001223 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001224 return false;
1225 addr += reg_byte_size;
1226 }
1227
1228 context.type = EmulateInstruction::eContextAdjustStackPointer;
1229 context.arg0 = eRegisterKindGeneric;
1230 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001231 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001232
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001233 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001234 return false;
1235 }
1236 return true;
1237}
1238
Johnny Chen587a0a42011-02-01 18:35:28 +00001239// Vector Pop loads multiple extension registers from the stack.
1240// It also updates SP to point just above the loaded data.
1241bool
1242EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1243{
1244#if 0
1245 // ARM pseudo code...
1246 if (ConditionPassed())
1247 {
1248 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1249 address = SP;
1250 SP = SP + imm32;
1251 if single_regs then
1252 for r = 0 to regs-1
1253 S[d+r] = MemA[address,4]; address = address+4;
1254 else
1255 for r = 0 to regs-1
1256 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1257 // Combine the word-aligned words in the correct order for current endianness.
1258 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1259 }
1260#endif
1261
1262 bool success = false;
1263 const uint32_t opcode = OpcodeAsUnsigned (&success);
1264 if (!success)
1265 return false;
1266
1267 if (ConditionPassed())
1268 {
1269 const uint32_t addr_byte_size = GetAddressByteSize();
1270 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1271 if (!success)
1272 return false;
1273 bool single_regs;
1274 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1275 uint32_t imm32; // stack offset
1276 uint32_t regs; // number of registers
1277 switch (encoding) {
1278 case eEncodingT1:
1279 case eEncodingA1:
1280 single_regs = false;
1281 d = Bits32(opcode, 22, 22) << 4 | Bits32(opcode, 15, 12);
1282 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1283 // If UInt(imm8) is odd, see "FLDMX".
1284 regs = Bits32(opcode, 7, 0) / 2;
1285 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1286 if (regs == 0 || regs > 16 || (d + regs) > 32)
1287 return false;
1288 break;
1289 case eEncodingT2:
1290 case eEncodingA2:
1291 single_regs = true;
1292 d = Bits32(opcode, 15, 12) << 1 | Bits32(opcode, 22, 22);
1293 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1294 regs = Bits32(opcode, 7, 0);
1295 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1296 if (regs == 0 || regs > 16 || (d + regs) > 32)
1297 return false;
1298 break;
1299 default:
1300 return false;
1301 }
1302 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1303 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1304 addr_t sp_offset = imm32;
1305 addr_t addr = sp;
1306 uint32_t i;
1307 uint64_t data; // uint64_t to accomodate 64-bit registers.
1308
1309 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1310 for (i=d; i<regs; ++i)
1311 {
1312 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1313 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1314 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1315 if (!success)
1316 return false;
1317 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1318 return false;
1319 addr += reg_byte_size;
1320 }
1321
1322 context.type = EmulateInstruction::eContextAdjustStackPointer;
1323 context.arg0 = eRegisterKindGeneric;
1324 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1325 context.arg2 = sp_offset;
1326
1327 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1328 return false;
1329 }
1330 return true;
1331}
1332
Johnny Chenb77be412011-02-04 00:40:18 +00001333// SVC (previously SWI)
1334bool
1335EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1336{
1337#if 0
1338 // ARM pseudo code...
1339 if (ConditionPassed())
1340 {
1341 EncodingSpecificOperations();
1342 CallSupervisor();
1343 }
1344#endif
1345
1346 bool success = false;
1347 const uint32_t opcode = OpcodeAsUnsigned (&success);
1348 if (!success)
1349 return false;
1350
1351 if (ConditionPassed())
1352 {
1353 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1354 addr_t lr; // next instruction address
1355 if (!success)
1356 return false;
1357 uint32_t imm32; // the immediate constant
1358 uint32_t mode; // ARM or Thumb mode
1359 switch (encoding) {
1360 case eEncodingT1:
1361 lr = (pc + 2) | 1u; // return address
1362 imm32 = Bits32(opcode, 7, 0);
1363 mode = eModeThumb;
1364 break;
1365 case eEncodingA1:
1366 lr = pc + 4; // return address
1367 imm32 = Bits32(opcode, 23, 0);
1368 mode = eModeARM;
1369 break;
1370 default:
1371 return false;
1372 }
1373 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1374 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1375 return false;
1376 }
1377 return true;
1378}
1379
Johnny Chenc315f862011-02-05 00:46:10 +00001380// If Then makes up to four following instructions (the IT block) conditional.
1381bool
1382EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1383{
1384#if 0
1385 // ARM pseudo code...
1386 EncodingSpecificOperations();
1387 ITSTATE.IT<7:0> = firstcond:mask;
1388#endif
1389
1390 bool success = false;
1391 const uint32_t opcode = OpcodeAsUnsigned (&success);
1392 if (!success)
1393 return false;
1394
1395 m_it_session.InitIT(Bits32(opcode, 7, 0));
1396 return true;
1397}
1398
Johnny Chen3b620b32011-02-07 20:11:47 +00001399// Branch causes a branch to a target address.
1400bool
1401EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1402{
1403#if 0
1404 // ARM pseudo code...
1405 if (ConditionPassed())
1406 {
1407 EncodingSpecificOperations();
1408 BranchWritePC(PC + imm32);
1409 }
1410#endif
1411
1412 bool success = false;
1413 const uint32_t opcode = OpcodeAsUnsigned (&success);
1414 if (!success)
1415 return false;
1416
Johnny Chen9ee056b2011-02-08 00:06:35 +00001417 if (ConditionPassed())
1418 {
1419 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1420 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001421 if (!success)
1422 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001423 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001424 int32_t imm32; // PC-relative offset
1425 switch (encoding) {
1426 case eEncodingT1:
1427 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1428 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1429 target = pc + 4 + imm32;
1430 context.arg1 = 4 + imm32; // signed offset
1431 context.arg2 = eModeThumb; // target instruction set
1432 break;
1433 case eEncodingT2:
1434 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1435 target = pc + 4 + imm32;
1436 context.arg1 = 4 + imm32; // signed offset
1437 context.arg2 = eModeThumb; // target instruction set
1438 break;
1439 case eEncodingT3:
1440 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1441 {
1442 uint32_t S = Bits32(opcode, 26, 26);
1443 uint32_t imm6 = Bits32(opcode, 21, 16);
1444 uint32_t J1 = Bits32(opcode, 13, 13);
1445 uint32_t J2 = Bits32(opcode, 11, 11);
1446 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001447 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001448 imm32 = llvm::SignExtend32<21>(imm21);
1449 target = pc + 4 + imm32;
1450 context.arg1 = eModeThumb; // target instruction set
1451 context.arg2 = 4 + imm32; // signed offset
1452 break;
1453 }
1454 case eEncodingT4:
1455 {
1456 uint32_t S = Bits32(opcode, 26, 26);
1457 uint32_t imm10 = Bits32(opcode, 25, 16);
1458 uint32_t J1 = Bits32(opcode, 13, 13);
1459 uint32_t J2 = Bits32(opcode, 11, 11);
1460 uint32_t imm11 = Bits32(opcode, 10, 0);
1461 uint32_t I1 = !(J1 ^ S);
1462 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001463 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001464 imm32 = llvm::SignExtend32<25>(imm25);
1465 target = pc + 4 + imm32;
1466 context.arg1 = eModeThumb; // target instruction set
1467 context.arg2 = 4 + imm32; // signed offset
1468 break;
1469 }
1470 case eEncodingA1:
1471 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1472 target = pc + 8 + imm32;
1473 context.arg1 = eModeARM; // target instruction set
1474 context.arg2 = 8 + imm32; // signed offset
1475 break;
1476 default:
1477 return false;
1478 }
1479 if (!BranchWritePC(context, target))
1480 return false;
1481 }
1482 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001483}
1484
Johnny Chen53ebab72011-02-08 23:21:57 +00001485// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1486// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1487// CBNZ, CBZ
1488bool
1489EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1490{
1491#if 0
1492 // ARM pseudo code...
1493 EncodingSpecificOperations();
1494 if nonzero ^ IsZero(R[n]) then
1495 BranchWritePC(PC + imm32);
1496#endif
1497
1498 bool success = false;
1499 const uint32_t opcode = OpcodeAsUnsigned (&success);
1500 if (!success)
1501 return false;
1502
1503 // Read the register value from the operand register Rn.
1504 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1505 if (!success)
1506 return false;
1507
1508 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1509 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1510 if (!success)
1511 return false;
1512
1513 addr_t target; // target address
1514 uint32_t imm32; // PC-relative offset to branch forward
1515 bool nonzero;
1516 switch (encoding) {
1517 case eEncodingT1:
1518 imm32 = Bits32(opcode, 9, 9) << 6 | Bits32(opcode, 7, 3) << 1;
1519 nonzero = BitIsSet(opcode, 11);
1520 target = pc + 4 + imm32;
1521 context.arg1 = 4 + imm32; // signed offset
1522 context.arg2 = eModeThumb; // target instruction set
1523 break;
1524 default:
1525 return false;
1526 }
1527 if (nonzero ^ (reg_val == 0))
1528 if (!BranchWritePC(context, target))
1529 return false;
1530
1531 return true;
1532}
1533
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001534// LDM loads multiple registers from consecutive memory locations, using an
1535// address from a base register. Optionally the addres just above the highest of those locations
1536// can be written back to the base register.
1537bool
1538EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1539{
1540#if 0
1541 // ARM pseudo code...
1542 if ConditionPassed()
1543 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1544 address = R[n];
1545
1546 for i = 0 to 14
1547 if registers<i> == '1' then
1548 R[i] = MemA[address, 4]; address = address + 4;
1549 if registers<15> == '1' then
1550 LoadWritePC (MemA[address, 4]);
1551
1552 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1553 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1554
1555#endif
1556
1557 bool success = false;
1558 const uint32_t opcode = OpcodeAsUnsigned (&success);
1559 if (!success)
1560 return false;
1561
1562 if (ConditionPassed())
1563 {
1564 uint32_t n;
1565 uint32_t registers = 0;
1566 bool wback;
1567 const uint32_t addr_byte_size = GetAddressByteSize();
1568 switch (encoding)
1569 {
1570 case eEncodingT1:
1571 n = Bits32 (opcode, 10, 8);
1572 registers = Bits32 (opcode, 7, 0);
1573 wback = BitIsClear (registers, n);
1574 // if BitCount(registers) < 1 then UNPREDICTABLE;
1575 if (BitCount(registers) < 1)
1576 return false;
1577 break;
1578 case eEncodingT2:
1579 n = Bits32 (opcode, 19, 16);
1580 registers = Bits32 (opcode, 15, 0);
1581 wback = BitIsSet (opcode, 21);
1582 if ((n == 15)
1583 || (BitCount (registers) < 2)
1584 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1585 return false;
1586 if (BitIsSet (registers, 15)
1587 && m_it_session.InITBlock()
1588 && !m_it_session.LastInITBlock())
1589 return false;
1590 if (wback
1591 && BitIsSet (registers, n))
1592 return false;
1593 break;
1594 case eEncodingA1:
1595 n = Bits32 (opcode, 19, 16);
1596 registers = Bits32 (opcode, 15, 0);
1597 wback = BitIsSet (opcode, 21);
1598 if ((n == 15)
1599 || (BitCount (registers) < 1))
1600 return false;
1601 break;
1602 default:
1603 return false;
1604 }
1605
1606 int32_t offset = 0;
1607 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1608 if (!success)
1609 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001610
1611 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1612 eRegisterKindDWARF,
1613 dwarf_r0 + n,
1614 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001615
1616 for (int i = 0; i < 14; ++i)
1617 {
1618 if (BitIsSet (registers, i))
1619 {
Caroline Tice85aab332011-02-08 23:56:10 +00001620 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1621 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001622 if (wback && (n == 13)) // Pop Instruction
1623 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1624
1625 // R[i] = MemA [address, 4]; address = address + 4;
1626 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1627 if (!success)
1628 return false;
1629
1630 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1631 return false;
1632
1633 offset += addr_byte_size;
1634 }
1635 }
1636
1637 if (BitIsSet (registers, 15))
1638 {
1639 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00001640 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1641 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001642 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
1643 if (!success)
1644 return false;
1645 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1646 return false;
1647 }
1648
1649 if (wback && BitIsClear (registers, n))
1650 {
1651 addr_t offset = addr_byte_size * BitCount (registers);
Caroline Tice85aab332011-02-08 23:56:10 +00001652 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1653 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001654
1655 // R[n] = R[n] + 4 * BitCount (registers)
1656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
1657 return false;
1658 }
1659 if (wback && BitIsSet (registers, n))
1660 // R[n] bits(32) UNKNOWN;
1661 return false; //I'm not convinced this is the right thing to do here...
1662 }
1663 return true;
1664}
1665
Caroline Tice0b29e242011-02-08 23:16:02 +00001666bool
1667EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
1668{
1669#if 0
1670 // ARM pseudo code...
1671 if ConditionPassed() then
1672 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1673 address = R[n] - 4*BitCount(registers);
1674
1675 for i = 0 to 14
1676 if registers<i> == ’1’ then
1677 R[i] = MemA[address,4]; address = address + 4;
1678 if registers<15> == ’1’ then
1679 LoadWritePC(MemA[address,4]);
1680
1681 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1682 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1683#endif
1684
1685 bool success = false;
1686 const uint32_t opcode = OpcodeAsUnsigned (&success);
1687 if (!success)
1688 return false;
1689
1690 if (ConditionPassed())
1691 {
1692 uint32_t n;
1693 uint32_t registers = 0;
1694 bool wback;
1695 const uint32_t addr_byte_size = GetAddressByteSize();
1696 switch (encoding)
1697 {
1698 case eEncodingT1:
1699 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
1700 n = Bits32 (opcode, 19, 16);
1701 registers = Bits32 (opcode, 15, 0);
1702 wback = BitIsSet (opcode, 21);
1703
1704 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
1705 if ((n == 15)
1706 || (BitCount (registers) < 2)
1707 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1708 return false;
1709
1710 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
1711 if (BitIsSet (registers, 15)
1712 && m_it_session.InITBlock()
1713 && !m_it_session.LastInITBlock())
1714 return false;
1715
1716 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
1717 if (wback && BitIsSet (registers, n))
1718 return false;
1719
1720 break;
1721
1722 case eEncodingA1:
1723 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1724 n = Bits32 (opcode, 19, 16);
1725 registers = Bits32 (opcode, 15, 0);
1726 wback = BitIsSet (opcode, 21);
1727
1728 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1729 if ((n == 15) || (BitCount (registers) < 1))
1730 return false;
1731
1732 break;
1733
1734 default:
1735 return false;
1736 }
1737
1738 int32_t offset = 0;
1739 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
1740 - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00001741 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1742 eRegisterKindDWARF,
1743 dwarf_r0 + n,
1744 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00001745
1746 for (int i = 0; i < 14; ++i)
1747 {
1748 if (BitIsSet (registers, i))
1749 {
1750 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00001751 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001752 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1753 if (!success)
1754 return false;
1755
1756 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1757 return false;
1758
1759 offset += addr_byte_size;
1760 }
1761 }
1762
1763 // if registers<15> == ’1’ then
1764 // LoadWritePC(MemA[address,4]);
1765 if (BitIsSet (registers, 15))
1766 {
Caroline Tice85aab332011-02-08 23:56:10 +00001767 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001768 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1769 if (!success)
1770 return false;
1771 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1772 return false;
1773 }
1774
1775 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
1776 if (wback && BitIsClear (registers, n))
1777 {
Caroline Tice85aab332011-02-08 23:56:10 +00001778 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00001779 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1780 if (!success)
1781 return false;
1782 addr = addr - (addr_byte_size * BitCount (registers));
1783 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1784 return false;
1785 }
1786
1787 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1788 if (wback && BitIsSet (registers, n))
1789 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1790 }
1791 return true;
1792}
Caroline Tice85aab332011-02-08 23:56:10 +00001793
1794bool
1795EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
1796{
1797#if 0
1798 if ConditionPassed() then
1799 EncodingSpecificOperations();
1800 address = R[n] + 4;
1801
1802 for i = 0 to 14
1803 if registers<i> == ’1’ then
1804 R[i] = MemA[address,4]; address = address + 4;
1805 if registers<15> == ’1’ then
1806 LoadWritePC(MemA[address,4]);
1807
1808 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1809 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
1810#endif
1811
1812 bool success = false;
1813 const uint32_t opcode = OpcodeAsUnsigned (&success);
1814 if (!success)
1815 return false;
1816
1817 if (ConditionPassed())
1818 {
1819 uint32_t n;
1820 uint32_t registers = 0;
1821 bool wback;
1822 const uint32_t addr_byte_size = GetAddressByteSize();
1823 switch (encoding)
1824 {
1825 case eEncodingA1:
1826 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
1827 n = Bits32 (opcode, 19, 16);
1828 registers = Bits32 (opcode, 15, 0);
1829 wback = BitIsSet (opcode, 21);
1830
1831 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
1832 if ((n == 15) || (BitCount (registers) < 1))
1833 return false;
1834
1835 break;
1836 default:
1837 return false;
1838 }
1839 // address = R[n] + 4;
1840
1841 int32_t offset = 0;
1842 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success) + addr_byte_size;
1843
1844 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1845 eRegisterKindDWARF,
1846 dwarf_r0 + n,
1847 offset };
1848
1849 for (int i = 0; i < 14; ++i)
1850 {
1851 if (BitIsSet (registers, i))
1852 {
1853 // R[i] = MemA[address,4]; address = address + 4;
1854
1855 context.arg2 = offset;
1856 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1857 if (!success)
1858 return false;
1859
1860 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
1861 return false;
1862
1863 offset += addr_byte_size;
1864 }
1865 }
1866
1867 // if registers<15> == ’1’ then
1868 // LoadWritePC(MemA[address,4]);
1869 if (BitIsSet (registers, 15))
1870 {
1871 context.arg2 = offset;
1872 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
1873 if (!success)
1874 return false;
1875 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
1876 return false;
1877 }
1878
1879 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
1880 if (wback && BitIsClear (registers, n))
1881 {
1882 context.arg2 = offset;
1883 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1884 if (!success)
1885 return false;
1886 addr = addr + (addr_byte_size * BitCount (registers));
1887 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
1888 return false;
1889 }
1890
1891 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1892 if (wback && BitIsSet (registers, n))
1893 return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
1894 }
1895 return true;
1896}
Caroline Tice0b29e242011-02-08 23:16:02 +00001897
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001898EmulateInstructionARM::ARMOpcode*
1899EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00001900{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001901 static ARMOpcode
1902 g_arm_opcodes[] =
1903 {
1904 //----------------------------------------------------------------------
1905 // Prologue instructions
1906 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00001907
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001908 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001909 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
1910 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00001911
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001912 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001913 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
1914 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001915 // set ip to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001916 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
1917 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
1918 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001919
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001920 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001921 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00001922
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001923 // push one register
1924 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00001925 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00001926
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001927 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001928 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
1929 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00001930
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001931 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00001932 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001933 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00001934
Johnny Chen9b8d7832011-02-02 01:13:56 +00001935 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
1936 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
1937 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
1938 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00001939 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
1940 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00001941 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00001942 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
1943
1944 //----------------------------------------------------------------------
1945 // Supervisor Call (previously Software Interrupt)
1946 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00001947 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
1948
1949 //----------------------------------------------------------------------
1950 // Branch instructions
1951 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001952 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chenb77be412011-02-04 00:40:18 +00001953
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001954 //----------------------------------------------------------------------
1955 // Load instructions
1956 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00001957 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00001958 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
1959 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001960
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001961 };
1962 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
1963
1964 for (size_t i=0; i<k_num_arm_opcodes; ++i)
1965 {
1966 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
1967 return &g_arm_opcodes[i];
1968 }
1969 return NULL;
1970}
Greg Clayton64c84432011-01-21 22:02:52 +00001971
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001972
1973EmulateInstructionARM::ARMOpcode*
1974EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00001975{
Johnny Chenfdd179e2011-01-31 20:09:28 +00001976
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001977 static ARMOpcode
1978 g_thumb_opcodes[] =
1979 {
1980 //----------------------------------------------------------------------
1981 // Prologue instructions
1982 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00001983
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001984 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001985 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00001986 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
1987 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001988 // move from high register to low register
Johnny Chenc28a76d2011-02-01 18:51:48 +00001989 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen788e0552011-01-27 22:52:23 +00001990
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001991 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00001992 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
1993 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chen60c0d622011-01-25 23:49:39 +00001994
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001995 // PC relative load into register (see also EmulateAddSPRm)
Johnny Chenc28a76d2011-02-01 18:51:48 +00001996 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRdPCRelative, "ldr <Rd>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00001997
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001998 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00001999 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2000 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002001 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2002 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002003
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002004 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002005 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2006 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002007
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002008 //----------------------------------------------------------------------
2009 // Epilogue instructions
2010 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002011
Johnny Chenc28a76d2011-02-01 18:51:48 +00002012 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002013 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
2014 // J1 == J2 == 1
Johnny Chend6c13f02011-02-08 20:36:34 +00002015 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2016 // J1 == J2 == 1
2017 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chenc28a76d2011-02-01 18:51:48 +00002018 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002019 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2020 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2021 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2022 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002023
2024 //----------------------------------------------------------------------
2025 // Supervisor Call (previously Software Interrupt)
2026 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002027 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2028
2029 //----------------------------------------------------------------------
2030 // If Then makes up to four following instructions conditional.
2031 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002032 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2033
2034 //----------------------------------------------------------------------
2035 // Branch instructions
2036 //----------------------------------------------------------------------
2037 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2038 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2039 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002040 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002041 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002042 // compare and branch
2043 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002044
2045 //----------------------------------------------------------------------
2046 // Load instructions
2047 //----------------------------------------------------------------------
2048 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002049 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
2050 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002051
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002052 };
2053
2054 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2055 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2056 {
2057 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2058 return &g_thumb_opcodes[i];
2059 }
2060 return NULL;
2061}
Greg Clayton64c84432011-01-21 22:02:52 +00002062
Greg Clayton31e2a382011-01-30 20:03:56 +00002063bool
2064EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2065{
2066 m_arm_isa = 0;
2067 const char *triple_cstr = triple.GetCString();
2068 if (triple_cstr)
2069 {
2070 const char *dash = ::strchr (triple_cstr, '-');
2071 if (dash)
2072 {
2073 std::string arch (triple_cstr, dash);
2074 const char *arch_cstr = arch.c_str();
2075 if (strcasecmp(arch_cstr, "armv4t") == 0)
2076 m_arm_isa = ARMv4T;
2077 else if (strcasecmp(arch_cstr, "armv4") == 0)
2078 m_arm_isa = ARMv4;
2079 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2080 m_arm_isa = ARMv5TEJ;
2081 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2082 m_arm_isa = ARMv5TE;
2083 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2084 m_arm_isa = ARMv5T;
2085 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2086 m_arm_isa = ARMv6K;
2087 else if (strcasecmp(arch_cstr, "armv6") == 0)
2088 m_arm_isa = ARMv6;
2089 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2090 m_arm_isa = ARMv6T2;
2091 else if (strcasecmp(arch_cstr, "armv7") == 0)
2092 m_arm_isa = ARMv7;
2093 else if (strcasecmp(arch_cstr, "armv8") == 0)
2094 m_arm_isa = ARMv8;
2095 }
2096 }
2097 return m_arm_isa != 0;
2098}
2099
2100
Greg Clayton64c84432011-01-21 22:02:52 +00002101bool
2102EmulateInstructionARM::ReadInstruction ()
2103{
2104 bool success = false;
2105 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2106 if (success)
2107 {
2108 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2109 if (success)
2110 {
2111 Context read_inst_context = {eContextReadOpcode, 0, 0};
2112 if (m_inst_cpsr & MASK_CPSR_T)
2113 {
2114 m_inst_mode = eModeThumb;
2115 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2116
2117 if (success)
2118 {
2119 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2120 {
2121 m_inst.opcode_type = eOpcode16;
2122 m_inst.opcode.inst16 = thumb_opcode;
2123 }
2124 else
2125 {
2126 m_inst.opcode_type = eOpcode32;
2127 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2128 }
2129 }
2130 }
2131 else
2132 {
2133 m_inst_mode = eModeARM;
2134 m_inst.opcode_type = eOpcode32;
2135 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2136 }
2137 }
2138 }
2139 if (!success)
2140 {
2141 m_inst_mode = eModeInvalid;
2142 m_inst_pc = LLDB_INVALID_ADDRESS;
2143 }
2144 return success;
2145}
2146
Johnny Chenee9b1f72011-02-09 01:00:31 +00002147uint32_t
2148EmulateInstructionARM::ArchVersion ()
2149{
2150 return m_arm_isa;
2151}
2152
Greg Clayton64c84432011-01-21 22:02:52 +00002153bool
2154EmulateInstructionARM::ConditionPassed ()
2155{
2156 if (m_inst_cpsr == 0)
2157 return false;
2158
2159 const uint32_t cond = CurrentCond ();
2160
2161 if (cond == UINT32_MAX)
2162 return false;
2163
2164 bool result = false;
2165 switch (UnsignedBits(cond, 3, 1))
2166 {
2167 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2168 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2169 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2170 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2171 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2172 case 5:
2173 {
2174 bool n = (m_inst_cpsr & MASK_CPSR_N);
2175 bool v = (m_inst_cpsr & MASK_CPSR_V);
2176 result = n == v;
2177 }
2178 break;
2179 case 6:
2180 {
2181 bool n = (m_inst_cpsr & MASK_CPSR_N);
2182 bool v = (m_inst_cpsr & MASK_CPSR_V);
2183 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
2184 }
2185 break;
2186 case 7:
2187 result = true;
2188 break;
2189 }
2190
2191 if (cond & 1)
2192 result = !result;
2193 return result;
2194}
2195
Johnny Chen9ee056b2011-02-08 00:06:35 +00002196uint32_t
2197EmulateInstructionARM::CurrentCond ()
2198{
2199 switch (m_inst_mode)
2200 {
2201 default:
2202 case eModeInvalid:
2203 break;
2204
2205 case eModeARM:
2206 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
2207
2208 case eModeThumb:
2209 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
2210 // 'cond' field of the encoding.
2211 if (m_inst.opcode_type == eOpcode16 &&
2212 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
2213 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
2214 {
2215 return Bits32(m_inst.opcode.inst16, 11, 7);
2216 }
2217 else if (m_inst.opcode_type == eOpcode32 &&
2218 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
2219 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
2220 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
2221 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
2222 {
2223 return Bits32(m_inst.opcode.inst32, 25, 22);
2224 }
2225
2226 return m_it_session.GetCond();
2227 }
2228 return UINT32_MAX; // Return invalid value
2229}
2230
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231bool
2232EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
2233{
2234 addr_t target;
2235
Johnny Chenee9b1f72011-02-09 01:00:31 +00002236 // Check the current instruction set.
2237 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00002238 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002239 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00002240 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00002241
Johnny Chen9ee056b2011-02-08 00:06:35 +00002242 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002243 return false;
2244
2245 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002246}
2247
2248// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
2249bool
2250EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
2251{
2252 addr_t target;
2253
2254 if (BitIsSet(addr, 0))
2255 {
Johnny Chenee9b1f72011-02-09 01:00:31 +00002256 SelectInstrSet(eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002257 target = addr & 0xfffffffe;
2258 context.arg2 = eModeThumb;
2259 }
2260 else if (BitIsClear(addr, 1))
2261 {
Johnny Chenee9b1f72011-02-09 01:00:31 +00002262 SelectInstrSet(eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002263 target = addr & 0xfffffffc;
2264 context.arg2 = eModeARM;
2265 }
2266 else
2267 return false; // address<1:0> == '10' => UNPREDICTABLE
2268
2269 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00002270 return false;
2271
2272 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00002273}
Greg Clayton64c84432011-01-21 22:02:52 +00002274
Johnny Chenee9b1f72011-02-09 01:00:31 +00002275// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
2276bool
2277EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
2278{
2279 if (ArchVersion() >= ARMv5T)
2280 return BXWritePC(context, addr);
2281 else
2282 return BranchWritePC((const Context)context, addr);
2283}
2284
2285EmulateInstructionARM::Mode
2286EmulateInstructionARM::CurrentInstrSet ()
2287{
2288 return m_inst_mode;
2289}
2290
2291// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
2292// ReadInstruction() is performed.
2293bool
2294EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
2295{
2296 switch (arm_or_thumb)
2297 {
2298 default:
2299 return false;
2300 eModeARM:
2301 // Clear the T bit.
2302 m_inst_cpsr &= ~MASK_CPSR_T;
2303 break;
2304 eModeThumb:
2305 // Set the T bit.
2306 m_inst_cpsr |= MASK_CPSR_T;
2307 break;
2308 }
2309 return true;
2310}
2311
Greg Clayton64c84432011-01-21 22:02:52 +00002312bool
2313EmulateInstructionARM::EvaluateInstruction ()
2314{
Johnny Chenc315f862011-02-05 00:46:10 +00002315 // Advance the ITSTATE bits to their values for the next instruction.
2316 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
2317 m_it_session.ITAdvance();
2318
Greg Clayton64c84432011-01-21 22:02:52 +00002319 return false;
2320}