blob: d2970c4457caa20e376d228085728a691ed3a039 [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
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000013#include "lldb/Core/ConstString.h"
14
Greg Claytonf29a08f2011-02-09 17:41:27 +000015#include "Plugins/Process/Utility/ARMDefines.h"
16#include "Plugins/Process/Utility/ARMUtils.h"
17#include "Utility/ARM_DWARF_Registers.h"
18
Johnny Chen9b8d7832011-02-02 01:13:56 +000019#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000020 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Johnny Chend6c13f02011-02-08 20:36:34 +000025static inline uint32_t Align(uint32_t val, uint32_t alignment)
26{
27 return alignment * (val / alignment);
28}
29
Johnny Chen0e00af22011-02-10 19:40:42 +000030//----------------------------------------------------------------------
31//
32// ITSession implementation
33//
34//----------------------------------------------------------------------
35
Johnny Chen93070472011-02-04 23:02:47 +000036// A8.6.50
37// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
38static unsigned short CountITSize(unsigned ITMask) {
39 // First count the trailing zeros of the IT mask.
40 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
41 if (TZ > 3)
42 {
43 printf("Encoding error: IT Mask '0000'\n");
44 return 0;
45 }
46 return (4 - TZ);
47}
48
49// Init ITState. Note that at least one bit is always 1 in mask.
50bool ITSession::InitIT(unsigned short bits7_0)
51{
52 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
53 if (ITCounter == 0)
54 return false;
55
56 // A8.6.50 IT
57 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
58 if (FirstCond == 0xF)
59 {
60 printf("Encoding error: IT FirstCond '1111'\n");
61 return false;
62 }
63 if (FirstCond == 0xE && ITCounter != 1)
64 {
65 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
66 return false;
67 }
68
69 ITState = bits7_0;
70 return true;
71}
72
73// Update ITState if necessary.
74void ITSession::ITAdvance()
75{
76 assert(ITCounter);
77 --ITCounter;
78 if (ITCounter == 0)
79 ITState = 0;
80 else
81 {
82 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
83 SetBits32(ITState, 4, 0, NewITState4_0);
84 }
85}
86
87// Return true if we're inside an IT Block.
88bool ITSession::InITBlock()
89{
90 return ITCounter != 0;
91}
92
Johnny Chenc315f862011-02-05 00:46:10 +000093// Return true if we're the last instruction inside an IT Block.
94bool ITSession::LastInITBlock()
95{
96 return ITCounter == 1;
97}
98
Johnny Chen93070472011-02-04 23:02:47 +000099// Get condition bits for the current thumb instruction.
100uint32_t ITSession::GetCond()
101{
Johnny Chenc315f862011-02-05 00:46:10 +0000102 if (InITBlock())
103 return Bits32(ITState, 7, 4);
104 else
105 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000106}
107
Greg Clayton64c84432011-01-21 22:02:52 +0000108// ARM constants used during decoding
109#define REG_RD 0
110#define LDM_REGLIST 1
111#define PC_REG 15
112#define PC_REGLIST_BIT 0x8000
113
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMv4T (1u << 1)
116#define ARMv5T (1u << 2)
117#define ARMv5TE (1u << 3)
118#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000119#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMv6K (1u << 6)
121#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000123#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMvAll (0xffffffffu)
125
Johnny Chen9b8d7832011-02-02 01:13:56 +0000126#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
127#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000129
Johnny Chen0e00af22011-02-10 19:40:42 +0000130//----------------------------------------------------------------------
131//
132// EmulateInstructionARM implementation
133//
134//----------------------------------------------------------------------
135
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000136void
137EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
145
Caroline Ticefa172202011-02-11 22:49:54 +0000146// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
147bool
148EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
149{
150 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteMemoryRandomBits,
151 address,
152 0,
153 0 };
154
155 uint32_t random_data = rand ();
156 const uint32_t addr_byte_size = GetAddressByteSize();
157
158 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
159 return false;
160
161 return true;
162}
163
Caroline Tice713c2662011-02-11 17:59:55 +0000164// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
165bool
166EmulateInstructionARM::WriteBits32Unknown (int n)
167{
168 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteRegisterRandomBits,
169 eRegisterKindDWARF,
170 dwarf_r0 + n,
171 0 };
172
Johnny Chen62ff6f52011-02-11 18:11:22 +0000173 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000174 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
175
176 if (!success)
177 return false;
178
179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
180 return false;
181
182 return true;
183}
184
Johnny Chen08c25e82011-01-31 18:02:28 +0000185// Push Multiple Registers stores multiple registers to the stack, storing to
186// consecutive memory locations ending just below the address in SP, and updates
187// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000188bool
189EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000190{
191#if 0
192 // ARM pseudo code...
193 if (ConditionPassed())
194 {
195 EncodingSpecificOperations();
196 NullCheckIfThumbEE(13);
197 address = SP - 4*BitCount(registers);
198
199 for (i = 0 to 14)
200 {
201 if (registers<i> == ’1’)
202 {
203 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
204 MemA[address,4] = bits(32) UNKNOWN;
205 else
206 MemA[address,4] = R[i];
207 address = address + 4;
208 }
209 }
210
211 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
212 MemA[address,4] = PCStoreValue();
213
214 SP = SP - 4*BitCount(registers);
215 }
216#endif
217
218 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000219 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000220 if (!success)
221 return false;
222
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000224 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 const uint32_t addr_byte_size = GetAddressByteSize();
226 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000227 if (!success)
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000230 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000235 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000236 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // if BitCount(registers) < 1 then UNPREDICTABLE;
238 if (BitCount(registers) < 1)
239 return false;
240 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000241 case eEncodingT2:
242 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BitCount(registers) < 2 then UNPREDICTABLE;
245 if (BitCount(registers) < 2)
246 return false;
247 break;
248 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000249 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000255 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000257 // Instead of return false, let's handle the following case as well,
258 // which amounts to pushing one reg onto the full descending stacks.
259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000260 break;
261 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000262 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000268 default:
269 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 }
Johnny Chence1ca772011-01-25 01:13:00 +0000271 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000272 addr_t addr = sp - sp_offset;
273 uint32_t i;
274
275 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
276 for (i=0; i<15; ++i)
277 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000278 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000279 {
280 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
281 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000282 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000283 if (!success)
284 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000286 return false;
287 addr += addr_byte_size;
288 }
289 }
290
Johnny Chen7c1bf922011-02-08 23:49:37 +0000291 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 {
293 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000294 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000295 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000296 if (!success)
297 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000299 return false;
300 }
301
302 context.type = EmulateInstruction::eContextAdjustStackPointer;
303 context.arg0 = eRegisterKindGeneric;
304 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000305 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000306
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000307 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310 return true;
311}
312
Johnny Chenef85e912011-01-31 23:07:40 +0000313// Pop Multiple Registers loads multiple registers from the stack, loading from
314// consecutive memory locations staring at the address in SP, and updates
315// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000316bool
317EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000318{
319#if 0
320 // ARM pseudo code...
321 if (ConditionPassed())
322 {
323 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
324 address = SP;
325 for i = 0 to 14
326 if registers<i> == ‘1’ then
327 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
328 if registers<15> == ‘1’ then
329 if UnalignedAllowed then
330 LoadWritePC(MemU[address,4]);
331 else
332 LoadWritePC(MemA[address,4]);
333 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
334 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
335 }
336#endif
337
338 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000339 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000340 if (!success)
341 return false;
342
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000345 const uint32_t addr_byte_size = GetAddressByteSize();
346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349 uint32_t registers = 0;
350 uint32_t Rt; // the destination register
351 switch (encoding) {
352 case eEncodingT1:
353 registers = Bits32(opcode, 7, 0);
354 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000355 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 registers |= (1u << 15);
357 // if BitCount(registers) < 1 then UNPREDICTABLE;
358 if (BitCount(registers) < 1)
359 return false;
360 break;
361 case eEncodingT2:
362 // Ignore bit 13.
363 registers = Bits32(opcode, 15, 0) & ~0x2000;
364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
369 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000370 break;
371 case eEncodingT3:
372 Rt = Bits32(opcode, 15, 12);
373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 if (Rt == 13)
375 return false;
376 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
378 registers = (1u << Rt);
379 break;
380 case eEncodingA1:
381 registers = Bits32(opcode, 15, 0);
382 // Instead of return false, let's handle the following case as well,
383 // which amounts to popping one reg from the full descending stacks.
384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
385
386 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 break;
390 case eEncodingA2:
391 Rt = Bits32(opcode, 15, 12);
392 // if t == 13 then UNPREDICTABLE;
393 if (Rt == dwarf_sp)
394 return false;
395 registers = (1u << Rt);
396 break;
397 default:
398 return false;
399 }
400 addr_t sp_offset = addr_byte_size * BitCount (registers);
401 addr_t addr = sp;
402 uint32_t i, data;
403
404 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
405 for (i=0; i<15; ++i)
406 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000407 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000408 {
409 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
410 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000411 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000412 if (!success)
413 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000415 return false;
416 addr += addr_byte_size;
417 }
418 }
419
Johnny Chen7c1bf922011-02-08 23:49:37 +0000420 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 {
422 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
423 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000424 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000425 if (!success)
426 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000427 // In ARMv5T and above, this is an interworking branch.
428 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000429 return false;
430 addr += addr_byte_size;
431 }
432
433 context.type = EmulateInstruction::eContextAdjustStackPointer;
434 context.arg0 = eRegisterKindGeneric;
435 context.arg1 = LLDB_REGNUM_GENERIC_SP;
436 context.arg2 = sp_offset;
437
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 }
441 return true;
442}
443
Johnny Chen5b442b72011-01-27 19:34:30 +0000444// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000445// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446bool
447EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448{
449#if 0
450 // ARM pseudo code...
451 if (ConditionPassed())
452 {
453 EncodingSpecificOperations();
454 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
455 if d == 15 then
456 ALUWritePC(result); // setflags is always FALSE here
457 else
458 R[d] = result;
459 if setflags then
460 APSR.N = result<31>;
461 APSR.Z = IsZeroBit(result);
462 APSR.C = carry;
463 APSR.V = overflow;
464 }
465#endif
466
467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if (!success)
470 return false;
471
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
494 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
495 eRegisterKindGeneric,
496 LLDB_REGNUM_GENERIC_SP,
497 sp_offset };
498
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000499 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000500 return false;
501 }
502 return true;
503}
504
Johnny Chen2ccad832011-01-28 19:57:25 +0000505// Set r7 or ip to the current stack pointer.
506// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000507bool
508EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000509{
510#if 0
511 // ARM pseudo code...
512 if (ConditionPassed())
513 {
514 EncodingSpecificOperations();
515 result = R[m];
516 if d == 15 then
517 ALUWritePC(result); // setflags is always FALSE here
518 else
519 R[d] = result;
520 if setflags then
521 APSR.N = result<31>;
522 APSR.Z = IsZeroBit(result);
523 // APSR.C unchanged
524 // APSR.V unchanged
525 }
526#endif
527
528 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000529 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000530 //if (!success)
531 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000532
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000533 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000534 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000536 if (!success)
537 return false;
538 uint32_t Rd; // the destination register
539 switch (encoding) {
540 case eEncodingT1:
541 Rd = 7;
542 break;
543 case eEncodingA1:
544 Rd = 12;
545 break;
546 default:
547 return false;
548 }
549 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
550 eRegisterKindGeneric,
551 LLDB_REGNUM_GENERIC_SP,
552 0 };
553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen1c13b622011-01-29 00:11:15 +0000560// Move from high register (r8-r15) to low register (r0-r7).
561// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
563EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000564{
Johnny Chen338bf542011-02-10 19:29:03 +0000565 return EmulateMovRdRm (encoding);
566}
567
568// Move from register to register.
569// MOV (register)
570bool
571EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
572{
Johnny Chen1c13b622011-01-29 00:11:15 +0000573#if 0
574 // ARM pseudo code...
575 if (ConditionPassed())
576 {
577 EncodingSpecificOperations();
578 result = R[m];
579 if d == 15 then
580 ALUWritePC(result); // setflags is always FALSE here
581 else
582 R[d] = result;
583 if setflags then
584 APSR.N = result<31>;
585 APSR.Z = IsZeroBit(result);
586 // APSR.C unchanged
587 // APSR.V unchanged
588 }
589#endif
590
591 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000592 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000593 if (!success)
594 return false;
595
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000596 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000597 {
598 uint32_t Rm; // the source register
599 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000600 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 switch (encoding) {
602 case eEncodingT1:
603 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000604 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000605 setflags = false;
606 break;
607 case eEncodingT2:
608 Rm = Bits32(opcode, 5, 3);
609 Rd = Bits32(opcode, 2, 1);
610 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 break;
612 default:
613 return false;
614 }
Johnny Chen338bf542011-02-10 19:29:03 +0000615 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000616 if (!success)
617 return false;
618
619 // The context specifies that Rm is to be moved into Rd.
620 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
621 eRegisterKindDWARF,
622 dwarf_r0 + Rm,
623 0 };
624
Johnny Chen338bf542011-02-10 19:29:03 +0000625 if (Rd == 15)
626 {
627 if (!ALUWritePC (context, reg_value))
628 return false;
629 }
630 else
631 {
632 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
633 return false;
634 if (setflags)
635 {
636 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000637 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
638 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000639 if (m_new_inst_cpsr != m_inst_cpsr)
640 {
641 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
642 return false;
643 }
644 }
645 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000646 }
647 return true;
648}
649
Johnny Chen28070c32011-02-12 01:27:26 +0000650// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
651// the destination register. It can optionally update the condition flags based
652// on the value.
653// MVN (immediate)
654bool
655EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
656{
657#if 0
658 // ARM pseudo code...
659 if (ConditionPassed())
660 {
661 EncodingSpecificOperations();
662 result = NOT(imm32);
663 if d == 15 then // Can only occur for ARM encoding
664 ALUWritePC(result); // setflags is always FALSE here
665 else
666 R[d] = result;
667 if setflags then
668 APSR.N = result<31>;
669 APSR.Z = IsZeroBit(result);
670 APSR.C = carry;
671 // APSR.V unchanged
672 }
673#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000674 bool success = false;
675 const uint32_t opcode = OpcodeAsUnsigned (&success);
676 if (!success)
677 return false;
678
679 if (ConditionPassed())
680 {
681 uint32_t Rd; // the destination register
682 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C.
683 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C.
684 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
685 bool setflags;
686 switch (encoding) {
687 case eEncodingT1:
688 Rd = Bits32(opcode, 11, 8);
689 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
690 setflags = BitIsSet(opcode, 20);
691 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
692 break;
693 case eEncodingA1:
694 Rd = Bits32(opcode, 15, 12);
695 imm12 = Bits32(opcode, 11, 0);
696 setflags = BitIsSet(opcode, 20);
697 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
698 break;
699 default:
700 return false;
701 }
702 uint32_t result = ~imm32;
703
704 // The context specifies that an immediate is to be moved into Rd.
705 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
706 0,
707 0,
708 0 };
709
710 if (Rd == 15)
711 {
712 if (!ALUWritePC (context, result))
713 return false;
714 }
715 else
716 {
717 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
718 return false;
719 if (setflags)
720 {
721 m_new_inst_cpsr = m_inst_cpsr;
722 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
723 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
724 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
725 if (m_new_inst_cpsr != m_inst_cpsr)
726 {
727 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
728 return false;
729 }
730 }
731 }
732 }
733 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000734}
735
Johnny Chen788e0552011-01-27 22:52:23 +0000736// PC relative immediate load into register, possibly followed by ADD (SP plus register).
737// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000738bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000739EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000740{
741#if 0
742 // ARM pseudo code...
743 if (ConditionPassed())
744 {
745 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
746 base = Align(PC,4);
747 address = if add then (base + imm32) else (base - imm32);
748 data = MemU[address,4];
749 if t == 15 then
750 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
751 elsif UnalignedSupport() || address<1:0> = ‘00’ then
752 R[t] = data;
753 else // Can only apply before ARMv7
754 if CurrentInstrSet() == InstrSet_ARM then
755 R[t] = ROR(data, 8*UInt(address<1:0>));
756 else
757 R[t] = bits(32) UNKNOWN;
758 }
759#endif
760
761 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000762 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000763 if (!success)
764 return false;
765
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000766 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000767 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000768 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000769 if (!success)
770 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000771
772 // PC relative immediate load context
773 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
774 eRegisterKindGeneric,
775 LLDB_REGNUM_GENERIC_PC,
776 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000777 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000778 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000779 bool add; // +imm32 or -imm32?
780 addr_t base; // the base address
781 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000782 uint32_t data; // the literal data value from the PC relative load
783 switch (encoding) {
784 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000785 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000786 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000787 add = true;
788 base = Align(pc + 4, 4);
789 context.arg2 = 4 + imm32;
790 break;
791 case eEncodingT2:
792 Rt = Bits32(opcode, 15, 12);
793 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
794 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000795 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000796 return false;
797 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000798 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000799 break;
800 default:
801 return false;
802 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000803
804 if (add)
805 address = base + imm32;
806 else
807 address = base - imm32;
808 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000809 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000810 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000811
812 if (Rt == 15)
813 {
814 if (Bits32(address, 1, 0) == 0)
815 {
816 // In ARMv5T and above, this is an interworking branch.
817 if (!LoadWritePC(context, data))
818 return false;
819 }
820 else
821 return false;
822 }
823 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
824 {
825 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
826 return false;
827 }
828 else // We don't handle ARM for now.
829 return false;
830
831 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000832 return false;
833 }
834 return true;
835}
836
Johnny Chen5b442b72011-01-27 19:34:30 +0000837// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000838// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000839bool
840EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000841{
842#if 0
843 // ARM pseudo code...
844 if (ConditionPassed())
845 {
846 EncodingSpecificOperations();
847 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
848 if d == 15 then // Can only occur for ARM encoding
849 ALUWritePC(result); // setflags is always FALSE here
850 else
851 R[d] = result;
852 if setflags then
853 APSR.N = result<31>;
854 APSR.Z = IsZeroBit(result);
855 APSR.C = carry;
856 APSR.V = overflow;
857 }
858#endif
859
860 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000861 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000862 if (!success)
863 return false;
864
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000865 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000866 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000867 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000868 if (!success)
869 return false;
870 uint32_t imm32; // the immediate operand
871 switch (encoding) {
872 case eEncodingT2:
873 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
874 break;
875 default:
876 return false;
877 }
878 addr_t sp_offset = imm32;
879 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
880
881 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
882 eRegisterKindGeneric,
883 LLDB_REGNUM_GENERIC_SP,
884 sp_offset };
885
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000886 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000887 return false;
888 }
889 return true;
890}
891
892// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000893// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000894bool
895EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000896{
897#if 0
898 // ARM pseudo code...
899 if (ConditionPassed())
900 {
901 EncodingSpecificOperations();
902 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
903 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
904 if d == 15 then
905 ALUWritePC(result); // setflags is always FALSE here
906 else
907 R[d] = result;
908 if setflags then
909 APSR.N = result<31>;
910 APSR.Z = IsZeroBit(result);
911 APSR.C = carry;
912 APSR.V = overflow;
913 }
914#endif
915
916 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000917 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000918 if (!success)
919 return false;
920
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000921 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000922 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000923 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000924 if (!success)
925 return false;
926 uint32_t Rm; // the second operand
927 switch (encoding) {
928 case eEncodingT2:
929 Rm = Bits32(opcode, 6, 3);
930 break;
931 default:
932 return false;
933 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000934 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000935 if (!success)
936 return false;
937
938 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
939
940 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
941 eRegisterKindGeneric,
942 LLDB_REGNUM_GENERIC_SP,
943 reg_value };
944
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000945 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000946 return false;
947 }
948 return true;
949}
950
Johnny Chen9b8d7832011-02-02 01:13:56 +0000951// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
952// at a PC-relative address, and changes instruction set from ARM to Thumb, or
953// from Thumb to ARM.
954// BLX (immediate)
955bool
956EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
957{
958#if 0
959 // ARM pseudo code...
960 if (ConditionPassed())
961 {
962 EncodingSpecificOperations();
963 if CurrentInstrSet() == InstrSet_ARM then
964 LR = PC - 4;
965 else
966 LR = PC<31:1> : '1';
967 if targetInstrSet == InstrSet_ARM then
968 targetAddress = Align(PC,4) + imm32;
969 else
970 targetAddress = PC + imm32;
971 SelectInstrSet(targetInstrSet);
972 BranchWritePC(targetAddress);
973 }
974#endif
975
976 bool success = false;
977 const uint32_t opcode = OpcodeAsUnsigned (&success);
978 if (!success)
979 return false;
980
981 if (ConditionPassed())
982 {
983 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
984 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000985 if (!success)
986 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000987 addr_t lr; // next instruction address
988 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000989 int32_t imm32; // PC-relative offset
990 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000991 case eEncodingT1:
992 {
993 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000994 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +0000995 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000996 uint32_t J1 = Bit32(opcode, 13);
997 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +0000998 uint32_t imm11 = Bits32(opcode, 10, 0);
999 uint32_t I1 = !(J1 ^ S);
1000 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001001 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001002 imm32 = llvm::SignExtend32<25>(imm25);
1003 target = pc + 4 + imm32;
1004 context.arg1 = 4 + imm32; // signed offset
1005 context.arg2 = eModeThumb; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +00001006 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001007 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001008 break;
1009 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001010 case eEncodingT2:
1011 {
1012 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001013 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001014 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001015 uint32_t J1 = Bit32(opcode, 13);
1016 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001017 uint32_t imm10L = Bits32(opcode, 10, 1);
1018 uint32_t I1 = !(J1 ^ S);
1019 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001020 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001021 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001022 target = Align(pc + 4, 4) + imm32;
1023 context.arg1 = 4 + imm32; // signed offset
1024 context.arg2 = eModeARM; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +00001025 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001026 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001027 break;
1028 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001029 case eEncodingA1:
1030 lr = pc + 4; // return address
1031 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001032 target = Align(pc + 8, 4) + imm32;
1033 context.arg1 = 8 + imm32; // signed offset
1034 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001035 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001036 case eEncodingA2:
1037 lr = pc + 4; // return address
1038 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1039 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001040 context.arg1 = 8 + imm32; // signed offset
1041 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +00001042 break;
1043 default:
1044 return false;
1045 }
1046 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1047 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001048 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001049 return false;
1050 }
1051 return true;
1052}
1053
1054// Branch with Link and Exchange (register) calls a subroutine at an address and
1055// instruction set specified by a register.
1056// BLX (register)
1057bool
1058EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1059{
1060#if 0
1061 // ARM pseudo code...
1062 if (ConditionPassed())
1063 {
1064 EncodingSpecificOperations();
1065 target = R[m];
1066 if CurrentInstrSet() == InstrSet_ARM then
1067 next_instr_addr = PC - 4;
1068 LR = next_instr_addr;
1069 else
1070 next_instr_addr = PC - 2;
1071 LR = next_instr_addr<31:1> : ‘1’;
1072 BXWritePC(target);
1073 }
1074#endif
1075
1076 bool success = false;
1077 const uint32_t opcode = OpcodeAsUnsigned (&success);
1078 if (!success)
1079 return false;
1080
1081 if (ConditionPassed())
1082 {
1083 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1084 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1085 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001086 if (!success)
1087 return false;
1088 uint32_t Rm; // the register with the target address
1089 switch (encoding) {
1090 case eEncodingT1:
1091 lr = (pc + 2) | 1u; // return address
1092 Rm = Bits32(opcode, 6, 3);
1093 // if m == 15 then UNPREDICTABLE;
1094 if (Rm == 15)
1095 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001096 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001097 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001098 break;
1099 case eEncodingA1:
1100 lr = pc + 4; // return address
1101 Rm = Bits32(opcode, 3, 0);
1102 // if m == 15 then UNPREDICTABLE;
1103 if (Rm == 15)
1104 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001105 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001106 default:
1107 return false;
1108 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001109 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1110 if (!success)
1111 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001112 context.arg0 = eRegisterKindDWARF;
1113 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1115 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001116 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001117 return false;
1118 }
1119 return true;
1120}
1121
Johnny Chenab3b3512011-02-12 00:10:51 +00001122// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1123// BX
1124bool
1125EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1126{
1127#if 0
1128 // ARM pseudo code...
1129 if (ConditionPassed())
1130 {
1131 EncodingSpecificOperations();
1132 BXWritePC(R[m]);
1133 }
1134#endif
1135
1136 bool success = false;
1137 const uint32_t opcode = OpcodeAsUnsigned (&success);
1138 if (!success)
1139 return false;
1140
1141 if (ConditionPassed())
1142 {
1143 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1144 uint32_t Rm; // the register with the target address
1145 switch (encoding) {
1146 case eEncodingT1:
1147 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001148 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001149 return false;
1150 break;
1151 case eEncodingA1:
1152 Rm = Bits32(opcode, 3, 0);
1153 break;
1154 default:
1155 return false;
1156 }
1157 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1158 if (!success)
1159 return false;
1160 context.arg0 = eRegisterKindDWARF;
1161 context.arg1 = dwarf_r0 + Rm;
1162 if (!BXWritePC(context, target))
1163 return false;
1164 }
1165 return true;
1166}
1167
Johnny Chen0d0148e2011-01-28 02:26:08 +00001168// Set r7 to point to some ip offset.
1169// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001170bool
1171EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001172{
1173#if 0
1174 // ARM pseudo code...
1175 if (ConditionPassed())
1176 {
1177 EncodingSpecificOperations();
1178 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1179 if d == 15 then // Can only occur for ARM encoding
1180 ALUWritePC(result); // setflags is always FALSE here
1181 else
1182 R[d] = result;
1183 if setflags then
1184 APSR.N = result<31>;
1185 APSR.Z = IsZeroBit(result);
1186 APSR.C = carry;
1187 APSR.V = overflow;
1188 }
1189#endif
1190
1191 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001192 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001193 if (!success)
1194 return false;
1195
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001196 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001197 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001198 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001199 if (!success)
1200 return false;
1201 uint32_t imm32;
1202 switch (encoding) {
1203 case eEncodingA1:
1204 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1205 break;
1206 default:
1207 return false;
1208 }
1209 addr_t ip_offset = imm32;
1210 addr_t addr = ip - ip_offset; // the adjusted ip value
1211
1212 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1213 eRegisterKindDWARF,
1214 dwarf_r12,
1215 -ip_offset };
1216
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001218 return false;
1219 }
1220 return true;
1221}
1222
1223// Set ip to point to some stack offset.
1224// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001225bool
1226EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001227{
1228#if 0
1229 // ARM pseudo code...
1230 if (ConditionPassed())
1231 {
1232 EncodingSpecificOperations();
1233 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1234 if d == 15 then // Can only occur for ARM encoding
1235 ALUWritePC(result); // setflags is always FALSE here
1236 else
1237 R[d] = result;
1238 if setflags then
1239 APSR.N = result<31>;
1240 APSR.Z = IsZeroBit(result);
1241 APSR.C = carry;
1242 APSR.V = overflow;
1243 }
1244#endif
1245
1246 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001247 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001248 if (!success)
1249 return false;
1250
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001251 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001252 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001253 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001254 if (!success)
1255 return false;
1256 uint32_t imm32;
1257 switch (encoding) {
1258 case eEncodingA1:
1259 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1260 break;
1261 default:
1262 return false;
1263 }
1264 addr_t sp_offset = imm32;
1265 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1266
1267 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1268 eRegisterKindGeneric,
1269 LLDB_REGNUM_GENERIC_SP,
1270 -sp_offset };
1271
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001272 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001273 return false;
1274 }
1275 return true;
1276}
1277
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001278// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001279bool
1280EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001281{
1282#if 0
1283 // ARM pseudo code...
1284 if (ConditionPassed())
1285 {
1286 EncodingSpecificOperations();
1287 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1288 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001289 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001290 else
1291 R[d] = result;
1292 if setflags then
1293 APSR.N = result<31>;
1294 APSR.Z = IsZeroBit(result);
1295 APSR.C = carry;
1296 APSR.V = overflow;
1297 }
1298#endif
1299
1300 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001301 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001302 if (!success)
1303 return false;
1304
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001305 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001306 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001307 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001308 if (!success)
1309 return false;
1310 uint32_t imm32;
1311 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001312 case eEncodingT1:
1313 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001314 case eEncodingT2:
1315 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1316 break;
1317 case eEncodingT3:
1318 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1319 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001320 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001321 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001322 break;
1323 default:
1324 return false;
1325 }
1326 addr_t sp_offset = imm32;
1327 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1328
1329 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1330 eRegisterKindGeneric,
1331 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001332 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001333
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001334 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001335 return false;
1336 }
1337 return true;
1338}
1339
Johnny Chen08c25e82011-01-31 18:02:28 +00001340// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001341bool
1342EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001343{
1344#if 0
1345 // ARM pseudo code...
1346 if (ConditionPassed())
1347 {
1348 EncodingSpecificOperations();
1349 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1350 address = if index then offset_addr else R[n];
1351 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1352 if wback then R[n] = offset_addr;
1353 }
1354#endif
1355
1356 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001357 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001358 if (!success)
1359 return false;
1360
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001361 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001362 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001363 const uint32_t addr_byte_size = GetAddressByteSize();
1364 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001365 if (!success)
1366 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001367 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001368 uint32_t imm12;
1369 switch (encoding) {
1370 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001371 Rt = Bits32(opcode, 15, 12);
1372 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001373 break;
1374 default:
1375 return false;
1376 }
1377 addr_t sp_offset = imm12;
1378 addr_t addr = sp - sp_offset;
1379
1380 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001381 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001382 {
Johnny Chen91d99862011-01-25 19:07:04 +00001383 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1384 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001385 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001386 if (!success)
1387 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001388 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001389 return false;
1390 }
1391 else
1392 {
1393 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1394 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001395 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001396 if (!success)
1397 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001398 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001399 return false;
1400 }
1401
1402 context.type = EmulateInstruction::eContextAdjustStackPointer;
1403 context.arg0 = eRegisterKindGeneric;
1404 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001405 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001406
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001407 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001408 return false;
1409 }
1410 return true;
1411}
1412
Johnny Chen08c25e82011-01-31 18:02:28 +00001413// Vector Push stores multiple extension registers to the stack.
1414// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001415bool
1416EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001417{
1418#if 0
1419 // ARM pseudo code...
1420 if (ConditionPassed())
1421 {
1422 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1423 address = SP - imm32;
1424 SP = SP - imm32;
1425 if single_regs then
1426 for r = 0 to regs-1
1427 MemA[address,4] = S[d+r]; address = address+4;
1428 else
1429 for r = 0 to regs-1
1430 // Store as two word-aligned words in the correct order for current endianness.
1431 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1432 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1433 address = address+8;
1434 }
1435#endif
1436
1437 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001438 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001439 if (!success)
1440 return false;
1441
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001442 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001443 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001444 const uint32_t addr_byte_size = GetAddressByteSize();
1445 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001446 if (!success)
1447 return false;
1448 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001449 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001450 uint32_t imm32; // stack offset
1451 uint32_t regs; // number of registers
1452 switch (encoding) {
1453 case eEncodingT1:
1454 case eEncodingA1:
1455 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001456 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001457 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1458 // If UInt(imm8) is odd, see "FSTMX".
1459 regs = Bits32(opcode, 7, 0) / 2;
1460 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1461 if (regs == 0 || regs > 16 || (d + regs) > 32)
1462 return false;
1463 break;
1464 case eEncodingT2:
1465 case eEncodingA2:
1466 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001467 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001468 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1469 regs = Bits32(opcode, 7, 0);
1470 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1471 if (regs == 0 || regs > 16 || (d + regs) > 32)
1472 return false;
1473 break;
1474 default:
1475 return false;
1476 }
1477 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1478 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1479 addr_t sp_offset = imm32;
1480 addr_t addr = sp - sp_offset;
1481 uint32_t i;
1482
1483 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1484 for (i=d; i<regs; ++i)
1485 {
1486 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1487 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1488 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001489 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001490 if (!success)
1491 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001492 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001493 return false;
1494 addr += reg_byte_size;
1495 }
1496
1497 context.type = EmulateInstruction::eContextAdjustStackPointer;
1498 context.arg0 = eRegisterKindGeneric;
1499 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001500 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001501
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001502 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001503 return false;
1504 }
1505 return true;
1506}
1507
Johnny Chen587a0a42011-02-01 18:35:28 +00001508// Vector Pop loads multiple extension registers from the stack.
1509// It also updates SP to point just above the loaded data.
1510bool
1511EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1512{
1513#if 0
1514 // ARM pseudo code...
1515 if (ConditionPassed())
1516 {
1517 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1518 address = SP;
1519 SP = SP + imm32;
1520 if single_regs then
1521 for r = 0 to regs-1
1522 S[d+r] = MemA[address,4]; address = address+4;
1523 else
1524 for r = 0 to regs-1
1525 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1526 // Combine the word-aligned words in the correct order for current endianness.
1527 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1528 }
1529#endif
1530
1531 bool success = false;
1532 const uint32_t opcode = OpcodeAsUnsigned (&success);
1533 if (!success)
1534 return false;
1535
1536 if (ConditionPassed())
1537 {
1538 const uint32_t addr_byte_size = GetAddressByteSize();
1539 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1540 if (!success)
1541 return false;
1542 bool single_regs;
1543 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1544 uint32_t imm32; // stack offset
1545 uint32_t regs; // number of registers
1546 switch (encoding) {
1547 case eEncodingT1:
1548 case eEncodingA1:
1549 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001550 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001551 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1552 // If UInt(imm8) is odd, see "FLDMX".
1553 regs = Bits32(opcode, 7, 0) / 2;
1554 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1555 if (regs == 0 || regs > 16 || (d + regs) > 32)
1556 return false;
1557 break;
1558 case eEncodingT2:
1559 case eEncodingA2:
1560 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001561 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001562 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1563 regs = Bits32(opcode, 7, 0);
1564 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1565 if (regs == 0 || regs > 16 || (d + regs) > 32)
1566 return false;
1567 break;
1568 default:
1569 return false;
1570 }
1571 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1572 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1573 addr_t sp_offset = imm32;
1574 addr_t addr = sp;
1575 uint32_t i;
1576 uint64_t data; // uint64_t to accomodate 64-bit registers.
1577
1578 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1579 for (i=d; i<regs; ++i)
1580 {
1581 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1582 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1583 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1584 if (!success)
1585 return false;
1586 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1587 return false;
1588 addr += reg_byte_size;
1589 }
1590
1591 context.type = EmulateInstruction::eContextAdjustStackPointer;
1592 context.arg0 = eRegisterKindGeneric;
1593 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1594 context.arg2 = sp_offset;
1595
1596 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1597 return false;
1598 }
1599 return true;
1600}
1601
Johnny Chenb77be412011-02-04 00:40:18 +00001602// SVC (previously SWI)
1603bool
1604EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1605{
1606#if 0
1607 // ARM pseudo code...
1608 if (ConditionPassed())
1609 {
1610 EncodingSpecificOperations();
1611 CallSupervisor();
1612 }
1613#endif
1614
1615 bool success = false;
1616 const uint32_t opcode = OpcodeAsUnsigned (&success);
1617 if (!success)
1618 return false;
1619
1620 if (ConditionPassed())
1621 {
1622 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1623 addr_t lr; // next instruction address
1624 if (!success)
1625 return false;
1626 uint32_t imm32; // the immediate constant
1627 uint32_t mode; // ARM or Thumb mode
1628 switch (encoding) {
1629 case eEncodingT1:
1630 lr = (pc + 2) | 1u; // return address
1631 imm32 = Bits32(opcode, 7, 0);
1632 mode = eModeThumb;
1633 break;
1634 case eEncodingA1:
1635 lr = pc + 4; // return address
1636 imm32 = Bits32(opcode, 23, 0);
1637 mode = eModeARM;
1638 break;
1639 default:
1640 return false;
1641 }
1642 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1643 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1644 return false;
1645 }
1646 return true;
1647}
1648
Johnny Chenc315f862011-02-05 00:46:10 +00001649// If Then makes up to four following instructions (the IT block) conditional.
1650bool
1651EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1652{
1653#if 0
1654 // ARM pseudo code...
1655 EncodingSpecificOperations();
1656 ITSTATE.IT<7:0> = firstcond:mask;
1657#endif
1658
1659 bool success = false;
1660 const uint32_t opcode = OpcodeAsUnsigned (&success);
1661 if (!success)
1662 return false;
1663
1664 m_it_session.InitIT(Bits32(opcode, 7, 0));
1665 return true;
1666}
1667
Johnny Chen3b620b32011-02-07 20:11:47 +00001668// Branch causes a branch to a target address.
1669bool
1670EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1671{
1672#if 0
1673 // ARM pseudo code...
1674 if (ConditionPassed())
1675 {
1676 EncodingSpecificOperations();
1677 BranchWritePC(PC + imm32);
1678 }
1679#endif
1680
1681 bool success = false;
1682 const uint32_t opcode = OpcodeAsUnsigned (&success);
1683 if (!success)
1684 return false;
1685
Johnny Chen9ee056b2011-02-08 00:06:35 +00001686 if (ConditionPassed())
1687 {
1688 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1689 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001690 if (!success)
1691 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001692 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001693 int32_t imm32; // PC-relative offset
1694 switch (encoding) {
1695 case eEncodingT1:
1696 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1697 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1698 target = pc + 4 + imm32;
1699 context.arg1 = 4 + imm32; // signed offset
1700 context.arg2 = eModeThumb; // target instruction set
1701 break;
1702 case eEncodingT2:
1703 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1704 target = pc + 4 + imm32;
1705 context.arg1 = 4 + imm32; // signed offset
1706 context.arg2 = eModeThumb; // target instruction set
1707 break;
1708 case eEncodingT3:
1709 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1710 {
Johnny Chenbd599902011-02-10 21:39:01 +00001711 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001712 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001713 uint32_t J1 = Bit32(opcode, 13);
1714 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001715 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001716 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001717 imm32 = llvm::SignExtend32<21>(imm21);
1718 target = pc + 4 + imm32;
1719 context.arg1 = eModeThumb; // target instruction set
1720 context.arg2 = 4 + imm32; // signed offset
1721 break;
1722 }
1723 case eEncodingT4:
1724 {
Johnny Chenbd599902011-02-10 21:39:01 +00001725 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001726 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001727 uint32_t J1 = Bit32(opcode, 13);
1728 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001729 uint32_t imm11 = Bits32(opcode, 10, 0);
1730 uint32_t I1 = !(J1 ^ S);
1731 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001732 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001733 imm32 = llvm::SignExtend32<25>(imm25);
1734 target = pc + 4 + imm32;
1735 context.arg1 = eModeThumb; // target instruction set
1736 context.arg2 = 4 + imm32; // signed offset
1737 break;
1738 }
1739 case eEncodingA1:
1740 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1741 target = pc + 8 + imm32;
1742 context.arg1 = eModeARM; // target instruction set
1743 context.arg2 = 8 + imm32; // signed offset
1744 break;
1745 default:
1746 return false;
1747 }
1748 if (!BranchWritePC(context, target))
1749 return false;
1750 }
1751 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001752}
1753
Johnny Chen53ebab72011-02-08 23:21:57 +00001754// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1755// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1756// CBNZ, CBZ
1757bool
1758EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1759{
1760#if 0
1761 // ARM pseudo code...
1762 EncodingSpecificOperations();
1763 if nonzero ^ IsZero(R[n]) then
1764 BranchWritePC(PC + imm32);
1765#endif
1766
1767 bool success = false;
1768 const uint32_t opcode = OpcodeAsUnsigned (&success);
1769 if (!success)
1770 return false;
1771
1772 // Read the register value from the operand register Rn.
1773 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1774 if (!success)
1775 return false;
1776
1777 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1778 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1779 if (!success)
1780 return false;
1781
1782 addr_t target; // target address
1783 uint32_t imm32; // PC-relative offset to branch forward
1784 bool nonzero;
1785 switch (encoding) {
1786 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001787 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001788 nonzero = BitIsSet(opcode, 11);
1789 target = pc + 4 + imm32;
1790 context.arg1 = 4 + imm32; // signed offset
1791 context.arg2 = eModeThumb; // target instruction set
1792 break;
1793 default:
1794 return false;
1795 }
1796 if (nonzero ^ (reg_val == 0))
1797 if (!BranchWritePC(context, target))
1798 return false;
1799
1800 return true;
1801}
1802
Johnny Chen26863dc2011-02-09 23:43:29 +00001803// ADD <Rdn>, <Rm>
1804// where <Rdn> the destination register is also the first operand register
1805// and <Rm> is the second operand register.
1806bool
1807EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1808{
1809#if 0
1810 // ARM pseudo code...
1811 if ConditionPassed() then
1812 EncodingSpecificOperations();
1813 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1814 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1815 if d == 15 then
1816 ALUWritePC(result); // setflags is always FALSE here
1817 else
1818 R[d] = result;
1819 if setflags then
1820 APSR.N = result<31>;
1821 APSR.Z = IsZeroBit(result);
1822 APSR.C = carry;
1823 APSR.V = overflow;
1824#endif
1825
1826 bool success = false;
1827 const uint32_t opcode = OpcodeAsUnsigned (&success);
1828 if (!success)
1829 return false;
1830
1831 if (ConditionPassed())
1832 {
1833 uint32_t Rd, Rn, Rm;
1834 //bool setflags = false;
1835 switch (encoding)
1836 {
1837 case eEncodingT2:
1838 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001839 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001840 Rm = Bits32(opcode, 6, 3);
1841 if (Rn == 15 && Rm == 15)
1842 return false;
1843 break;
1844 default:
1845 return false;
1846 }
1847
1848 int32_t result, val1, val2;
1849 // Read the first operand.
1850 if (Rn == 15)
1851 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1852 else
1853 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1854 if (!success)
1855 return false;
1856
1857 // Read the second operand.
1858 if (Rm == 15)
1859 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1860 else
1861 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1862 if (!success)
1863 return false;
1864
1865 result = val1 + val2;
1866 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001867 0,
Johnny Chen26863dc2011-02-09 23:43:29 +00001868 0,
1869 0 };
1870
1871 if (Rd == 15)
1872 {
1873 if (!ALUWritePC (context, result))
1874 return false;
1875 }
1876 else
1877 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001879 return false;
1880 }
1881 }
1882 return true;
1883}
1884
Johnny Chene4a4d302011-02-11 21:53:58 +00001885// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001886bool
1887EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1888{
1889#if 0
1890 // ARM pseudo code...
1891 if ConditionPassed() then
1892 EncodingSpecificOperations();
1893 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1894 APSR.N = result<31>;
1895 APSR.Z = IsZeroBit(result);
1896 APSR.C = carry;
1897 APSR.V = overflow;
1898#endif
1899
1900 bool success = false;
1901 const uint32_t opcode = OpcodeAsUnsigned (&success);
1902 if (!success)
1903 return false;
1904
1905 uint32_t Rn; // the first operand
1906 uint32_t imm32; // the immediate value to be compared with
1907 switch (encoding) {
1908 case eEncodingT1:
1909 Rn = Bits32(opcode, 10, 8);
1910 imm32 = Bits32(opcode, 7, 0);
1911 break;
1912 default:
1913 return false;
1914 }
1915 // Read the register value from the operand register Rn.
1916 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1917 if (!success)
1918 return false;
1919
Johnny Chend4dc4442011-02-11 02:02:56 +00001920 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1921 m_new_inst_cpsr = m_inst_cpsr;
1922 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1923 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1924 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1925 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1926 if (m_new_inst_cpsr != m_inst_cpsr)
1927 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001928 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
Johnny Chend4dc4442011-02-11 02:02:56 +00001929 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1930 return false;
1931 }
1932 return true;
1933}
1934
Johnny Chene4a4d302011-02-11 21:53:58 +00001935// CMP (register)
1936bool
1937EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1938{
1939#if 0
1940 // ARM pseudo code...
1941 if ConditionPassed() then
1942 EncodingSpecificOperations();
1943 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1944 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1945 APSR.N = result<31>;
1946 APSR.Z = IsZeroBit(result);
1947 APSR.C = carry;
1948 APSR.V = overflow;
1949#endif
1950
1951 bool success = false;
1952 const uint32_t opcode = OpcodeAsUnsigned (&success);
1953 if (!success)
1954 return false;
1955
1956 uint32_t Rn; // the first operand
1957 uint32_t Rm; // the second operand
1958 switch (encoding) {
1959 case eEncodingT1:
1960 Rn = Bits32(opcode, 2, 0);
1961 Rm = Bits32(opcode, 5, 3);
1962 break;
1963 case eEncodingT2:
1964 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1965 Rm = Bits32(opcode, 6, 3);
1966 if (Rn < 8 && Rm < 8)
1967 return false;
1968 if (Rn == 15 || Rm == 15)
1969 return false;
1970 break;
1971 default:
1972 return false;
1973 }
1974 // Read the register value from register Rn.
1975 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1976 if (!success)
1977 return false;
1978 // Read the register value from register Rm.
1979 // The register value is not being shifted since we don't handle ARM for now.
1980 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1981 if (!success)
1982 return false;
1983
Johnny Chene4a4d302011-02-11 21:53:58 +00001984 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
1985 m_new_inst_cpsr = m_inst_cpsr;
1986 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1987 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1988 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1989 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1990 if (m_new_inst_cpsr != m_inst_cpsr)
1991 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001992 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
Johnny Chene4a4d302011-02-11 21:53:58 +00001993 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1994 return false;
1995 }
1996 return true;
1997}
1998
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001999// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002000// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002001// can be written back to the base register.
2002bool
2003EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2004{
2005#if 0
2006 // ARM pseudo code...
2007 if ConditionPassed()
2008 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2009 address = R[n];
2010
2011 for i = 0 to 14
2012 if registers<i> == '1' then
2013 R[i] = MemA[address, 4]; address = address + 4;
2014 if registers<15> == '1' then
2015 LoadWritePC (MemA[address, 4]);
2016
2017 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2018 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2019
2020#endif
2021
2022 bool success = false;
2023 const uint32_t opcode = OpcodeAsUnsigned (&success);
2024 if (!success)
2025 return false;
2026
2027 if (ConditionPassed())
2028 {
2029 uint32_t n;
2030 uint32_t registers = 0;
2031 bool wback;
2032 const uint32_t addr_byte_size = GetAddressByteSize();
2033 switch (encoding)
2034 {
2035 case eEncodingT1:
2036 n = Bits32 (opcode, 10, 8);
2037 registers = Bits32 (opcode, 7, 0);
2038 wback = BitIsClear (registers, n);
2039 // if BitCount(registers) < 1 then UNPREDICTABLE;
2040 if (BitCount(registers) < 1)
2041 return false;
2042 break;
2043 case eEncodingT2:
2044 n = Bits32 (opcode, 19, 16);
2045 registers = Bits32 (opcode, 15, 0);
2046 wback = BitIsSet (opcode, 21);
2047 if ((n == 15)
2048 || (BitCount (registers) < 2)
2049 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2050 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002051 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002052 return false;
2053 if (wback
2054 && BitIsSet (registers, n))
2055 return false;
2056 break;
2057 case eEncodingA1:
2058 n = Bits32 (opcode, 19, 16);
2059 registers = Bits32 (opcode, 15, 0);
2060 wback = BitIsSet (opcode, 21);
2061 if ((n == 15)
2062 || (BitCount (registers) < 1))
2063 return false;
2064 break;
2065 default:
2066 return false;
2067 }
2068
2069 int32_t offset = 0;
2070 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2071 if (!success)
2072 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002073
2074 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2075 eRegisterKindDWARF,
2076 dwarf_r0 + n,
2077 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002078
2079 for (int i = 0; i < 14; ++i)
2080 {
2081 if (BitIsSet (registers, i))
2082 {
Caroline Tice85aab332011-02-08 23:56:10 +00002083 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2084 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002085 if (wback && (n == 13)) // Pop Instruction
2086 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2087
2088 // R[i] = MemA [address, 4]; address = address + 4;
2089 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2090 if (!success)
2091 return false;
2092
2093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2094 return false;
2095
2096 offset += addr_byte_size;
2097 }
2098 }
2099
2100 if (BitIsSet (registers, 15))
2101 {
2102 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002103 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2104 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002105 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2106 if (!success)
2107 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002108 // In ARMv5T and above, this is an interworking branch.
2109 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002110 return false;
2111 }
2112
2113 if (wback && BitIsClear (registers, n))
2114 {
Caroline Ticefa172202011-02-11 22:49:54 +00002115 // R[n] = R[n] + 4 * BitCount (registers)
2116 int32_t offset = addr_byte_size * BitCount (registers);
2117 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice85aab332011-02-08 23:56:10 +00002118 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002119
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002120 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2121 return false;
2122 }
2123 if (wback && BitIsSet (registers, n))
2124 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002125 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002126 }
2127 return true;
2128}
Caroline Tice713c2662011-02-11 17:59:55 +00002129
2130// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2131// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2132// can optionally be written back tot he base registers.
2133bool
2134EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2135{
2136#if 0
2137 // ARM pseudo code...
2138 if ConditionPassed() then
2139 EncodingSpecificOperations();
2140 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002141
Caroline Tice713c2662011-02-11 17:59:55 +00002142 for i = 0 to 14
2143 if registers<i> == ’1’ then
2144 R[i] = MemA[address,4]; address = address + 4;
2145
2146 if registers<15> == ’1’ then
2147 LoadWritePC(MemA[address,4]);
2148
2149 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2150 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2151#endif
2152
2153 bool success = false;
2154 const uint32_t opcode = OpcodeAsUnsigned (&success);
2155 if (!success)
2156 return false;
2157
2158 if (ConditionPassed())
2159 {
2160 uint32_t n;
2161 uint32_t registers = 0;
2162 bool wback;
2163 const uint32_t addr_byte_size = GetAddressByteSize();
2164
2165 // EncodingSpecificOperations();
2166 switch (encoding)
2167 {
2168 case eEncodingA1:
2169 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2170 n = Bits32 (opcode, 19, 16);
2171 registers = Bits32 (opcode, 15, 0);
2172 wback = BitIsSet (opcode, 21);
2173
2174 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2175 if ((n == 15) || (BitCount (registers) < 1))
2176 return false;
2177
2178 break;
2179
2180 default:
2181 return false;
2182 }
2183 // address = R[n] - 4*BitCount(registers) + 4;
2184
2185 int32_t offset = 0;
2186 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2187
2188 if (!success)
2189 return false;
2190
2191 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2192
2193 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2194 eRegisterKindDWARF,
2195 dwarf_r0 + n,
2196 offset };
2197
2198 // for i = 0 to 14
2199 for (int i = 0; i < 14; ++i)
2200 {
2201 // if registers<i> == ’1’ then
2202 if (BitIsSet (registers, i))
2203 {
2204 // R[i] = MemA[address,4]; address = address + 4;
2205 context.arg2 = offset;
2206 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2207 if (!success)
2208 return false;
2209 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2210 return false;
2211 offset += addr_byte_size;
2212 }
2213 }
2214
2215 // if registers<15> == ’1’ then
2216 // LoadWritePC(MemA[address,4]);
2217 if (BitIsSet (registers, 15))
2218 {
2219 context.arg2 = offset;
2220 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2221 if (!success)
2222 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002223 // In ARMv5T and above, this is an interworking branch.
2224 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002225 return false;
2226 }
2227
2228 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2229 if (wback && BitIsClear (registers, n))
2230 {
Caroline Tice713c2662011-02-11 17:59:55 +00002231 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2232 if (!success)
2233 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002234
2235 offset = (addr_byte_size * BitCount (registers)) * -1;
2236 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2237 context.arg2 = offset;
2238 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002239 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2240 return false;
2241 }
2242
2243 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2244 if (wback && BitIsSet (registers, n))
2245 return WriteBits32Unknown (n);
2246 }
2247 return true;
2248}
2249
2250// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2251// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2252// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002253bool
2254EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2255{
2256#if 0
2257 // ARM pseudo code...
2258 if ConditionPassed() then
2259 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2260 address = R[n] - 4*BitCount(registers);
2261
2262 for i = 0 to 14
2263 if registers<i> == ’1’ then
2264 R[i] = MemA[address,4]; address = address + 4;
2265 if registers<15> == ’1’ then
2266 LoadWritePC(MemA[address,4]);
2267
2268 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2269 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2270#endif
2271
2272 bool success = false;
2273 const uint32_t opcode = OpcodeAsUnsigned (&success);
2274 if (!success)
2275 return false;
2276
2277 if (ConditionPassed())
2278 {
2279 uint32_t n;
2280 uint32_t registers = 0;
2281 bool wback;
2282 const uint32_t addr_byte_size = GetAddressByteSize();
2283 switch (encoding)
2284 {
2285 case eEncodingT1:
2286 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2287 n = Bits32 (opcode, 19, 16);
2288 registers = Bits32 (opcode, 15, 0);
2289 wback = BitIsSet (opcode, 21);
2290
2291 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2292 if ((n == 15)
2293 || (BitCount (registers) < 2)
2294 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2295 return false;
2296
2297 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002298 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002299 return false;
2300
2301 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2302 if (wback && BitIsSet (registers, n))
2303 return false;
2304
2305 break;
2306
2307 case eEncodingA1:
2308 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2309 n = Bits32 (opcode, 19, 16);
2310 registers = Bits32 (opcode, 15, 0);
2311 wback = BitIsSet (opcode, 21);
2312
2313 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2314 if ((n == 15) || (BitCount (registers) < 1))
2315 return false;
2316
2317 break;
2318
2319 default:
2320 return false;
2321 }
2322
Caroline Tice713c2662011-02-11 17:59:55 +00002323 // address = R[n] - 4*BitCount(registers);
2324
Caroline Tice0b29e242011-02-08 23:16:02 +00002325 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002326 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2327
2328 if (!success)
2329 return false;
2330
2331 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002332 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2333 eRegisterKindDWARF,
2334 dwarf_r0 + n,
2335 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002336
2337 for (int i = 0; i < 14; ++i)
2338 {
2339 if (BitIsSet (registers, i))
2340 {
2341 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002342 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002343 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2344 if (!success)
2345 return false;
2346
2347 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2348 return false;
2349
2350 offset += addr_byte_size;
2351 }
2352 }
2353
2354 // if registers<15> == ’1’ then
2355 // LoadWritePC(MemA[address,4]);
2356 if (BitIsSet (registers, 15))
2357 {
Caroline Tice85aab332011-02-08 23:56:10 +00002358 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002359 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2360 if (!success)
2361 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002362 // In ARMv5T and above, this is an interworking branch.
2363 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002364 return false;
2365 }
2366
2367 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2368 if (wback && BitIsClear (registers, n))
2369 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002370 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2371 if (!success)
2372 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002373
2374 offset = (addr_byte_size * BitCount (registers)) * -1;
2375 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2376 context.arg2 = offset;
2377 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002378 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2379 return false;
2380 }
2381
2382 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2383 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002384 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002385 }
2386 return true;
2387}
Caroline Tice85aab332011-02-08 23:56:10 +00002388
Caroline Tice713c2662011-02-11 17:59:55 +00002389// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2390// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2391// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002392bool
2393EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2394{
2395#if 0
2396 if ConditionPassed() then
2397 EncodingSpecificOperations();
2398 address = R[n] + 4;
2399
2400 for i = 0 to 14
2401 if registers<i> == ’1’ then
2402 R[i] = MemA[address,4]; address = address + 4;
2403 if registers<15> == ’1’ then
2404 LoadWritePC(MemA[address,4]);
2405
2406 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2407 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2408#endif
2409
2410 bool success = false;
2411 const uint32_t opcode = OpcodeAsUnsigned (&success);
2412 if (!success)
2413 return false;
2414
2415 if (ConditionPassed())
2416 {
2417 uint32_t n;
2418 uint32_t registers = 0;
2419 bool wback;
2420 const uint32_t addr_byte_size = GetAddressByteSize();
2421 switch (encoding)
2422 {
2423 case eEncodingA1:
2424 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2425 n = Bits32 (opcode, 19, 16);
2426 registers = Bits32 (opcode, 15, 0);
2427 wback = BitIsSet (opcode, 21);
2428
2429 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2430 if ((n == 15) || (BitCount (registers) < 1))
2431 return false;
2432
2433 break;
2434 default:
2435 return false;
2436 }
2437 // address = R[n] + 4;
2438
2439 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002440 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2441
2442 if (!success)
2443 return false;
2444
2445 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002446
2447 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2448 eRegisterKindDWARF,
2449 dwarf_r0 + n,
2450 offset };
2451
2452 for (int i = 0; i < 14; ++i)
2453 {
2454 if (BitIsSet (registers, i))
2455 {
2456 // R[i] = MemA[address,4]; address = address + 4;
2457
2458 context.arg2 = offset;
2459 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2460 if (!success)
2461 return false;
2462
2463 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2464 return false;
2465
2466 offset += addr_byte_size;
2467 }
2468 }
2469
2470 // if registers<15> == ’1’ then
2471 // LoadWritePC(MemA[address,4]);
2472 if (BitIsSet (registers, 15))
2473 {
2474 context.arg2 = offset;
2475 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2476 if (!success)
2477 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002478 // In ARMv5T and above, this is an interworking branch.
2479 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002480 return false;
2481 }
2482
2483 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2484 if (wback && BitIsClear (registers, n))
2485 {
Caroline Tice85aab332011-02-08 23:56:10 +00002486 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2487 if (!success)
2488 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002489
2490 offset = addr_byte_size * BitCount (registers);
2491 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2492 context.arg2 = offset;
2493 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2495 return false;
2496 }
2497
2498 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2499 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002500 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002501 }
2502 return true;
2503}
Caroline Tice0b29e242011-02-08 23:16:02 +00002504
Johnny Chenef21b592011-02-10 01:52:38 +00002505// Load Register (immediate) calculates an address from a base register value and
2506// an immediate offset, loads a word from memory, and writes to a register.
2507// LDR (immediate, Thumb)
2508bool
2509EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2510{
2511#if 0
2512 // ARM pseudo code...
2513 if (ConditionPassed())
2514 {
2515 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2516 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2517 address = if index then offset_addr else R[n];
2518 data = MemU[address,4];
2519 if wback then R[n] = offset_addr;
2520 if t == 15 then
2521 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2522 elsif UnalignedSupport() || address<1:0> = '00' then
2523 R[t] = data;
2524 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2525 }
2526#endif
2527
2528 bool success = false;
2529 const uint32_t opcode = OpcodeAsUnsigned (&success);
2530 if (!success)
2531 return false;
2532
2533 if (ConditionPassed())
2534 {
2535 uint32_t Rt; // the destination register
2536 uint32_t Rn; // the base register
2537 uint32_t imm32; // the immediate offset used to form the address
2538 addr_t offset_addr; // the offset address
2539 addr_t address; // the calculated address
2540 uint32_t data; // the literal data value from memory load
2541 bool add, index, wback;
2542 switch (encoding) {
2543 case eEncodingT1:
2544 Rt = Bits32(opcode, 5, 3);
2545 Rn = Bits32(opcode, 2, 0);
2546 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2547 // index = TRUE; add = TRUE; wback = FALSE
2548 add = true;
2549 index = true;
2550 wback = false;
2551 break;
2552 default:
2553 return false;
2554 }
2555 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2556 if (!success)
2557 return false;
2558 if (add)
2559 offset_addr = base + imm32;
2560 else
2561 offset_addr = base - imm32;
2562
2563 address = (index ? offset_addr : base);
2564
2565 if (wback)
2566 {
2567 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2568 eRegisterKindDWARF,
2569 dwarf_r0 + Rn,
2570 (int32_t) (offset_addr - base)};
2571 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2572 return false;
2573 }
2574
2575 // Prepare to write to the Rt register.
2576 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2577 0,
2578 0,
2579 0};
2580
2581 // Read memory from the address.
2582 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2583 if (!success)
2584 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00002585
2586 if (Rt == 15)
2587 {
2588 if (Bits32(address, 1, 0) == 0)
2589 {
2590 if (!LoadWritePC(context, data))
2591 return false;
2592 }
2593 else
2594 return false;
2595 }
2596 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2597 {
2598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2599 return false;
2600 }
2601 else
2602 return false;
2603 }
2604 return true;
2605}
2606
Caroline Ticefa172202011-02-11 22:49:54 +00002607// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2608// consecutive memory locations start at this address, and teh address just above the last of those locations can
2609// optionally be written back to the base register.
2610bool
2611EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2612{
2613#if 0
2614 if ConditionPassed() then
2615 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2616 address = R[n];
2617
2618 for i = 0 to 14
2619 if registers<i> == ’1’ then
2620 if i == n && wback && i != LowestSetBit(registers) then
2621 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2622 else
2623 MemA[address,4] = R[i];
2624 address = address + 4;
2625
2626 if registers<15> == ’1’ then // Only possible for encoding A1
2627 MemA[address,4] = PCStoreValue();
2628 if wback then R[n] = R[n] + 4*BitCount(registers);
2629#endif
2630
2631 bool success = false;
2632 const uint32_t opcode = OpcodeAsUnsigned (&success);
2633 if (!success)
2634 return false;
2635
2636 if (ConditionPassed ())
2637 {
2638 uint32_t n;
2639 uint32_t registers = 0;
2640 bool wback;
2641 const uint32_t addr_byte_size = GetAddressByteSize();
2642
2643 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2644 switch (encoding)
2645 {
2646 case eEncodingT1:
2647 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2648 n = Bits32 (opcode, 10, 8);
2649 registers = Bits32 (opcode, 7, 0);
2650 wback = true;
2651
2652 // if BitCount(registers) < 1 then UNPREDICTABLE;
2653 if (BitCount (registers) < 1)
2654 return false;
2655
2656 break;
2657
2658 case eEncodingT2:
2659 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2660 n = Bits32 (opcode, 19, 16);
2661 registers = Bits32 (opcode, 15, 0);
2662 wback = BitIsSet (opcode, 21);
2663
2664 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2665 if ((n == 15) || (BitCount (registers) < 2))
2666 return false;
2667
2668 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2669 if (wback && BitIsSet (registers, n))
2670 return false;
2671
2672 break;
2673
2674 case eEncodingA1:
2675 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2676 n = Bits32 (opcode, 19, 16);
2677 registers = Bits32 (opcode, 15, 0);
2678 wback = BitIsSet (opcode, 21);
2679
2680 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2681 if ((n == 15) || (BitCount (registers) < 1))
2682 return false;
2683
2684 break;
2685
2686 default:
2687 return false;
2688 }
2689
2690 // address = R[n];
2691 int32_t offset = 0;
2692 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2693 if (!success)
2694 return false;
2695
2696 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterStore,
2697 eRegisterKindDWARF,
2698 dwarf_r0 + n,
2699 offset };
2700
2701 // for i = 0 to 14
2702 for (int i = 0; i < 14; ++i)
2703 {
2704 int lowest_set_bit = 14;
2705 // if registers<i> == ’1’ then
2706 if (BitIsSet (registers, i))
2707 {
2708 if (i < lowest_set_bit)
2709 lowest_set_bit = i;
2710 // if i == n && wback && i != LowestSetBit(registers) then
2711 if ((i == n) && wback && (i != lowest_set_bit))
2712 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2713 WriteBits32UnknownToMemory (address + offset);
2714 else
2715 {
2716 // MemA[address,4] = R[i];
2717 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2718 if (!success)
2719 return false;
2720
2721 context.arg1 = dwarf_r0 + i;
2722 context.arg2 = address + offset;
2723 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2724 return false;
2725 }
2726
2727 // address = address + 4;
2728 offset += addr_byte_size;
2729 }
2730 }
2731
2732 // if registers<15> == ’1’ then // Only possible for encoding A1
2733 // MemA[address,4] = PCStoreValue();
2734 if (BitIsSet (registers, 15))
2735 {
2736 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2737 if (!success)
2738 return false;
2739
2740 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
2741 context.arg2 = address + offset - sp; // arg2 in the context is the stack pointer offset
2742 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2743 if (!success)
2744 return false;
2745
2746 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2747 return false;
2748 }
2749
2750 // if wback then R[n] = R[n] + 4*BitCount(registers);
2751 if (wback)
2752 {
2753 offset = addr_byte_size * BitCount (registers);
2754 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2755 context.arg1 = dwarf_r0 + n;
2756 context.arg2 = offset;
2757 addr_t data = address + offset;
2758 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2759 return false;
2760 }
2761 }
2762 return true;
2763}
2764
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002765EmulateInstructionARM::ARMOpcode*
2766EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002767{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002768 static ARMOpcode
2769 g_arm_opcodes[] =
2770 {
2771 //----------------------------------------------------------------------
2772 // Prologue instructions
2773 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002774
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002775 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002776 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2777 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002778
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002779 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002780 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2781 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002782 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002783 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2784 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2785 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002786
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002787 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002788 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002789
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002790 // push one register
2791 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002792 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002793
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002794 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002795 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2796 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002797
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002798 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002799 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002800 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002801
Johnny Chenc28a76d2011-02-01 18:51:48 +00002802 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2803 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002804 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002805 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2806
2807 //----------------------------------------------------------------------
2808 // Supervisor Call (previously Software Interrupt)
2809 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002810 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2811
2812 //----------------------------------------------------------------------
2813 // Branch instructions
2814 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002815 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002816 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2817 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2818 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2819 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002820 // for example, "bx lr"
2821 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002822
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002823 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00002824 // Data-processing instructions
2825 //----------------------------------------------------------------------
2826 // move bitwise not
2827 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
2828
2829 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002830 // Load instructions
2831 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002832 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002833 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002834 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002835 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2836
2837 //----------------------------------------------------------------------
2838 // Store instructions
2839 //----------------------------------------------------------------------
2840 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002841
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002842 };
2843 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2844
2845 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2846 {
2847 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2848 return &g_arm_opcodes[i];
2849 }
2850 return NULL;
2851}
Greg Clayton64c84432011-01-21 22:02:52 +00002852
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002853
2854EmulateInstructionARM::ARMOpcode*
2855EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002856{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002857
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002858 static ARMOpcode
2859 g_thumb_opcodes[] =
2860 {
2861 //----------------------------------------------------------------------
2862 // Prologue instructions
2863 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002864
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002865 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002866 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002867 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2868 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002869
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002870 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002871 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002872 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002873 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002874 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2875 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002876
Johnny Chenc9de9102011-02-11 19:12:30 +00002877 // PC-relative load into register (see also EmulateAddSPRm)
2878 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002879
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002880 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002881 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2882 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002883 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2884 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002885
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002886 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002887 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2888 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002889
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002890 //----------------------------------------------------------------------
2891 // Epilogue instructions
2892 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002893
Johnny Chenc28a76d2011-02-01 18:51:48 +00002894 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2895 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002896 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2897 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2898 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2899 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002900
2901 //----------------------------------------------------------------------
2902 // Supervisor Call (previously Software Interrupt)
2903 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002904 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2905
2906 //----------------------------------------------------------------------
2907 // If Then makes up to four following instructions conditional.
2908 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002909 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2910
2911 //----------------------------------------------------------------------
2912 // Branch instructions
2913 //----------------------------------------------------------------------
2914 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2915 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2916 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002917 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002918 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00002919 // J1 == J2 == 1
2920 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2921 // J1 == J2 == 1
2922 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2923 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002924 // for example, "bx lr"
2925 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002926 // compare and branch
2927 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002928
2929 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002930 // Data-processing instructions
2931 //----------------------------------------------------------------------
2932 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2933 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002934 // move from high register to high register
2935 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2936 // move from low register to low register
2937 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00002938 // move bitwise not
2939 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00002940 // compare a register with immediate
2941 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00002942 // compare Rn with Rm (Rn and Rm both from r0-r7)
2943 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
2944 // compare Rn with Rm (Rn and Rm not both from r0-r7)
2945 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002946
2947 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002948 // Load instructions
2949 //----------------------------------------------------------------------
2950 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002951 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002952 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00002953 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
2954 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00002955 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
2956
2957 //----------------------------------------------------------------------
2958 // Store instructions
2959 //----------------------------------------------------------------------
2960 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
2961 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002962
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002963 };
2964
2965 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2966 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2967 {
2968 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2969 return &g_thumb_opcodes[i];
2970 }
2971 return NULL;
2972}
Greg Clayton64c84432011-01-21 22:02:52 +00002973
Greg Clayton31e2a382011-01-30 20:03:56 +00002974bool
2975EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2976{
2977 m_arm_isa = 0;
2978 const char *triple_cstr = triple.GetCString();
2979 if (triple_cstr)
2980 {
2981 const char *dash = ::strchr (triple_cstr, '-');
2982 if (dash)
2983 {
2984 std::string arch (triple_cstr, dash);
2985 const char *arch_cstr = arch.c_str();
2986 if (strcasecmp(arch_cstr, "armv4t") == 0)
2987 m_arm_isa = ARMv4T;
2988 else if (strcasecmp(arch_cstr, "armv4") == 0)
2989 m_arm_isa = ARMv4;
2990 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2991 m_arm_isa = ARMv5TEJ;
2992 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2993 m_arm_isa = ARMv5TE;
2994 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2995 m_arm_isa = ARMv5T;
2996 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2997 m_arm_isa = ARMv6K;
2998 else if (strcasecmp(arch_cstr, "armv6") == 0)
2999 m_arm_isa = ARMv6;
3000 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
3001 m_arm_isa = ARMv6T2;
3002 else if (strcasecmp(arch_cstr, "armv7") == 0)
3003 m_arm_isa = ARMv7;
3004 else if (strcasecmp(arch_cstr, "armv8") == 0)
3005 m_arm_isa = ARMv8;
3006 }
3007 }
3008 return m_arm_isa != 0;
3009}
3010
3011
Greg Clayton64c84432011-01-21 22:02:52 +00003012bool
3013EmulateInstructionARM::ReadInstruction ()
3014{
3015 bool success = false;
3016 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
3017 if (success)
3018 {
3019 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
3020 if (success)
3021 {
3022 Context read_inst_context = {eContextReadOpcode, 0, 0};
3023 if (m_inst_cpsr & MASK_CPSR_T)
3024 {
3025 m_inst_mode = eModeThumb;
3026 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
3027
3028 if (success)
3029 {
3030 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
3031 {
3032 m_inst.opcode_type = eOpcode16;
3033 m_inst.opcode.inst16 = thumb_opcode;
3034 }
3035 else
3036 {
3037 m_inst.opcode_type = eOpcode32;
3038 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
3039 }
3040 }
3041 }
3042 else
3043 {
3044 m_inst_mode = eModeARM;
3045 m_inst.opcode_type = eOpcode32;
3046 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
3047 }
3048 }
3049 }
3050 if (!success)
3051 {
3052 m_inst_mode = eModeInvalid;
3053 m_inst_pc = LLDB_INVALID_ADDRESS;
3054 }
3055 return success;
3056}
3057
Johnny Chenee9b1f72011-02-09 01:00:31 +00003058uint32_t
3059EmulateInstructionARM::ArchVersion ()
3060{
3061 return m_arm_isa;
3062}
3063
Greg Clayton64c84432011-01-21 22:02:52 +00003064bool
3065EmulateInstructionARM::ConditionPassed ()
3066{
3067 if (m_inst_cpsr == 0)
3068 return false;
3069
3070 const uint32_t cond = CurrentCond ();
3071
3072 if (cond == UINT32_MAX)
3073 return false;
3074
3075 bool result = false;
3076 switch (UnsignedBits(cond, 3, 1))
3077 {
3078 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
3079 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
3080 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
3081 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
3082 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
3083 case 5:
3084 {
3085 bool n = (m_inst_cpsr & MASK_CPSR_N);
3086 bool v = (m_inst_cpsr & MASK_CPSR_V);
3087 result = n == v;
3088 }
3089 break;
3090 case 6:
3091 {
3092 bool n = (m_inst_cpsr & MASK_CPSR_N);
3093 bool v = (m_inst_cpsr & MASK_CPSR_V);
3094 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3095 }
3096 break;
3097 case 7:
3098 result = true;
3099 break;
3100 }
3101
3102 if (cond & 1)
3103 result = !result;
3104 return result;
3105}
3106
Johnny Chen9ee056b2011-02-08 00:06:35 +00003107uint32_t
3108EmulateInstructionARM::CurrentCond ()
3109{
3110 switch (m_inst_mode)
3111 {
3112 default:
3113 case eModeInvalid:
3114 break;
3115
3116 case eModeARM:
3117 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3118
3119 case eModeThumb:
3120 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3121 // 'cond' field of the encoding.
3122 if (m_inst.opcode_type == eOpcode16 &&
3123 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3124 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3125 {
3126 return Bits32(m_inst.opcode.inst16, 11, 7);
3127 }
3128 else if (m_inst.opcode_type == eOpcode32 &&
3129 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3130 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3131 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3132 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3133 {
3134 return Bits32(m_inst.opcode.inst32, 25, 22);
3135 }
3136
3137 return m_it_session.GetCond();
3138 }
3139 return UINT32_MAX; // Return invalid value
3140}
3141
Johnny Chen9ee056b2011-02-08 00:06:35 +00003142bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003143EmulateInstructionARM::InITBlock()
3144{
3145 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3146}
3147
3148bool
3149EmulateInstructionARM::LastInITBlock()
3150{
3151 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3152}
3153
3154bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003155EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3156{
3157 addr_t target;
3158
Johnny Chenee9b1f72011-02-09 01:00:31 +00003159 // Check the current instruction set.
3160 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003161 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003162 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003163 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003164
Johnny Chen9ee056b2011-02-08 00:06:35 +00003165 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003166 return false;
3167
3168 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003169}
3170
3171// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3172bool
3173EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
3174{
3175 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003176 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3177 // we want to record it and issue a WriteRegister callback so the clients
3178 // can track the mode changes accordingly.
3179 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003180
3181 if (BitIsSet(addr, 0))
3182 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003183 if (CurrentInstrSet() != eModeThumb)
3184 {
3185 SelectInstrSet(eModeThumb);
3186 cpsr_changed = true;
3187 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003188 target = addr & 0xfffffffe;
3189 context.arg2 = eModeThumb;
3190 }
3191 else if (BitIsClear(addr, 1))
3192 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003193 if (CurrentInstrSet() != eModeARM)
3194 {
3195 SelectInstrSet(eModeARM);
3196 cpsr_changed = true;
3197 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003198 target = addr & 0xfffffffc;
3199 context.arg2 = eModeARM;
3200 }
3201 else
3202 return false; // address<1:0> == '10' => UNPREDICTABLE
3203
Johnny Chen0f309db2011-02-09 19:11:32 +00003204 if (cpsr_changed)
3205 {
Johnny Chen558133b2011-02-09 23:59:17 +00003206 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003207 return false;
3208 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003209 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003210 return false;
3211
3212 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003213}
Greg Clayton64c84432011-01-21 22:02:52 +00003214
Johnny Chenee9b1f72011-02-09 01:00:31 +00003215// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3216bool
3217EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
3218{
3219 if (ArchVersion() >= ARMv5T)
3220 return BXWritePC(context, addr);
3221 else
3222 return BranchWritePC((const Context)context, addr);
3223}
3224
Johnny Chen26863dc2011-02-09 23:43:29 +00003225// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3226bool
3227EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
3228{
3229 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
3230 return BXWritePC(context, addr);
3231 else
3232 return BranchWritePC((const Context)context, addr);
3233}
3234
Johnny Chenee9b1f72011-02-09 01:00:31 +00003235EmulateInstructionARM::Mode
3236EmulateInstructionARM::CurrentInstrSet ()
3237{
3238 return m_inst_mode;
3239}
3240
3241// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003242// ReadInstruction() is performed. This function has a side effect of updating
3243// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003244bool
3245EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3246{
Johnny Chen558133b2011-02-09 23:59:17 +00003247 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003248 switch (arm_or_thumb)
3249 {
3250 default:
3251 return false;
3252 eModeARM:
3253 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003254 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003255 break;
3256 eModeThumb:
3257 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003258 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003259 break;
3260 }
3261 return true;
3262}
3263
Johnny Chenef21b592011-02-10 01:52:38 +00003264// This function returns TRUE if the processor currently provides support for
3265// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3266// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3267bool
3268EmulateInstructionARM::UnalignedSupport()
3269{
3270 return (ArchVersion() >= ARMv7);
3271}
3272
Johnny Chenbf6ad172011-02-11 01:29:53 +00003273// The main addition and subtraction instructions can produce status information
3274// about both unsigned carry and signed overflow conditions. This status
3275// information can be used to synthesize multi-word additions and subtractions.
3276EmulateInstructionARM::AddWithCarryResult
3277EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3278{
3279 uint32_t result;
3280 uint8_t carry_out;
3281 uint8_t overflow;
3282
3283 uint64_t unsigned_sum = x + y + carry_in;
3284 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3285
3286 result = UnsignedBits(unsigned_sum, 31, 0);
3287 carry_out = (result == unsigned_sum ? 0 : 1);
3288 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3289
3290 AddWithCarryResult res = { result, carry_out, overflow };
3291 return res;
3292}
3293
Greg Clayton64c84432011-01-21 22:02:52 +00003294bool
3295EmulateInstructionARM::EvaluateInstruction ()
3296{
Johnny Chenc315f862011-02-05 00:46:10 +00003297 // Advance the ITSTATE bits to their values for the next instruction.
3298 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3299 m_it_session.ITAdvance();
3300
Greg Clayton64c84432011-01-21 22:02:52 +00003301 return false;
3302}