blob: 0513042102376828cdf58dfba8f8e4cc2b528fa8 [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;
367 break;
368 case eEncodingT3:
369 Rt = Bits32(opcode, 15, 12);
370 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
371 if (Rt == dwarf_sp)
372 return false;
373 registers = (1u << Rt);
374 break;
375 case eEncodingA1:
376 registers = Bits32(opcode, 15, 0);
377 // Instead of return false, let's handle the following case as well,
378 // which amounts to popping one reg from the full descending stacks.
379 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
380
381 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000382 if (Bit32(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000383 return false;
384 break;
385 case eEncodingA2:
386 Rt = Bits32(opcode, 15, 12);
387 // if t == 13 then UNPREDICTABLE;
388 if (Rt == dwarf_sp)
389 return false;
390 registers = (1u << Rt);
391 break;
392 default:
393 return false;
394 }
395 addr_t sp_offset = addr_byte_size * BitCount (registers);
396 addr_t addr = sp;
397 uint32_t i, data;
398
399 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
400 for (i=0; i<15; ++i)
401 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000402 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000403 {
404 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
405 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000406 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000407 if (!success)
408 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000409 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 return false;
411 addr += addr_byte_size;
412 }
413 }
414
Johnny Chen7c1bf922011-02-08 23:49:37 +0000415 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000416 {
417 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
418 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000419 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000420 if (!success)
421 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000422 // In ARMv5T and above, this is an interworking branch.
423 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000424 return false;
425 addr += addr_byte_size;
426 }
427
428 context.type = EmulateInstruction::eContextAdjustStackPointer;
429 context.arg0 = eRegisterKindGeneric;
430 context.arg1 = LLDB_REGNUM_GENERIC_SP;
431 context.arg2 = sp_offset;
432
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000433 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000434 return false;
435 }
436 return true;
437}
438
Johnny Chen5b442b72011-01-27 19:34:30 +0000439// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000440// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000441bool
442EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000443{
444#if 0
445 // ARM pseudo code...
446 if (ConditionPassed())
447 {
448 EncodingSpecificOperations();
449 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
450 if d == 15 then
451 ALUWritePC(result); // setflags is always FALSE here
452 else
453 R[d] = result;
454 if setflags then
455 APSR.N = result<31>;
456 APSR.Z = IsZeroBit(result);
457 APSR.C = carry;
458 APSR.V = overflow;
459 }
460#endif
461
462 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000463 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000464 if (!success)
465 return false;
466
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000467 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000468 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000469 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000470 if (!success)
471 return false;
472 uint32_t Rd; // the destination register
473 uint32_t imm32;
474 switch (encoding) {
475 case eEncodingT1:
476 Rd = 7;
477 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
478 break;
479 case eEncodingA1:
480 Rd = Bits32(opcode, 15, 12);
481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
482 break;
483 default:
484 return false;
485 }
486 addr_t sp_offset = imm32;
487 addr_t addr = sp + sp_offset; // a pointer to the stack area
488
489 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
490 eRegisterKindGeneric,
491 LLDB_REGNUM_GENERIC_SP,
492 sp_offset };
493
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000495 return false;
496 }
497 return true;
498}
499
Johnny Chen2ccad832011-01-28 19:57:25 +0000500// Set r7 or ip to the current stack pointer.
501// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502bool
503EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000504{
505#if 0
506 // ARM pseudo code...
507 if (ConditionPassed())
508 {
509 EncodingSpecificOperations();
510 result = R[m];
511 if d == 15 then
512 ALUWritePC(result); // setflags is always FALSE here
513 else
514 R[d] = result;
515 if setflags then
516 APSR.N = result<31>;
517 APSR.Z = IsZeroBit(result);
518 // APSR.C unchanged
519 // APSR.V unchanged
520 }
521#endif
522
523 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000524 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000525 //if (!success)
526 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000527
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000528 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000529 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000531 if (!success)
532 return false;
533 uint32_t Rd; // the destination register
534 switch (encoding) {
535 case eEncodingT1:
536 Rd = 7;
537 break;
538 case eEncodingA1:
539 Rd = 12;
540 break;
541 default:
542 return false;
543 }
544 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
545 eRegisterKindGeneric,
546 LLDB_REGNUM_GENERIC_SP,
547 0 };
548
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000549 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000550 return false;
551 }
552 return true;
553}
554
Johnny Chen1c13b622011-01-29 00:11:15 +0000555// Move from high register (r8-r15) to low register (r0-r7).
556// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000557bool
558EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000559{
Johnny Chen338bf542011-02-10 19:29:03 +0000560 return EmulateMovRdRm (encoding);
561}
562
563// Move from register to register.
564// MOV (register)
565bool
566EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
567{
Johnny Chen1c13b622011-01-29 00:11:15 +0000568#if 0
569 // ARM pseudo code...
570 if (ConditionPassed())
571 {
572 EncodingSpecificOperations();
573 result = R[m];
574 if d == 15 then
575 ALUWritePC(result); // setflags is always FALSE here
576 else
577 R[d] = result;
578 if setflags then
579 APSR.N = result<31>;
580 APSR.Z = IsZeroBit(result);
581 // APSR.C unchanged
582 // APSR.V unchanged
583 }
584#endif
585
586 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000587 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000588 if (!success)
589 return false;
590
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000591 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000592 {
593 uint32_t Rm; // the source register
594 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000595 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 switch (encoding) {
597 case eEncodingT1:
598 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000599 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000600 setflags = false;
601 break;
602 case eEncodingT2:
603 Rm = Bits32(opcode, 5, 3);
604 Rd = Bits32(opcode, 2, 1);
605 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 break;
607 default:
608 return false;
609 }
Johnny Chen338bf542011-02-10 19:29:03 +0000610 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 if (!success)
612 return false;
613
614 // The context specifies that Rm is to be moved into Rd.
615 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
616 eRegisterKindDWARF,
617 dwarf_r0 + Rm,
618 0 };
619
Johnny Chen338bf542011-02-10 19:29:03 +0000620 if (Rd == 15)
621 {
622 if (!ALUWritePC (context, reg_value))
623 return false;
624 }
625 else
626 {
627 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
628 return false;
629 if (setflags)
630 {
631 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000632 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
633 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000634 if (m_new_inst_cpsr != m_inst_cpsr)
635 {
636 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
637 return false;
638 }
639 }
640 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000641 }
642 return true;
643}
644
Johnny Chen788e0552011-01-27 22:52:23 +0000645// PC relative immediate load into register, possibly followed by ADD (SP plus register).
646// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000647bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000648EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000649{
650#if 0
651 // ARM pseudo code...
652 if (ConditionPassed())
653 {
654 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
655 base = Align(PC,4);
656 address = if add then (base + imm32) else (base - imm32);
657 data = MemU[address,4];
658 if t == 15 then
659 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
660 elsif UnalignedSupport() || address<1:0> = ‘00’ then
661 R[t] = data;
662 else // Can only apply before ARMv7
663 if CurrentInstrSet() == InstrSet_ARM then
664 R[t] = ROR(data, 8*UInt(address<1:0>));
665 else
666 R[t] = bits(32) UNKNOWN;
667 }
668#endif
669
670 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000671 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000672 if (!success)
673 return false;
674
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000675 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000676 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000677 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000678 if (!success)
679 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000680
681 // PC relative immediate load context
682 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
683 eRegisterKindGeneric,
684 LLDB_REGNUM_GENERIC_PC,
685 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000686 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000687 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000688 bool add; // +imm32 or -imm32?
689 addr_t base; // the base address
690 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000691 uint32_t data; // the literal data value from the PC relative load
692 switch (encoding) {
693 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000694 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000695 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000696 add = true;
697 base = Align(pc + 4, 4);
698 context.arg2 = 4 + imm32;
699 break;
700 case eEncodingT2:
701 Rt = Bits32(opcode, 15, 12);
702 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
703 add = BitIsSet(opcode, 23);
704 if (Rt == 15
705 && m_it_session.InITBlock()
706 && !m_it_session.LastInITBlock())
707 return false;
708 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000709 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000710 break;
711 default:
712 return false;
713 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000714
715 if (add)
716 address = base + imm32;
717 else
718 address = base - imm32;
719 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000720 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000721 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000722
723 if (Rt == 15)
724 {
725 if (Bits32(address, 1, 0) == 0)
726 {
727 // In ARMv5T and above, this is an interworking branch.
728 if (!LoadWritePC(context, data))
729 return false;
730 }
731 else
732 return false;
733 }
734 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
735 {
736 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
737 return false;
738 }
739 else // We don't handle ARM for now.
740 return false;
741
742 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000743 return false;
744 }
745 return true;
746}
747
Johnny Chen5b442b72011-01-27 19:34:30 +0000748// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000749// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000750bool
751EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000752{
753#if 0
754 // ARM pseudo code...
755 if (ConditionPassed())
756 {
757 EncodingSpecificOperations();
758 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
759 if d == 15 then // Can only occur for ARM encoding
760 ALUWritePC(result); // setflags is always FALSE here
761 else
762 R[d] = result;
763 if setflags then
764 APSR.N = result<31>;
765 APSR.Z = IsZeroBit(result);
766 APSR.C = carry;
767 APSR.V = overflow;
768 }
769#endif
770
771 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000772 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000773 if (!success)
774 return false;
775
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000776 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000777 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000778 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000779 if (!success)
780 return false;
781 uint32_t imm32; // the immediate operand
782 switch (encoding) {
783 case eEncodingT2:
784 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
785 break;
786 default:
787 return false;
788 }
789 addr_t sp_offset = imm32;
790 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
791
792 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
793 eRegisterKindGeneric,
794 LLDB_REGNUM_GENERIC_SP,
795 sp_offset };
796
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000797 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000798 return false;
799 }
800 return true;
801}
802
803// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000804// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000805bool
806EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000807{
808#if 0
809 // ARM pseudo code...
810 if (ConditionPassed())
811 {
812 EncodingSpecificOperations();
813 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
814 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
815 if d == 15 then
816 ALUWritePC(result); // setflags is always FALSE here
817 else
818 R[d] = result;
819 if setflags then
820 APSR.N = result<31>;
821 APSR.Z = IsZeroBit(result);
822 APSR.C = carry;
823 APSR.V = overflow;
824 }
825#endif
826
827 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000828 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000829 if (!success)
830 return false;
831
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000832 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000833 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000834 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000835 if (!success)
836 return false;
837 uint32_t Rm; // the second operand
838 switch (encoding) {
839 case eEncodingT2:
840 Rm = Bits32(opcode, 6, 3);
841 break;
842 default:
843 return false;
844 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000845 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000846 if (!success)
847 return false;
848
849 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
850
851 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
852 eRegisterKindGeneric,
853 LLDB_REGNUM_GENERIC_SP,
854 reg_value };
855
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000857 return false;
858 }
859 return true;
860}
861
Johnny Chen9b8d7832011-02-02 01:13:56 +0000862// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
863// at a PC-relative address, and changes instruction set from ARM to Thumb, or
864// from Thumb to ARM.
865// BLX (immediate)
866bool
867EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
868{
869#if 0
870 // ARM pseudo code...
871 if (ConditionPassed())
872 {
873 EncodingSpecificOperations();
874 if CurrentInstrSet() == InstrSet_ARM then
875 LR = PC - 4;
876 else
877 LR = PC<31:1> : '1';
878 if targetInstrSet == InstrSet_ARM then
879 targetAddress = Align(PC,4) + imm32;
880 else
881 targetAddress = PC + imm32;
882 SelectInstrSet(targetInstrSet);
883 BranchWritePC(targetAddress);
884 }
885#endif
886
887 bool success = false;
888 const uint32_t opcode = OpcodeAsUnsigned (&success);
889 if (!success)
890 return false;
891
892 if (ConditionPassed())
893 {
894 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
895 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000896 if (!success)
897 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +0000898 addr_t lr; // next instruction address
899 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000900 int32_t imm32; // PC-relative offset
901 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +0000902 case eEncodingT1:
903 {
904 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000905 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +0000906 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000907 uint32_t J1 = Bit32(opcode, 13);
908 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +0000909 uint32_t imm11 = Bits32(opcode, 10, 0);
910 uint32_t I1 = !(J1 ^ S);
911 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000912 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +0000913 imm32 = llvm::SignExtend32<25>(imm25);
914 target = pc + 4 + imm32;
915 context.arg1 = 4 + imm32; // signed offset
916 context.arg2 = eModeThumb; // target instruction set
Johnny Chenab3b3512011-02-12 00:10:51 +0000917 if (m_it_session.InITBlock() && !m_it_session.LastInITBlock())
918 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +0000919 break;
920 }
Johnny Chen9b8d7832011-02-02 01:13:56 +0000921 case eEncodingT2:
922 {
923 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +0000924 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000925 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +0000926 uint32_t J1 = Bit32(opcode, 13);
927 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000928 uint32_t imm10L = Bits32(opcode, 10, 1);
929 uint32_t I1 = !(J1 ^ S);
930 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +0000931 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +0000932 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +0000933 target = Align(pc + 4, 4) + imm32;
934 context.arg1 = 4 + imm32; // signed offset
935 context.arg2 = eModeARM; // target instruction set
Johnny Chenab3b3512011-02-12 00:10:51 +0000936 if (m_it_session.InITBlock() && !m_it_session.LastInITBlock())
937 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000938 break;
939 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000940 case eEncodingA1:
941 lr = pc + 4; // return address
942 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +0000943 target = Align(pc + 8, 4) + imm32;
944 context.arg1 = 8 + imm32; // signed offset
945 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +0000946 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +0000947 case eEncodingA2:
948 lr = pc + 4; // return address
949 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
950 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000951 context.arg1 = 8 + imm32; // signed offset
952 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +0000953 break;
954 default:
955 return false;
956 }
957 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
958 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +0000959 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +0000960 return false;
961 }
962 return true;
963}
964
965// Branch with Link and Exchange (register) calls a subroutine at an address and
966// instruction set specified by a register.
967// BLX (register)
968bool
969EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
970{
971#if 0
972 // ARM pseudo code...
973 if (ConditionPassed())
974 {
975 EncodingSpecificOperations();
976 target = R[m];
977 if CurrentInstrSet() == InstrSet_ARM then
978 next_instr_addr = PC - 4;
979 LR = next_instr_addr;
980 else
981 next_instr_addr = PC - 2;
982 LR = next_instr_addr<31:1> : ‘1’;
983 BXWritePC(target);
984 }
985#endif
986
987 bool success = false;
988 const uint32_t opcode = OpcodeAsUnsigned (&success);
989 if (!success)
990 return false;
991
992 if (ConditionPassed())
993 {
994 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
995 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
996 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +0000997 if (!success)
998 return false;
999 uint32_t Rm; // the register with the target address
1000 switch (encoding) {
1001 case eEncodingT1:
1002 lr = (pc + 2) | 1u; // return address
1003 Rm = Bits32(opcode, 6, 3);
1004 // if m == 15 then UNPREDICTABLE;
1005 if (Rm == 15)
1006 return false;
Johnny Chenab3b3512011-02-12 00:10:51 +00001007 if (m_it_session.InITBlock() && !m_it_session.LastInITBlock())
1008 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001009 break;
1010 case eEncodingA1:
1011 lr = pc + 4; // return address
1012 Rm = Bits32(opcode, 3, 0);
1013 // if m == 15 then UNPREDICTABLE;
1014 if (Rm == 15)
1015 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001016 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001017 default:
1018 return false;
1019 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001020 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1021 if (!success)
1022 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001023 context.arg0 = eRegisterKindDWARF;
1024 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001025 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1026 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001027 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001028 return false;
1029 }
1030 return true;
1031}
1032
Johnny Chenab3b3512011-02-12 00:10:51 +00001033// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1034// BX
1035bool
1036EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1037{
1038#if 0
1039 // ARM pseudo code...
1040 if (ConditionPassed())
1041 {
1042 EncodingSpecificOperations();
1043 BXWritePC(R[m]);
1044 }
1045#endif
1046
1047 bool success = false;
1048 const uint32_t opcode = OpcodeAsUnsigned (&success);
1049 if (!success)
1050 return false;
1051
1052 if (ConditionPassed())
1053 {
1054 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1055 uint32_t Rm; // the register with the target address
1056 switch (encoding) {
1057 case eEncodingT1:
1058 Rm = Bits32(opcode, 6, 3);
1059 if (m_it_session.InITBlock() && !m_it_session.LastInITBlock())
1060 return false;
1061 break;
1062 case eEncodingA1:
1063 Rm = Bits32(opcode, 3, 0);
1064 break;
1065 default:
1066 return false;
1067 }
1068 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1069 if (!success)
1070 return false;
1071 context.arg0 = eRegisterKindDWARF;
1072 context.arg1 = dwarf_r0 + Rm;
1073 if (!BXWritePC(context, target))
1074 return false;
1075 }
1076 return true;
1077}
1078
Johnny Chen0d0148e2011-01-28 02:26:08 +00001079// Set r7 to point to some ip offset.
1080// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001081bool
1082EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001083{
1084#if 0
1085 // ARM pseudo code...
1086 if (ConditionPassed())
1087 {
1088 EncodingSpecificOperations();
1089 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1090 if d == 15 then // Can only occur for ARM encoding
1091 ALUWritePC(result); // setflags is always FALSE here
1092 else
1093 R[d] = result;
1094 if setflags then
1095 APSR.N = result<31>;
1096 APSR.Z = IsZeroBit(result);
1097 APSR.C = carry;
1098 APSR.V = overflow;
1099 }
1100#endif
1101
1102 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001103 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001104 if (!success)
1105 return false;
1106
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001107 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001108 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001109 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001110 if (!success)
1111 return false;
1112 uint32_t imm32;
1113 switch (encoding) {
1114 case eEncodingA1:
1115 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1116 break;
1117 default:
1118 return false;
1119 }
1120 addr_t ip_offset = imm32;
1121 addr_t addr = ip - ip_offset; // the adjusted ip value
1122
1123 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1124 eRegisterKindDWARF,
1125 dwarf_r12,
1126 -ip_offset };
1127
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001128 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001129 return false;
1130 }
1131 return true;
1132}
1133
1134// Set ip to point to some stack offset.
1135// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001136bool
1137EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001138{
1139#if 0
1140 // ARM pseudo code...
1141 if (ConditionPassed())
1142 {
1143 EncodingSpecificOperations();
1144 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1145 if d == 15 then // Can only occur for ARM encoding
1146 ALUWritePC(result); // setflags is always FALSE here
1147 else
1148 R[d] = result;
1149 if setflags then
1150 APSR.N = result<31>;
1151 APSR.Z = IsZeroBit(result);
1152 APSR.C = carry;
1153 APSR.V = overflow;
1154 }
1155#endif
1156
1157 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001158 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001159 if (!success)
1160 return false;
1161
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001162 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001163 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001164 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001165 if (!success)
1166 return false;
1167 uint32_t imm32;
1168 switch (encoding) {
1169 case eEncodingA1:
1170 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1171 break;
1172 default:
1173 return false;
1174 }
1175 addr_t sp_offset = imm32;
1176 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1177
1178 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1179 eRegisterKindGeneric,
1180 LLDB_REGNUM_GENERIC_SP,
1181 -sp_offset };
1182
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001184 return false;
1185 }
1186 return true;
1187}
1188
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001189// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001190bool
1191EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001192{
1193#if 0
1194 // ARM pseudo code...
1195 if (ConditionPassed())
1196 {
1197 EncodingSpecificOperations();
1198 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1199 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001200 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001201 else
1202 R[d] = result;
1203 if setflags then
1204 APSR.N = result<31>;
1205 APSR.Z = IsZeroBit(result);
1206 APSR.C = carry;
1207 APSR.V = overflow;
1208 }
1209#endif
1210
1211 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001212 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001213 if (!success)
1214 return false;
1215
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001216 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001217 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001218 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001219 if (!success)
1220 return false;
1221 uint32_t imm32;
1222 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001223 case eEncodingT1:
1224 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001225 case eEncodingT2:
1226 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1227 break;
1228 case eEncodingT3:
1229 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1230 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001231 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001232 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001233 break;
1234 default:
1235 return false;
1236 }
1237 addr_t sp_offset = imm32;
1238 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1239
1240 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1241 eRegisterKindGeneric,
1242 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001243 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001244
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001245 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001246 return false;
1247 }
1248 return true;
1249}
1250
Johnny Chen08c25e82011-01-31 18:02:28 +00001251// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001252bool
1253EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001254{
1255#if 0
1256 // ARM pseudo code...
1257 if (ConditionPassed())
1258 {
1259 EncodingSpecificOperations();
1260 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1261 address = if index then offset_addr else R[n];
1262 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1263 if wback then R[n] = offset_addr;
1264 }
1265#endif
1266
1267 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001268 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001269 if (!success)
1270 return false;
1271
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001272 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001273 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001274 const uint32_t addr_byte_size = GetAddressByteSize();
1275 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001276 if (!success)
1277 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001278 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001279 uint32_t imm12;
1280 switch (encoding) {
1281 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001282 Rt = Bits32(opcode, 15, 12);
1283 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001284 break;
1285 default:
1286 return false;
1287 }
1288 addr_t sp_offset = imm12;
1289 addr_t addr = sp - sp_offset;
1290
1291 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001292 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001293 {
Johnny Chen91d99862011-01-25 19:07:04 +00001294 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1295 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001296 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001297 if (!success)
1298 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001299 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001300 return false;
1301 }
1302 else
1303 {
1304 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1305 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001306 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001307 if (!success)
1308 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001309 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001310 return false;
1311 }
1312
1313 context.type = EmulateInstruction::eContextAdjustStackPointer;
1314 context.arg0 = eRegisterKindGeneric;
1315 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001316 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001317
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001318 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001319 return false;
1320 }
1321 return true;
1322}
1323
Johnny Chen08c25e82011-01-31 18:02:28 +00001324// Vector Push stores multiple extension registers to the stack.
1325// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001326bool
1327EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001328{
1329#if 0
1330 // ARM pseudo code...
1331 if (ConditionPassed())
1332 {
1333 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1334 address = SP - imm32;
1335 SP = SP - imm32;
1336 if single_regs then
1337 for r = 0 to regs-1
1338 MemA[address,4] = S[d+r]; address = address+4;
1339 else
1340 for r = 0 to regs-1
1341 // Store as two word-aligned words in the correct order for current endianness.
1342 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1343 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1344 address = address+8;
1345 }
1346#endif
1347
1348 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001349 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001350 if (!success)
1351 return false;
1352
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001353 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001354 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001355 const uint32_t addr_byte_size = GetAddressByteSize();
1356 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001357 if (!success)
1358 return false;
1359 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001360 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001361 uint32_t imm32; // stack offset
1362 uint32_t regs; // number of registers
1363 switch (encoding) {
1364 case eEncodingT1:
1365 case eEncodingA1:
1366 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001367 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001368 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1369 // If UInt(imm8) is odd, see "FSTMX".
1370 regs = Bits32(opcode, 7, 0) / 2;
1371 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1372 if (regs == 0 || regs > 16 || (d + regs) > 32)
1373 return false;
1374 break;
1375 case eEncodingT2:
1376 case eEncodingA2:
1377 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001378 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001379 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1380 regs = Bits32(opcode, 7, 0);
1381 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1382 if (regs == 0 || regs > 16 || (d + regs) > 32)
1383 return false;
1384 break;
1385 default:
1386 return false;
1387 }
1388 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1389 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1390 addr_t sp_offset = imm32;
1391 addr_t addr = sp - sp_offset;
1392 uint32_t i;
1393
1394 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1395 for (i=d; i<regs; ++i)
1396 {
1397 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1398 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1399 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001400 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001401 if (!success)
1402 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001403 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001404 return false;
1405 addr += reg_byte_size;
1406 }
1407
1408 context.type = EmulateInstruction::eContextAdjustStackPointer;
1409 context.arg0 = eRegisterKindGeneric;
1410 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001411 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001412
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001414 return false;
1415 }
1416 return true;
1417}
1418
Johnny Chen587a0a42011-02-01 18:35:28 +00001419// Vector Pop loads multiple extension registers from the stack.
1420// It also updates SP to point just above the loaded data.
1421bool
1422EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1423{
1424#if 0
1425 // ARM pseudo code...
1426 if (ConditionPassed())
1427 {
1428 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1429 address = SP;
1430 SP = SP + imm32;
1431 if single_regs then
1432 for r = 0 to regs-1
1433 S[d+r] = MemA[address,4]; address = address+4;
1434 else
1435 for r = 0 to regs-1
1436 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1437 // Combine the word-aligned words in the correct order for current endianness.
1438 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1439 }
1440#endif
1441
1442 bool success = false;
1443 const uint32_t opcode = OpcodeAsUnsigned (&success);
1444 if (!success)
1445 return false;
1446
1447 if (ConditionPassed())
1448 {
1449 const uint32_t addr_byte_size = GetAddressByteSize();
1450 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1451 if (!success)
1452 return false;
1453 bool single_regs;
1454 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1455 uint32_t imm32; // stack offset
1456 uint32_t regs; // number of registers
1457 switch (encoding) {
1458 case eEncodingT1:
1459 case eEncodingA1:
1460 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001461 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001462 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1463 // If UInt(imm8) is odd, see "FLDMX".
1464 regs = Bits32(opcode, 7, 0) / 2;
1465 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1466 if (regs == 0 || regs > 16 || (d + regs) > 32)
1467 return false;
1468 break;
1469 case eEncodingT2:
1470 case eEncodingA2:
1471 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001472 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001473 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1474 regs = Bits32(opcode, 7, 0);
1475 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1476 if (regs == 0 || regs > 16 || (d + regs) > 32)
1477 return false;
1478 break;
1479 default:
1480 return false;
1481 }
1482 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1483 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1484 addr_t sp_offset = imm32;
1485 addr_t addr = sp;
1486 uint32_t i;
1487 uint64_t data; // uint64_t to accomodate 64-bit registers.
1488
1489 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1490 for (i=d; i<regs; ++i)
1491 {
1492 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1493 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1494 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1495 if (!success)
1496 return false;
1497 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1498 return false;
1499 addr += reg_byte_size;
1500 }
1501
1502 context.type = EmulateInstruction::eContextAdjustStackPointer;
1503 context.arg0 = eRegisterKindGeneric;
1504 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1505 context.arg2 = sp_offset;
1506
1507 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1508 return false;
1509 }
1510 return true;
1511}
1512
Johnny Chenb77be412011-02-04 00:40:18 +00001513// SVC (previously SWI)
1514bool
1515EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1516{
1517#if 0
1518 // ARM pseudo code...
1519 if (ConditionPassed())
1520 {
1521 EncodingSpecificOperations();
1522 CallSupervisor();
1523 }
1524#endif
1525
1526 bool success = false;
1527 const uint32_t opcode = OpcodeAsUnsigned (&success);
1528 if (!success)
1529 return false;
1530
1531 if (ConditionPassed())
1532 {
1533 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1534 addr_t lr; // next instruction address
1535 if (!success)
1536 return false;
1537 uint32_t imm32; // the immediate constant
1538 uint32_t mode; // ARM or Thumb mode
1539 switch (encoding) {
1540 case eEncodingT1:
1541 lr = (pc + 2) | 1u; // return address
1542 imm32 = Bits32(opcode, 7, 0);
1543 mode = eModeThumb;
1544 break;
1545 case eEncodingA1:
1546 lr = pc + 4; // return address
1547 imm32 = Bits32(opcode, 23, 0);
1548 mode = eModeARM;
1549 break;
1550 default:
1551 return false;
1552 }
1553 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1554 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1555 return false;
1556 }
1557 return true;
1558}
1559
Johnny Chenc315f862011-02-05 00:46:10 +00001560// If Then makes up to four following instructions (the IT block) conditional.
1561bool
1562EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1563{
1564#if 0
1565 // ARM pseudo code...
1566 EncodingSpecificOperations();
1567 ITSTATE.IT<7:0> = firstcond:mask;
1568#endif
1569
1570 bool success = false;
1571 const uint32_t opcode = OpcodeAsUnsigned (&success);
1572 if (!success)
1573 return false;
1574
1575 m_it_session.InitIT(Bits32(opcode, 7, 0));
1576 return true;
1577}
1578
Johnny Chen3b620b32011-02-07 20:11:47 +00001579// Branch causes a branch to a target address.
1580bool
1581EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1582{
1583#if 0
1584 // ARM pseudo code...
1585 if (ConditionPassed())
1586 {
1587 EncodingSpecificOperations();
1588 BranchWritePC(PC + imm32);
1589 }
1590#endif
1591
1592 bool success = false;
1593 const uint32_t opcode = OpcodeAsUnsigned (&success);
1594 if (!success)
1595 return false;
1596
Johnny Chen9ee056b2011-02-08 00:06:35 +00001597 if (ConditionPassed())
1598 {
1599 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1600 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001601 if (!success)
1602 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001603 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001604 int32_t imm32; // PC-relative offset
1605 switch (encoding) {
1606 case eEncodingT1:
1607 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1608 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1609 target = pc + 4 + imm32;
1610 context.arg1 = 4 + imm32; // signed offset
1611 context.arg2 = eModeThumb; // target instruction set
1612 break;
1613 case eEncodingT2:
1614 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1615 target = pc + 4 + imm32;
1616 context.arg1 = 4 + imm32; // signed offset
1617 context.arg2 = eModeThumb; // target instruction set
1618 break;
1619 case eEncodingT3:
1620 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1621 {
Johnny Chenbd599902011-02-10 21:39:01 +00001622 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001623 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001624 uint32_t J1 = Bit32(opcode, 13);
1625 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001626 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001627 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001628 imm32 = llvm::SignExtend32<21>(imm21);
1629 target = pc + 4 + imm32;
1630 context.arg1 = eModeThumb; // target instruction set
1631 context.arg2 = 4 + imm32; // signed offset
1632 break;
1633 }
1634 case eEncodingT4:
1635 {
Johnny Chenbd599902011-02-10 21:39:01 +00001636 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001637 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001638 uint32_t J1 = Bit32(opcode, 13);
1639 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001640 uint32_t imm11 = Bits32(opcode, 10, 0);
1641 uint32_t I1 = !(J1 ^ S);
1642 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001643 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001644 imm32 = llvm::SignExtend32<25>(imm25);
1645 target = pc + 4 + imm32;
1646 context.arg1 = eModeThumb; // target instruction set
1647 context.arg2 = 4 + imm32; // signed offset
1648 break;
1649 }
1650 case eEncodingA1:
1651 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1652 target = pc + 8 + imm32;
1653 context.arg1 = eModeARM; // target instruction set
1654 context.arg2 = 8 + imm32; // signed offset
1655 break;
1656 default:
1657 return false;
1658 }
1659 if (!BranchWritePC(context, target))
1660 return false;
1661 }
1662 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001663}
1664
Johnny Chen53ebab72011-02-08 23:21:57 +00001665// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1666// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1667// CBNZ, CBZ
1668bool
1669EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1670{
1671#if 0
1672 // ARM pseudo code...
1673 EncodingSpecificOperations();
1674 if nonzero ^ IsZero(R[n]) then
1675 BranchWritePC(PC + imm32);
1676#endif
1677
1678 bool success = false;
1679 const uint32_t opcode = OpcodeAsUnsigned (&success);
1680 if (!success)
1681 return false;
1682
1683 // Read the register value from the operand register Rn.
1684 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1685 if (!success)
1686 return false;
1687
1688 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1689 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1690 if (!success)
1691 return false;
1692
1693 addr_t target; // target address
1694 uint32_t imm32; // PC-relative offset to branch forward
1695 bool nonzero;
1696 switch (encoding) {
1697 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001698 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001699 nonzero = BitIsSet(opcode, 11);
1700 target = pc + 4 + imm32;
1701 context.arg1 = 4 + imm32; // signed offset
1702 context.arg2 = eModeThumb; // target instruction set
1703 break;
1704 default:
1705 return false;
1706 }
1707 if (nonzero ^ (reg_val == 0))
1708 if (!BranchWritePC(context, target))
1709 return false;
1710
1711 return true;
1712}
1713
Johnny Chen26863dc2011-02-09 23:43:29 +00001714// ADD <Rdn>, <Rm>
1715// where <Rdn> the destination register is also the first operand register
1716// and <Rm> is the second operand register.
1717bool
1718EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1719{
1720#if 0
1721 // ARM pseudo code...
1722 if ConditionPassed() then
1723 EncodingSpecificOperations();
1724 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1725 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1726 if d == 15 then
1727 ALUWritePC(result); // setflags is always FALSE here
1728 else
1729 R[d] = result;
1730 if setflags then
1731 APSR.N = result<31>;
1732 APSR.Z = IsZeroBit(result);
1733 APSR.C = carry;
1734 APSR.V = overflow;
1735#endif
1736
1737 bool success = false;
1738 const uint32_t opcode = OpcodeAsUnsigned (&success);
1739 if (!success)
1740 return false;
1741
1742 if (ConditionPassed())
1743 {
1744 uint32_t Rd, Rn, Rm;
1745 //bool setflags = false;
1746 switch (encoding)
1747 {
1748 case eEncodingT2:
1749 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001750 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001751 Rm = Bits32(opcode, 6, 3);
1752 if (Rn == 15 && Rm == 15)
1753 return false;
1754 break;
1755 default:
1756 return false;
1757 }
1758
1759 int32_t result, val1, val2;
1760 // Read the first operand.
1761 if (Rn == 15)
1762 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1763 else
1764 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1765 if (!success)
1766 return false;
1767
1768 // Read the second operand.
1769 if (Rm == 15)
1770 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1771 else
1772 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1773 if (!success)
1774 return false;
1775
1776 result = val1 + val2;
1777 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
1778 result,
1779 0,
1780 0 };
1781
1782 if (Rd == 15)
1783 {
1784 if (!ALUWritePC (context, result))
1785 return false;
1786 }
1787 else
1788 {
1789 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, result))
1790 return false;
1791 }
1792 }
1793 return true;
1794}
1795
Johnny Chene4a4d302011-02-11 21:53:58 +00001796// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001797bool
1798EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1799{
1800#if 0
1801 // ARM pseudo code...
1802 if ConditionPassed() then
1803 EncodingSpecificOperations();
1804 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1805 APSR.N = result<31>;
1806 APSR.Z = IsZeroBit(result);
1807 APSR.C = carry;
1808 APSR.V = overflow;
1809#endif
1810
1811 bool success = false;
1812 const uint32_t opcode = OpcodeAsUnsigned (&success);
1813 if (!success)
1814 return false;
1815
1816 uint32_t Rn; // the first operand
1817 uint32_t imm32; // the immediate value to be compared with
1818 switch (encoding) {
1819 case eEncodingT1:
1820 Rn = Bits32(opcode, 10, 8);
1821 imm32 = Bits32(opcode, 7, 0);
1822 break;
1823 default:
1824 return false;
1825 }
1826 // Read the register value from the operand register Rn.
1827 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1828 if (!success)
1829 return false;
1830
1831 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1832 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
1833 m_new_inst_cpsr = m_inst_cpsr;
1834 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1835 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1836 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1837 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1838 if (m_new_inst_cpsr != m_inst_cpsr)
1839 {
1840 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1841 return false;
1842 }
1843 return true;
1844}
1845
Johnny Chene4a4d302011-02-11 21:53:58 +00001846// CMP (register)
1847bool
1848EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
1849{
1850#if 0
1851 // ARM pseudo code...
1852 if ConditionPassed() then
1853 EncodingSpecificOperations();
1854 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1855 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
1856 APSR.N = result<31>;
1857 APSR.Z = IsZeroBit(result);
1858 APSR.C = carry;
1859 APSR.V = overflow;
1860#endif
1861
1862 bool success = false;
1863 const uint32_t opcode = OpcodeAsUnsigned (&success);
1864 if (!success)
1865 return false;
1866
1867 uint32_t Rn; // the first operand
1868 uint32_t Rm; // the second operand
1869 switch (encoding) {
1870 case eEncodingT1:
1871 Rn = Bits32(opcode, 2, 0);
1872 Rm = Bits32(opcode, 5, 3);
1873 break;
1874 case eEncodingT2:
1875 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1876 Rm = Bits32(opcode, 6, 3);
1877 if (Rn < 8 && Rm < 8)
1878 return false;
1879 if (Rn == 15 || Rm == 15)
1880 return false;
1881 break;
1882 default:
1883 return false;
1884 }
1885 // Read the register value from register Rn.
1886 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1887 if (!success)
1888 return false;
1889 // Read the register value from register Rm.
1890 // The register value is not being shifted since we don't handle ARM for now.
1891 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1892 if (!success)
1893 return false;
1894
1895 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
1896 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
1897 m_new_inst_cpsr = m_inst_cpsr;
1898 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
1899 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
1900 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
1901 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
1902 if (m_new_inst_cpsr != m_inst_cpsr)
1903 {
1904 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1905 return false;
1906 }
1907 return true;
1908}
1909
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001910// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00001911// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001912// can be written back to the base register.
1913bool
1914EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
1915{
1916#if 0
1917 // ARM pseudo code...
1918 if ConditionPassed()
1919 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
1920 address = R[n];
1921
1922 for i = 0 to 14
1923 if registers<i> == '1' then
1924 R[i] = MemA[address, 4]; address = address + 4;
1925 if registers<15> == '1' then
1926 LoadWritePC (MemA[address, 4]);
1927
1928 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
1929 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
1930
1931#endif
1932
1933 bool success = false;
1934 const uint32_t opcode = OpcodeAsUnsigned (&success);
1935 if (!success)
1936 return false;
1937
1938 if (ConditionPassed())
1939 {
1940 uint32_t n;
1941 uint32_t registers = 0;
1942 bool wback;
1943 const uint32_t addr_byte_size = GetAddressByteSize();
1944 switch (encoding)
1945 {
1946 case eEncodingT1:
1947 n = Bits32 (opcode, 10, 8);
1948 registers = Bits32 (opcode, 7, 0);
1949 wback = BitIsClear (registers, n);
1950 // if BitCount(registers) < 1 then UNPREDICTABLE;
1951 if (BitCount(registers) < 1)
1952 return false;
1953 break;
1954 case eEncodingT2:
1955 n = Bits32 (opcode, 19, 16);
1956 registers = Bits32 (opcode, 15, 0);
1957 wback = BitIsSet (opcode, 21);
1958 if ((n == 15)
1959 || (BitCount (registers) < 2)
1960 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
1961 return false;
1962 if (BitIsSet (registers, 15)
1963 && m_it_session.InITBlock()
1964 && !m_it_session.LastInITBlock())
1965 return false;
1966 if (wback
1967 && BitIsSet (registers, n))
1968 return false;
1969 break;
1970 case eEncodingA1:
1971 n = Bits32 (opcode, 19, 16);
1972 registers = Bits32 (opcode, 15, 0);
1973 wback = BitIsSet (opcode, 21);
1974 if ((n == 15)
1975 || (BitCount (registers) < 1))
1976 return false;
1977 break;
1978 default:
1979 return false;
1980 }
1981
1982 int32_t offset = 0;
1983 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1984 if (!success)
1985 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00001986
1987 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1988 eRegisterKindDWARF,
1989 dwarf_r0 + n,
1990 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001991
1992 for (int i = 0; i < 14; ++i)
1993 {
1994 if (BitIsSet (registers, i))
1995 {
Caroline Tice85aab332011-02-08 23:56:10 +00001996 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1997 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00001998 if (wback && (n == 13)) // Pop Instruction
1999 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2000
2001 // R[i] = MemA [address, 4]; address = address + 4;
2002 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2003 if (!success)
2004 return false;
2005
2006 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2007 return false;
2008
2009 offset += addr_byte_size;
2010 }
2011 }
2012
2013 if (BitIsSet (registers, 15))
2014 {
2015 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002016 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2017 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002018 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2019 if (!success)
2020 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002021 // In ARMv5T and above, this is an interworking branch.
2022 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002023 return false;
2024 }
2025
2026 if (wback && BitIsClear (registers, n))
2027 {
Caroline Ticefa172202011-02-11 22:49:54 +00002028 // R[n] = R[n] + 4 * BitCount (registers)
2029 int32_t offset = addr_byte_size * BitCount (registers);
2030 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice85aab332011-02-08 23:56:10 +00002031 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002032
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002033 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2034 return false;
2035 }
2036 if (wback && BitIsSet (registers, n))
2037 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002038 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002039 }
2040 return true;
2041}
Caroline Tice713c2662011-02-11 17:59:55 +00002042
2043// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2044// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2045// can optionally be written back tot he base registers.
2046bool
2047EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2048{
2049#if 0
2050 // ARM pseudo code...
2051 if ConditionPassed() then
2052 EncodingSpecificOperations();
2053 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002054
Caroline Tice713c2662011-02-11 17:59:55 +00002055 for i = 0 to 14
2056 if registers<i> == ’1’ then
2057 R[i] = MemA[address,4]; address = address + 4;
2058
2059 if registers<15> == ’1’ then
2060 LoadWritePC(MemA[address,4]);
2061
2062 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2063 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2064#endif
2065
2066 bool success = false;
2067 const uint32_t opcode = OpcodeAsUnsigned (&success);
2068 if (!success)
2069 return false;
2070
2071 if (ConditionPassed())
2072 {
2073 uint32_t n;
2074 uint32_t registers = 0;
2075 bool wback;
2076 const uint32_t addr_byte_size = GetAddressByteSize();
2077
2078 // EncodingSpecificOperations();
2079 switch (encoding)
2080 {
2081 case eEncodingA1:
2082 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2083 n = Bits32 (opcode, 19, 16);
2084 registers = Bits32 (opcode, 15, 0);
2085 wback = BitIsSet (opcode, 21);
2086
2087 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2088 if ((n == 15) || (BitCount (registers) < 1))
2089 return false;
2090
2091 break;
2092
2093 default:
2094 return false;
2095 }
2096 // address = R[n] - 4*BitCount(registers) + 4;
2097
2098 int32_t offset = 0;
2099 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2100
2101 if (!success)
2102 return false;
2103
2104 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2105
2106 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2107 eRegisterKindDWARF,
2108 dwarf_r0 + n,
2109 offset };
2110
2111 // for i = 0 to 14
2112 for (int i = 0; i < 14; ++i)
2113 {
2114 // if registers<i> == ’1’ then
2115 if (BitIsSet (registers, i))
2116 {
2117 // R[i] = MemA[address,4]; address = address + 4;
2118 context.arg2 = offset;
2119 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2120 if (!success)
2121 return false;
2122 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2123 return false;
2124 offset += addr_byte_size;
2125 }
2126 }
2127
2128 // if registers<15> == ’1’ then
2129 // LoadWritePC(MemA[address,4]);
2130 if (BitIsSet (registers, 15))
2131 {
2132 context.arg2 = offset;
2133 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2134 if (!success)
2135 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002136 // In ARMv5T and above, this is an interworking branch.
2137 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002138 return false;
2139 }
2140
2141 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2142 if (wback && BitIsClear (registers, n))
2143 {
Caroline Tice713c2662011-02-11 17:59:55 +00002144 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2145 if (!success)
2146 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002147
2148 offset = (addr_byte_size * BitCount (registers)) * -1;
2149 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2150 context.arg2 = offset;
2151 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002152 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2153 return false;
2154 }
2155
2156 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2157 if (wback && BitIsSet (registers, n))
2158 return WriteBits32Unknown (n);
2159 }
2160 return true;
2161}
2162
2163// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2164// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2165// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002166bool
2167EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2168{
2169#if 0
2170 // ARM pseudo code...
2171 if ConditionPassed() then
2172 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2173 address = R[n] - 4*BitCount(registers);
2174
2175 for i = 0 to 14
2176 if registers<i> == ’1’ then
2177 R[i] = MemA[address,4]; address = address + 4;
2178 if registers<15> == ’1’ then
2179 LoadWritePC(MemA[address,4]);
2180
2181 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2182 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2183#endif
2184
2185 bool success = false;
2186 const uint32_t opcode = OpcodeAsUnsigned (&success);
2187 if (!success)
2188 return false;
2189
2190 if (ConditionPassed())
2191 {
2192 uint32_t n;
2193 uint32_t registers = 0;
2194 bool wback;
2195 const uint32_t addr_byte_size = GetAddressByteSize();
2196 switch (encoding)
2197 {
2198 case eEncodingT1:
2199 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2200 n = Bits32 (opcode, 19, 16);
2201 registers = Bits32 (opcode, 15, 0);
2202 wback = BitIsSet (opcode, 21);
2203
2204 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2205 if ((n == 15)
2206 || (BitCount (registers) < 2)
2207 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2208 return false;
2209
2210 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
2211 if (BitIsSet (registers, 15)
2212 && m_it_session.InITBlock()
2213 && !m_it_session.LastInITBlock())
2214 return false;
2215
2216 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2217 if (wback && BitIsSet (registers, n))
2218 return false;
2219
2220 break;
2221
2222 case eEncodingA1:
2223 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2224 n = Bits32 (opcode, 19, 16);
2225 registers = Bits32 (opcode, 15, 0);
2226 wback = BitIsSet (opcode, 21);
2227
2228 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2229 if ((n == 15) || (BitCount (registers) < 1))
2230 return false;
2231
2232 break;
2233
2234 default:
2235 return false;
2236 }
2237
Caroline Tice713c2662011-02-11 17:59:55 +00002238 // address = R[n] - 4*BitCount(registers);
2239
Caroline Tice0b29e242011-02-08 23:16:02 +00002240 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002241 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2242
2243 if (!success)
2244 return false;
2245
2246 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002247 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2248 eRegisterKindDWARF,
2249 dwarf_r0 + n,
2250 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002251
2252 for (int i = 0; i < 14; ++i)
2253 {
2254 if (BitIsSet (registers, i))
2255 {
2256 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002257 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002258 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2259 if (!success)
2260 return false;
2261
2262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2263 return false;
2264
2265 offset += addr_byte_size;
2266 }
2267 }
2268
2269 // if registers<15> == ’1’ then
2270 // LoadWritePC(MemA[address,4]);
2271 if (BitIsSet (registers, 15))
2272 {
Caroline Tice85aab332011-02-08 23:56:10 +00002273 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002274 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2275 if (!success)
2276 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002277 // In ARMv5T and above, this is an interworking branch.
2278 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002279 return false;
2280 }
2281
2282 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2283 if (wback && BitIsClear (registers, n))
2284 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002285 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2286 if (!success)
2287 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002288
2289 offset = (addr_byte_size * BitCount (registers)) * -1;
2290 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2291 context.arg2 = offset;
2292 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2294 return false;
2295 }
2296
2297 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2298 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002299 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002300 }
2301 return true;
2302}
Caroline Tice85aab332011-02-08 23:56:10 +00002303
Caroline Tice713c2662011-02-11 17:59:55 +00002304// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2305// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2306// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002307bool
2308EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2309{
2310#if 0
2311 if ConditionPassed() then
2312 EncodingSpecificOperations();
2313 address = R[n] + 4;
2314
2315 for i = 0 to 14
2316 if registers<i> == ’1’ then
2317 R[i] = MemA[address,4]; address = address + 4;
2318 if registers<15> == ’1’ then
2319 LoadWritePC(MemA[address,4]);
2320
2321 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2322 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2323#endif
2324
2325 bool success = false;
2326 const uint32_t opcode = OpcodeAsUnsigned (&success);
2327 if (!success)
2328 return false;
2329
2330 if (ConditionPassed())
2331 {
2332 uint32_t n;
2333 uint32_t registers = 0;
2334 bool wback;
2335 const uint32_t addr_byte_size = GetAddressByteSize();
2336 switch (encoding)
2337 {
2338 case eEncodingA1:
2339 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2340 n = Bits32 (opcode, 19, 16);
2341 registers = Bits32 (opcode, 15, 0);
2342 wback = BitIsSet (opcode, 21);
2343
2344 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2345 if ((n == 15) || (BitCount (registers) < 1))
2346 return false;
2347
2348 break;
2349 default:
2350 return false;
2351 }
2352 // address = R[n] + 4;
2353
2354 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002355 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2356
2357 if (!success)
2358 return false;
2359
2360 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002361
2362 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2363 eRegisterKindDWARF,
2364 dwarf_r0 + n,
2365 offset };
2366
2367 for (int i = 0; i < 14; ++i)
2368 {
2369 if (BitIsSet (registers, i))
2370 {
2371 // R[i] = MemA[address,4]; address = address + 4;
2372
2373 context.arg2 = offset;
2374 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2375 if (!success)
2376 return false;
2377
2378 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2379 return false;
2380
2381 offset += addr_byte_size;
2382 }
2383 }
2384
2385 // if registers<15> == ’1’ then
2386 // LoadWritePC(MemA[address,4]);
2387 if (BitIsSet (registers, 15))
2388 {
2389 context.arg2 = offset;
2390 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2391 if (!success)
2392 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002393 // In ARMv5T and above, this is an interworking branch.
2394 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002395 return false;
2396 }
2397
2398 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2399 if (wback && BitIsClear (registers, n))
2400 {
Caroline Tice85aab332011-02-08 23:56:10 +00002401 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2402 if (!success)
2403 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002404
2405 offset = addr_byte_size * BitCount (registers);
2406 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2407 context.arg2 = offset;
2408 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002409 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2410 return false;
2411 }
2412
2413 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2414 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002415 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002416 }
2417 return true;
2418}
Caroline Tice0b29e242011-02-08 23:16:02 +00002419
Johnny Chenef21b592011-02-10 01:52:38 +00002420// Load Register (immediate) calculates an address from a base register value and
2421// an immediate offset, loads a word from memory, and writes to a register.
2422// LDR (immediate, Thumb)
2423bool
2424EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2425{
2426#if 0
2427 // ARM pseudo code...
2428 if (ConditionPassed())
2429 {
2430 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2431 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2432 address = if index then offset_addr else R[n];
2433 data = MemU[address,4];
2434 if wback then R[n] = offset_addr;
2435 if t == 15 then
2436 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2437 elsif UnalignedSupport() || address<1:0> = '00' then
2438 R[t] = data;
2439 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2440 }
2441#endif
2442
2443 bool success = false;
2444 const uint32_t opcode = OpcodeAsUnsigned (&success);
2445 if (!success)
2446 return false;
2447
2448 if (ConditionPassed())
2449 {
2450 uint32_t Rt; // the destination register
2451 uint32_t Rn; // the base register
2452 uint32_t imm32; // the immediate offset used to form the address
2453 addr_t offset_addr; // the offset address
2454 addr_t address; // the calculated address
2455 uint32_t data; // the literal data value from memory load
2456 bool add, index, wback;
2457 switch (encoding) {
2458 case eEncodingT1:
2459 Rt = Bits32(opcode, 5, 3);
2460 Rn = Bits32(opcode, 2, 0);
2461 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2462 // index = TRUE; add = TRUE; wback = FALSE
2463 add = true;
2464 index = true;
2465 wback = false;
2466 break;
2467 default:
2468 return false;
2469 }
2470 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2471 if (!success)
2472 return false;
2473 if (add)
2474 offset_addr = base + imm32;
2475 else
2476 offset_addr = base - imm32;
2477
2478 address = (index ? offset_addr : base);
2479
2480 if (wback)
2481 {
2482 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2483 eRegisterKindDWARF,
2484 dwarf_r0 + Rn,
2485 (int32_t) (offset_addr - base)};
2486 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2487 return false;
2488 }
2489
2490 // Prepare to write to the Rt register.
2491 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2492 0,
2493 0,
2494 0};
2495
2496 // Read memory from the address.
2497 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2498 if (!success)
2499 return false;
2500 context.arg0 = data;
2501
2502 if (Rt == 15)
2503 {
2504 if (Bits32(address, 1, 0) == 0)
2505 {
2506 if (!LoadWritePC(context, data))
2507 return false;
2508 }
2509 else
2510 return false;
2511 }
2512 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2513 {
2514 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2515 return false;
2516 }
2517 else
2518 return false;
2519 }
2520 return true;
2521}
2522
Caroline Ticefa172202011-02-11 22:49:54 +00002523// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2524// consecutive memory locations start at this address, and teh address just above the last of those locations can
2525// optionally be written back to the base register.
2526bool
2527EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2528{
2529#if 0
2530 if ConditionPassed() then
2531 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2532 address = R[n];
2533
2534 for i = 0 to 14
2535 if registers<i> == ’1’ then
2536 if i == n && wback && i != LowestSetBit(registers) then
2537 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2538 else
2539 MemA[address,4] = R[i];
2540 address = address + 4;
2541
2542 if registers<15> == ’1’ then // Only possible for encoding A1
2543 MemA[address,4] = PCStoreValue();
2544 if wback then R[n] = R[n] + 4*BitCount(registers);
2545#endif
2546
2547 bool success = false;
2548 const uint32_t opcode = OpcodeAsUnsigned (&success);
2549 if (!success)
2550 return false;
2551
2552 if (ConditionPassed ())
2553 {
2554 uint32_t n;
2555 uint32_t registers = 0;
2556 bool wback;
2557 const uint32_t addr_byte_size = GetAddressByteSize();
2558
2559 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2560 switch (encoding)
2561 {
2562 case eEncodingT1:
2563 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2564 n = Bits32 (opcode, 10, 8);
2565 registers = Bits32 (opcode, 7, 0);
2566 wback = true;
2567
2568 // if BitCount(registers) < 1 then UNPREDICTABLE;
2569 if (BitCount (registers) < 1)
2570 return false;
2571
2572 break;
2573
2574 case eEncodingT2:
2575 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2576 n = Bits32 (opcode, 19, 16);
2577 registers = Bits32 (opcode, 15, 0);
2578 wback = BitIsSet (opcode, 21);
2579
2580 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2581 if ((n == 15) || (BitCount (registers) < 2))
2582 return false;
2583
2584 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2585 if (wback && BitIsSet (registers, n))
2586 return false;
2587
2588 break;
2589
2590 case eEncodingA1:
2591 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2592 n = Bits32 (opcode, 19, 16);
2593 registers = Bits32 (opcode, 15, 0);
2594 wback = BitIsSet (opcode, 21);
2595
2596 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2597 if ((n == 15) || (BitCount (registers) < 1))
2598 return false;
2599
2600 break;
2601
2602 default:
2603 return false;
2604 }
2605
2606 // address = R[n];
2607 int32_t offset = 0;
2608 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2609 if (!success)
2610 return false;
2611
2612 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterStore,
2613 eRegisterKindDWARF,
2614 dwarf_r0 + n,
2615 offset };
2616
2617 // for i = 0 to 14
2618 for (int i = 0; i < 14; ++i)
2619 {
2620 int lowest_set_bit = 14;
2621 // if registers<i> == ’1’ then
2622 if (BitIsSet (registers, i))
2623 {
2624 if (i < lowest_set_bit)
2625 lowest_set_bit = i;
2626 // if i == n && wback && i != LowestSetBit(registers) then
2627 if ((i == n) && wback && (i != lowest_set_bit))
2628 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2629 WriteBits32UnknownToMemory (address + offset);
2630 else
2631 {
2632 // MemA[address,4] = R[i];
2633 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2634 if (!success)
2635 return false;
2636
2637 context.arg1 = dwarf_r0 + i;
2638 context.arg2 = address + offset;
2639 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2640 return false;
2641 }
2642
2643 // address = address + 4;
2644 offset += addr_byte_size;
2645 }
2646 }
2647
2648 // if registers<15> == ’1’ then // Only possible for encoding A1
2649 // MemA[address,4] = PCStoreValue();
2650 if (BitIsSet (registers, 15))
2651 {
2652 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2653 if (!success)
2654 return false;
2655
2656 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
2657 context.arg2 = address + offset - sp; // arg2 in the context is the stack pointer offset
2658 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2659 if (!success)
2660 return false;
2661
2662 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2663 return false;
2664 }
2665
2666 // if wback then R[n] = R[n] + 4*BitCount(registers);
2667 if (wback)
2668 {
2669 offset = addr_byte_size * BitCount (registers);
2670 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2671 context.arg1 = dwarf_r0 + n;
2672 context.arg2 = offset;
2673 addr_t data = address + offset;
2674 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2675 return false;
2676 }
2677 }
2678 return true;
2679}
2680
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002681EmulateInstructionARM::ARMOpcode*
2682EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002683{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002684 static ARMOpcode
2685 g_arm_opcodes[] =
2686 {
2687 //----------------------------------------------------------------------
2688 // Prologue instructions
2689 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002690
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002691 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002692 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2693 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002694
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002695 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002696 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2697 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002698 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002699 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2700 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2701 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002702
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002703 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002704 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002705
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002706 // push one register
2707 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002708 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002709
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002710 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002711 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2712 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002713
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002714 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002715 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002716 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002717
Johnny Chenc28a76d2011-02-01 18:51:48 +00002718 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2719 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002720 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002721 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2722
2723 //----------------------------------------------------------------------
2724 // Supervisor Call (previously Software Interrupt)
2725 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002726 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2727
2728 //----------------------------------------------------------------------
2729 // Branch instructions
2730 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002731 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002732 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2733 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2734 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2735 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002736 // for example, "bx lr"
2737 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002738
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002739 //----------------------------------------------------------------------
2740 // Load instructions
2741 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002742 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002743 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002744 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002745 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2746
2747 //----------------------------------------------------------------------
2748 // Store instructions
2749 //----------------------------------------------------------------------
2750 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002751
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002752 };
2753 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2754
2755 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2756 {
2757 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2758 return &g_arm_opcodes[i];
2759 }
2760 return NULL;
2761}
Greg Clayton64c84432011-01-21 22:02:52 +00002762
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002763
2764EmulateInstructionARM::ARMOpcode*
2765EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002766{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002767
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002768 static ARMOpcode
2769 g_thumb_opcodes[] =
2770 {
2771 //----------------------------------------------------------------------
2772 // Prologue instructions
2773 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002774
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002775 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002776 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002777 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2778 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002779
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002780 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002781 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002782 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002783 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002784 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2785 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002786
Johnny Chenc9de9102011-02-11 19:12:30 +00002787 // PC-relative load into register (see also EmulateAddSPRm)
2788 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002789
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002790 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002791 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2792 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002793 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2794 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002795
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002796 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002797 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2798 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002799
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002800 //----------------------------------------------------------------------
2801 // Epilogue instructions
2802 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002803
Johnny Chenc28a76d2011-02-01 18:51:48 +00002804 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2805 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002806 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2807 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2808 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2809 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002810
2811 //----------------------------------------------------------------------
2812 // Supervisor Call (previously Software Interrupt)
2813 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002814 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2815
2816 //----------------------------------------------------------------------
2817 // If Then makes up to four following instructions conditional.
2818 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002819 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2820
2821 //----------------------------------------------------------------------
2822 // Branch instructions
2823 //----------------------------------------------------------------------
2824 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
2825 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
2826 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00002827 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002828 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00002829 // J1 == J2 == 1
2830 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2831 // J1 == J2 == 1
2832 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2833 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002834 // for example, "bx lr"
2835 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00002836 // compare and branch
2837 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002838
2839 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00002840 // Data-processing instructions
2841 //----------------------------------------------------------------------
2842 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
2843 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00002844 // move from high register to high register
2845 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
2846 // move from low register to low register
2847 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00002848 // compare a register with immediate
2849 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00002850 // compare Rn with Rm (Rn and Rm both from r0-r7)
2851 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
2852 // compare Rn with Rm (Rn and Rm not both from r0-r7)
2853 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00002854
2855 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002856 // Load instructions
2857 //----------------------------------------------------------------------
2858 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00002859 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00002860 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00002861 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
2862 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00002863 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
2864
2865 //----------------------------------------------------------------------
2866 // Store instructions
2867 //----------------------------------------------------------------------
2868 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
2869 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002870
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002871 };
2872
2873 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
2874 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
2875 {
2876 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
2877 return &g_thumb_opcodes[i];
2878 }
2879 return NULL;
2880}
Greg Clayton64c84432011-01-21 22:02:52 +00002881
Greg Clayton31e2a382011-01-30 20:03:56 +00002882bool
2883EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
2884{
2885 m_arm_isa = 0;
2886 const char *triple_cstr = triple.GetCString();
2887 if (triple_cstr)
2888 {
2889 const char *dash = ::strchr (triple_cstr, '-');
2890 if (dash)
2891 {
2892 std::string arch (triple_cstr, dash);
2893 const char *arch_cstr = arch.c_str();
2894 if (strcasecmp(arch_cstr, "armv4t") == 0)
2895 m_arm_isa = ARMv4T;
2896 else if (strcasecmp(arch_cstr, "armv4") == 0)
2897 m_arm_isa = ARMv4;
2898 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
2899 m_arm_isa = ARMv5TEJ;
2900 else if (strcasecmp(arch_cstr, "armv5te") == 0)
2901 m_arm_isa = ARMv5TE;
2902 else if (strcasecmp(arch_cstr, "armv5t") == 0)
2903 m_arm_isa = ARMv5T;
2904 else if (strcasecmp(arch_cstr, "armv6k") == 0)
2905 m_arm_isa = ARMv6K;
2906 else if (strcasecmp(arch_cstr, "armv6") == 0)
2907 m_arm_isa = ARMv6;
2908 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
2909 m_arm_isa = ARMv6T2;
2910 else if (strcasecmp(arch_cstr, "armv7") == 0)
2911 m_arm_isa = ARMv7;
2912 else if (strcasecmp(arch_cstr, "armv8") == 0)
2913 m_arm_isa = ARMv8;
2914 }
2915 }
2916 return m_arm_isa != 0;
2917}
2918
2919
Greg Clayton64c84432011-01-21 22:02:52 +00002920bool
2921EmulateInstructionARM::ReadInstruction ()
2922{
2923 bool success = false;
2924 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
2925 if (success)
2926 {
2927 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
2928 if (success)
2929 {
2930 Context read_inst_context = {eContextReadOpcode, 0, 0};
2931 if (m_inst_cpsr & MASK_CPSR_T)
2932 {
2933 m_inst_mode = eModeThumb;
2934 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
2935
2936 if (success)
2937 {
2938 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
2939 {
2940 m_inst.opcode_type = eOpcode16;
2941 m_inst.opcode.inst16 = thumb_opcode;
2942 }
2943 else
2944 {
2945 m_inst.opcode_type = eOpcode32;
2946 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
2947 }
2948 }
2949 }
2950 else
2951 {
2952 m_inst_mode = eModeARM;
2953 m_inst.opcode_type = eOpcode32;
2954 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
2955 }
2956 }
2957 }
2958 if (!success)
2959 {
2960 m_inst_mode = eModeInvalid;
2961 m_inst_pc = LLDB_INVALID_ADDRESS;
2962 }
2963 return success;
2964}
2965
Johnny Chenee9b1f72011-02-09 01:00:31 +00002966uint32_t
2967EmulateInstructionARM::ArchVersion ()
2968{
2969 return m_arm_isa;
2970}
2971
Greg Clayton64c84432011-01-21 22:02:52 +00002972bool
2973EmulateInstructionARM::ConditionPassed ()
2974{
2975 if (m_inst_cpsr == 0)
2976 return false;
2977
2978 const uint32_t cond = CurrentCond ();
2979
2980 if (cond == UINT32_MAX)
2981 return false;
2982
2983 bool result = false;
2984 switch (UnsignedBits(cond, 3, 1))
2985 {
2986 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
2987 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
2988 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
2989 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
2990 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
2991 case 5:
2992 {
2993 bool n = (m_inst_cpsr & MASK_CPSR_N);
2994 bool v = (m_inst_cpsr & MASK_CPSR_V);
2995 result = n == v;
2996 }
2997 break;
2998 case 6:
2999 {
3000 bool n = (m_inst_cpsr & MASK_CPSR_N);
3001 bool v = (m_inst_cpsr & MASK_CPSR_V);
3002 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3003 }
3004 break;
3005 case 7:
3006 result = true;
3007 break;
3008 }
3009
3010 if (cond & 1)
3011 result = !result;
3012 return result;
3013}
3014
Johnny Chen9ee056b2011-02-08 00:06:35 +00003015uint32_t
3016EmulateInstructionARM::CurrentCond ()
3017{
3018 switch (m_inst_mode)
3019 {
3020 default:
3021 case eModeInvalid:
3022 break;
3023
3024 case eModeARM:
3025 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3026
3027 case eModeThumb:
3028 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3029 // 'cond' field of the encoding.
3030 if (m_inst.opcode_type == eOpcode16 &&
3031 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3032 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3033 {
3034 return Bits32(m_inst.opcode.inst16, 11, 7);
3035 }
3036 else if (m_inst.opcode_type == eOpcode32 &&
3037 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3038 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3039 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3040 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3041 {
3042 return Bits32(m_inst.opcode.inst32, 25, 22);
3043 }
3044
3045 return m_it_session.GetCond();
3046 }
3047 return UINT32_MAX; // Return invalid value
3048}
3049
Johnny Chen9ee056b2011-02-08 00:06:35 +00003050bool
3051EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3052{
3053 addr_t target;
3054
Johnny Chenee9b1f72011-02-09 01:00:31 +00003055 // Check the current instruction set.
3056 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003057 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003058 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003059 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003060
Johnny Chen9ee056b2011-02-08 00:06:35 +00003061 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003062 return false;
3063
3064 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003065}
3066
3067// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3068bool
3069EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
3070{
3071 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003072 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3073 // we want to record it and issue a WriteRegister callback so the clients
3074 // can track the mode changes accordingly.
3075 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003076
3077 if (BitIsSet(addr, 0))
3078 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003079 if (CurrentInstrSet() != eModeThumb)
3080 {
3081 SelectInstrSet(eModeThumb);
3082 cpsr_changed = true;
3083 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003084 target = addr & 0xfffffffe;
3085 context.arg2 = eModeThumb;
3086 }
3087 else if (BitIsClear(addr, 1))
3088 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003089 if (CurrentInstrSet() != eModeARM)
3090 {
3091 SelectInstrSet(eModeARM);
3092 cpsr_changed = true;
3093 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003094 target = addr & 0xfffffffc;
3095 context.arg2 = eModeARM;
3096 }
3097 else
3098 return false; // address<1:0> == '10' => UNPREDICTABLE
3099
Johnny Chen0f309db2011-02-09 19:11:32 +00003100 if (cpsr_changed)
3101 {
Johnny Chen558133b2011-02-09 23:59:17 +00003102 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003103 return false;
3104 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003105 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003106 return false;
3107
3108 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003109}
Greg Clayton64c84432011-01-21 22:02:52 +00003110
Johnny Chenee9b1f72011-02-09 01:00:31 +00003111// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3112bool
3113EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
3114{
3115 if (ArchVersion() >= ARMv5T)
3116 return BXWritePC(context, addr);
3117 else
3118 return BranchWritePC((const Context)context, addr);
3119}
3120
Johnny Chen26863dc2011-02-09 23:43:29 +00003121// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3122bool
3123EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
3124{
3125 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
3126 return BXWritePC(context, addr);
3127 else
3128 return BranchWritePC((const Context)context, addr);
3129}
3130
Johnny Chenee9b1f72011-02-09 01:00:31 +00003131EmulateInstructionARM::Mode
3132EmulateInstructionARM::CurrentInstrSet ()
3133{
3134 return m_inst_mode;
3135}
3136
3137// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003138// ReadInstruction() is performed. This function has a side effect of updating
3139// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003140bool
3141EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3142{
Johnny Chen558133b2011-02-09 23:59:17 +00003143 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003144 switch (arm_or_thumb)
3145 {
3146 default:
3147 return false;
3148 eModeARM:
3149 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003150 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003151 break;
3152 eModeThumb:
3153 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003154 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003155 break;
3156 }
3157 return true;
3158}
3159
Johnny Chenef21b592011-02-10 01:52:38 +00003160// This function returns TRUE if the processor currently provides support for
3161// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3162// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3163bool
3164EmulateInstructionARM::UnalignedSupport()
3165{
3166 return (ArchVersion() >= ARMv7);
3167}
3168
Johnny Chenbf6ad172011-02-11 01:29:53 +00003169// The main addition and subtraction instructions can produce status information
3170// about both unsigned carry and signed overflow conditions. This status
3171// information can be used to synthesize multi-word additions and subtractions.
3172EmulateInstructionARM::AddWithCarryResult
3173EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3174{
3175 uint32_t result;
3176 uint8_t carry_out;
3177 uint8_t overflow;
3178
3179 uint64_t unsigned_sum = x + y + carry_in;
3180 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3181
3182 result = UnsignedBits(unsigned_sum, 31, 0);
3183 carry_out = (result == unsigned_sum ? 0 : 1);
3184 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3185
3186 AddWithCarryResult res = { result, carry_out, overflow };
3187 return res;
3188}
3189
Greg Clayton64c84432011-01-21 22:02:52 +00003190bool
3191EmulateInstructionARM::EvaluateInstruction ()
3192{
Johnny Chenc315f862011-02-05 00:46:10 +00003193 // Advance the ITSTATE bits to their values for the next instruction.
3194 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3195 m_it_session.ITAdvance();
3196
Greg Clayton64c84432011-01-21 22:02:52 +00003197 return false;
3198}