blob: 4bfe4d0cca0e861833de6749b560472b377e106a [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000013#include "lldb/Core/ConstString.h"
14
Greg Claytonf29a08f2011-02-09 17:41:27 +000015#include "Plugins/Process/Utility/ARMDefines.h"
16#include "Plugins/Process/Utility/ARMUtils.h"
17#include "Utility/ARM_DWARF_Registers.h"
18
Johnny Chen9b8d7832011-02-02 01:13:56 +000019#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000020 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Johnny Chend6c13f02011-02-08 20:36:34 +000025static inline uint32_t Align(uint32_t val, uint32_t alignment)
26{
27 return alignment * (val / alignment);
28}
29
Johnny Chen0e00af22011-02-10 19:40:42 +000030//----------------------------------------------------------------------
31//
32// ITSession implementation
33//
34//----------------------------------------------------------------------
35
Johnny Chen93070472011-02-04 23:02:47 +000036// A8.6.50
37// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
38static unsigned short CountITSize(unsigned ITMask) {
39 // First count the trailing zeros of the IT mask.
40 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
41 if (TZ > 3)
42 {
43 printf("Encoding error: IT Mask '0000'\n");
44 return 0;
45 }
46 return (4 - TZ);
47}
48
49// Init ITState. Note that at least one bit is always 1 in mask.
50bool ITSession::InitIT(unsigned short bits7_0)
51{
52 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
53 if (ITCounter == 0)
54 return false;
55
56 // A8.6.50 IT
57 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
58 if (FirstCond == 0xF)
59 {
60 printf("Encoding error: IT FirstCond '1111'\n");
61 return false;
62 }
63 if (FirstCond == 0xE && ITCounter != 1)
64 {
65 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
66 return false;
67 }
68
69 ITState = bits7_0;
70 return true;
71}
72
73// Update ITState if necessary.
74void ITSession::ITAdvance()
75{
76 assert(ITCounter);
77 --ITCounter;
78 if (ITCounter == 0)
79 ITState = 0;
80 else
81 {
82 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
83 SetBits32(ITState, 4, 0, NewITState4_0);
84 }
85}
86
87// Return true if we're inside an IT Block.
88bool ITSession::InITBlock()
89{
90 return ITCounter != 0;
91}
92
Johnny Chenc315f862011-02-05 00:46:10 +000093// Return true if we're the last instruction inside an IT Block.
94bool ITSession::LastInITBlock()
95{
96 return ITCounter == 1;
97}
98
Johnny Chen93070472011-02-04 23:02:47 +000099// Get condition bits for the current thumb instruction.
100uint32_t ITSession::GetCond()
101{
Johnny Chenc315f862011-02-05 00:46:10 +0000102 if (InITBlock())
103 return Bits32(ITState, 7, 4);
104 else
105 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000106}
107
Greg Clayton64c84432011-01-21 22:02:52 +0000108// ARM constants used during decoding
109#define REG_RD 0
110#define LDM_REGLIST 1
111#define PC_REG 15
112#define PC_REGLIST_BIT 0x8000
113
Johnny Chen251af6a2011-01-21 22:47:25 +0000114#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define ARMv4T (1u << 1)
116#define ARMv5T (1u << 2)
117#define ARMv5TE (1u << 3)
118#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000119#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define ARMv6K (1u << 6)
121#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000123#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMvAll (0xffffffffu)
125
Johnny Chen9b8d7832011-02-02 01:13:56 +0000126#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
127#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
128#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000129
Johnny Chen0e00af22011-02-10 19:40:42 +0000130//----------------------------------------------------------------------
131//
132// EmulateInstructionARM implementation
133//
134//----------------------------------------------------------------------
135
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000136void
137EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000138{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000139}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
145
Caroline Ticefa172202011-02-11 22:49:54 +0000146// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
147bool
148EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
149{
150 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteMemoryRandomBits,
151 address,
152 0,
153 0 };
154
155 uint32_t random_data = rand ();
156 const uint32_t addr_byte_size = GetAddressByteSize();
157
158 if (!WriteMemoryUnsigned (context, address, random_data, addr_byte_size))
159 return false;
160
161 return true;
162}
163
Caroline Tice713c2662011-02-11 17:59:55 +0000164// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
165bool
166EmulateInstructionARM::WriteBits32Unknown (int n)
167{
168 EmulateInstruction::Context context = { EmulateInstruction::eContextWriteRegisterRandomBits,
169 eRegisterKindDWARF,
170 dwarf_r0 + n,
171 0 };
172
Johnny Chen62ff6f52011-02-11 18:11:22 +0000173 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000174 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
175
176 if (!success)
177 return false;
178
179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
180 return false;
181
182 return true;
183}
184
Johnny Chen08c25e82011-01-31 18:02:28 +0000185// Push Multiple Registers stores multiple registers to the stack, storing to
186// consecutive memory locations ending just below the address in SP, and updates
187// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000188bool
189EmulateInstructionARM::EmulatePush (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000190{
191#if 0
192 // ARM pseudo code...
193 if (ConditionPassed())
194 {
195 EncodingSpecificOperations();
196 NullCheckIfThumbEE(13);
197 address = SP - 4*BitCount(registers);
198
199 for (i = 0 to 14)
200 {
201 if (registers<i> == ’1’)
202 {
203 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
204 MemA[address,4] = bits(32) UNKNOWN;
205 else
206 MemA[address,4] = R[i];
207 address = address + 4;
208 }
209 }
210
211 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
212 MemA[address,4] = PCStoreValue();
213
214 SP = SP - 4*BitCount(registers);
215 }
216#endif
217
218 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000219 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000220 if (!success)
221 return false;
222
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000224 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 const uint32_t addr_byte_size = GetAddressByteSize();
226 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000227 if (!success)
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000230 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000235 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000236 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // if BitCount(registers) < 1 then UNPREDICTABLE;
238 if (BitCount(registers) < 1)
239 return false;
240 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000241 case eEncodingT2:
242 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BitCount(registers) < 2 then UNPREDICTABLE;
245 if (BitCount(registers) < 2)
246 return false;
247 break;
248 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000249 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000255 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000257 // Instead of return false, let's handle the following case as well,
258 // which amounts to pushing one reg onto the full descending stacks.
259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000260 break;
261 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000262 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000268 default:
269 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 }
Johnny Chence1ca772011-01-25 01:13:00 +0000271 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000272 addr_t addr = sp - sp_offset;
273 uint32_t i;
274
275 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
276 for (i=0; i<15; ++i)
277 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000278 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000279 {
280 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
281 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000282 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000283 if (!success)
284 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000285 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000286 return false;
287 addr += addr_byte_size;
288 }
289 }
290
Johnny Chen7c1bf922011-02-08 23:49:37 +0000291 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 {
293 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
Johnny Chen3c75c762011-01-22 00:47:08 +0000294 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000295 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000296 if (!success)
297 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000299 return false;
300 }
301
302 context.type = EmulateInstruction::eContextAdjustStackPointer;
303 context.arg0 = eRegisterKindGeneric;
304 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +0000305 context.arg2 = -sp_offset;
Greg Clayton64c84432011-01-21 22:02:52 +0000306
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000307 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310 return true;
311}
312
Johnny Chenef85e912011-01-31 23:07:40 +0000313// Pop Multiple Registers loads multiple registers from the stack, loading from
314// consecutive memory locations staring at the address in SP, and updates
315// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000316bool
317EmulateInstructionARM::EmulatePop (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000318{
319#if 0
320 // ARM pseudo code...
321 if (ConditionPassed())
322 {
323 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
324 address = SP;
325 for i = 0 to 14
326 if registers<i> == ‘1’ then
327 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
328 if registers<15> == ‘1’ then
329 if UnalignedAllowed then
330 LoadWritePC(MemU[address,4]);
331 else
332 LoadWritePC(MemA[address,4]);
333 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
334 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
335 }
336#endif
337
338 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000339 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000340 if (!success)
341 return false;
342
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000345 const uint32_t addr_byte_size = GetAddressByteSize();
346 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349 uint32_t registers = 0;
350 uint32_t Rt; // the destination register
351 switch (encoding) {
352 case eEncodingT1:
353 registers = Bits32(opcode, 7, 0);
354 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000355 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 registers |= (1u << 15);
357 // if BitCount(registers) < 1 then UNPREDICTABLE;
358 if (BitCount(registers) < 1)
359 return false;
360 break;
361 case eEncodingT2:
362 // Ignore bit 13.
363 registers = Bits32(opcode, 15, 0) & ~0x2000;
364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
369 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000370 break;
371 case eEncodingT3:
372 Rt = Bits32(opcode, 15, 12);
373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 if (Rt == 13)
375 return false;
376 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
378 registers = (1u << Rt);
379 break;
380 case eEncodingA1:
381 registers = Bits32(opcode, 15, 0);
382 // Instead of return false, let's handle the following case as well,
383 // which amounts to popping one reg from the full descending stacks.
384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
385
386 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 break;
390 case eEncodingA2:
391 Rt = Bits32(opcode, 15, 12);
392 // if t == 13 then UNPREDICTABLE;
393 if (Rt == dwarf_sp)
394 return false;
395 registers = (1u << Rt);
396 break;
397 default:
398 return false;
399 }
400 addr_t sp_offset = addr_byte_size * BitCount (registers);
401 addr_t addr = sp;
402 uint32_t i, data;
403
404 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
405 for (i=0; i<15; ++i)
406 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000407 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000408 {
409 context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
410 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000411 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000412 if (!success)
413 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000414 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000415 return false;
416 addr += addr_byte_size;
417 }
418 }
419
Johnny Chen7c1bf922011-02-08 23:49:37 +0000420 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 {
422 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
423 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000424 data = ReadMemoryUnsigned(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000425 if (!success)
426 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000427 // In ARMv5T and above, this is an interworking branch.
428 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000429 return false;
430 addr += addr_byte_size;
431 }
432
433 context.type = EmulateInstruction::eContextAdjustStackPointer;
434 context.arg0 = eRegisterKindGeneric;
435 context.arg1 = LLDB_REGNUM_GENERIC_SP;
436 context.arg2 = sp_offset;
437
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 }
441 return true;
442}
443
Johnny Chen5b442b72011-01-27 19:34:30 +0000444// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000445// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446bool
447EmulateInstructionARM::EmulateAddRdSPImmediate (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448{
449#if 0
450 // ARM pseudo code...
451 if (ConditionPassed())
452 {
453 EncodingSpecificOperations();
454 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
455 if d == 15 then
456 ALUWritePC(result); // setflags is always FALSE here
457 else
458 R[d] = result;
459 if setflags then
460 APSR.N = result<31>;
461 APSR.Z = IsZeroBit(result);
462 APSR.C = carry;
463 APSR.V = overflow;
464 }
465#endif
466
467 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000468 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if (!success)
470 return false;
471
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
494 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
495 eRegisterKindGeneric,
496 LLDB_REGNUM_GENERIC_SP,
497 sp_offset };
498
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000499 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000500 return false;
501 }
502 return true;
503}
504
Johnny Chen2ccad832011-01-28 19:57:25 +0000505// Set r7 or ip to the current stack pointer.
506// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000507bool
508EmulateInstructionARM::EmulateMovRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000509{
510#if 0
511 // ARM pseudo code...
512 if (ConditionPassed())
513 {
514 EncodingSpecificOperations();
515 result = R[m];
516 if d == 15 then
517 ALUWritePC(result); // setflags is always FALSE here
518 else
519 R[d] = result;
520 if setflags then
521 APSR.N = result<31>;
522 APSR.Z = IsZeroBit(result);
523 // APSR.C unchanged
524 // APSR.V unchanged
525 }
526#endif
527
528 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000529 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000530 //if (!success)
531 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000532
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000533 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000534 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000536 if (!success)
537 return false;
538 uint32_t Rd; // the destination register
539 switch (encoding) {
540 case eEncodingT1:
541 Rd = 7;
542 break;
543 case eEncodingA1:
544 Rd = 12;
545 break;
546 default:
547 return false;
548 }
549 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
550 eRegisterKindGeneric,
551 LLDB_REGNUM_GENERIC_SP,
552 0 };
553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen1c13b622011-01-29 00:11:15 +0000560// Move from high register (r8-r15) to low register (r0-r7).
561// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
563EmulateInstructionARM::EmulateMovLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000564{
Johnny Chen338bf542011-02-10 19:29:03 +0000565 return EmulateMovRdRm (encoding);
566}
567
568// Move from register to register.
569// MOV (register)
570bool
571EmulateInstructionARM::EmulateMovRdRm (ARMEncoding encoding)
572{
Johnny Chen1c13b622011-01-29 00:11:15 +0000573#if 0
574 // ARM pseudo code...
575 if (ConditionPassed())
576 {
577 EncodingSpecificOperations();
578 result = R[m];
579 if d == 15 then
580 ALUWritePC(result); // setflags is always FALSE here
581 else
582 R[d] = result;
583 if setflags then
584 APSR.N = result<31>;
585 APSR.Z = IsZeroBit(result);
586 // APSR.C unchanged
587 // APSR.V unchanged
588 }
589#endif
590
591 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000592 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000593 if (!success)
594 return false;
595
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000596 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000597 {
598 uint32_t Rm; // the source register
599 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000600 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 switch (encoding) {
602 case eEncodingT1:
603 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000604 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000605 setflags = false;
606 break;
607 case eEncodingT2:
608 Rm = Bits32(opcode, 5, 3);
609 Rd = Bits32(opcode, 2, 1);
610 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 break;
612 default:
613 return false;
614 }
Johnny Chen338bf542011-02-10 19:29:03 +0000615 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000616 if (!success)
617 return false;
618
619 // The context specifies that Rm is to be moved into Rd.
620 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
621 eRegisterKindDWARF,
622 dwarf_r0 + Rm,
623 0 };
624
Johnny Chen338bf542011-02-10 19:29:03 +0000625 if (Rd == 15)
626 {
627 if (!ALUWritePC (context, reg_value))
628 return false;
629 }
630 else
631 {
632 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, reg_value))
633 return false;
634 if (setflags)
635 {
636 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenbd599902011-02-10 21:39:01 +0000637 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(reg_value, CPSR_N));
638 SetBit32(m_new_inst_cpsr, CPSR_Z, reg_value == 0 ? 1 : 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000639 if (m_new_inst_cpsr != m_inst_cpsr)
640 {
641 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
642 return false;
643 }
644 }
645 }
Johnny Chen1c13b622011-01-29 00:11:15 +0000646 }
647 return true;
648}
649
Johnny Chen357c30f2011-02-14 22:04:25 +0000650// Move (immediate) writes an immediate value to the destination register. It
651// can optionally update the condition flags based on the value.
652// MOV (immediate)
653bool
654EmulateInstructionARM::EmulateMovRdImm (ARMEncoding encoding)
655{
656#if 0
657 // ARM pseudo code...
658 if (ConditionPassed())
659 {
660 EncodingSpecificOperations();
661 result = imm32;
662 if d == 15 then // Can only occur for ARM encoding
663 ALUWritePC(result); // setflags is always FALSE here
664 else
665 R[d] = result;
666 if setflags then
667 APSR.N = result<31>;
668 APSR.Z = IsZeroBit(result);
669 APSR.C = carry;
670 // APSR.V unchanged
671 }
672#endif
673 bool success = false;
674 const uint32_t opcode = OpcodeAsUnsigned (&success);
675 if (!success)
676 return false;
677
678 if (ConditionPassed())
679 {
680 uint32_t Rd; // the destination register
681 uint32_t imm12; // some intermediate result
682 uint32_t imm32; // the immediate value to be written to Rd
683 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
684 bool setflags;
685 switch (encoding) {
686 case eEncodingT1:
687 Rd = Bits32(opcode, 11, 8);
688 setflags = !InITBlock();
689 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
690 carry = Bit32(m_inst_cpsr, CPSR_C);
691 break;
692 case eEncodingT2:
693 Rd = Bits32(opcode, 15, 12);
694 setflags = BitIsSet(opcode, 20);
695 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
696 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
697 break;
698 default:
699 return false;
700 }
701 uint32_t result = imm32;
702
703 // The context specifies that an immediate is to be moved into Rd.
704 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
705 0,
706 0,
707 0 };
708
709 if (Rd == 15)
710 {
711 if (!ALUWritePC (context, result))
712 return false;
713 }
714 else
715 {
716 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
717 return false;
718 if (setflags)
719 {
720 m_new_inst_cpsr = m_inst_cpsr;
721 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
722 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
723 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
724 if (m_new_inst_cpsr != m_inst_cpsr)
725 {
726 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
727 return false;
728 }
729 }
730 }
731 }
732 return true;
733}
734
Johnny Chen28070c32011-02-12 01:27:26 +0000735// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
736// the destination register. It can optionally update the condition flags based
737// on the value.
738// MVN (immediate)
739bool
740EmulateInstructionARM::EmulateMvnRdImm (ARMEncoding encoding)
741{
742#if 0
743 // ARM pseudo code...
744 if (ConditionPassed())
745 {
746 EncodingSpecificOperations();
747 result = NOT(imm32);
748 if d == 15 then // Can only occur for ARM encoding
749 ALUWritePC(result); // setflags is always FALSE here
750 else
751 R[d] = result;
752 if setflags then
753 APSR.N = result<31>;
754 APSR.Z = IsZeroBit(result);
755 APSR.C = carry;
756 // APSR.V unchanged
757 }
758#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000759 bool success = false;
760 const uint32_t opcode = OpcodeAsUnsigned (&success);
761 if (!success)
762 return false;
763
764 if (ConditionPassed())
765 {
766 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000767 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
768 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
769 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000770 bool setflags;
771 switch (encoding) {
772 case eEncodingT1:
773 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000774 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000775 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000776 imm32 = ThumbExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
777 break;
778 case eEncodingA1:
779 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000780 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000781 imm12 = Bits32(opcode, 11, 0);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000782 imm32 = ARMExpandImm_C(imm12, Bit32(m_inst_cpsr, CPSR_C), carry);
783 break;
784 default:
785 return false;
786 }
787 uint32_t result = ~imm32;
788
789 // The context specifies that an immediate is to be moved into Rd.
790 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
791 0,
792 0,
793 0 };
794
795 if (Rd == 15)
796 {
797 if (!ALUWritePC (context, result))
798 return false;
799 }
800 else
801 {
802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
803 return false;
804 if (setflags)
805 {
806 m_new_inst_cpsr = m_inst_cpsr;
807 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
808 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
809 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
810 if (m_new_inst_cpsr != m_inst_cpsr)
811 {
812 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
813 return false;
814 }
815 }
816 }
817 }
818 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000819}
820
Johnny Chen788e0552011-01-27 22:52:23 +0000821// PC relative immediate load into register, possibly followed by ADD (SP plus register).
822// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000823bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000824EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000825{
826#if 0
827 // ARM pseudo code...
828 if (ConditionPassed())
829 {
830 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
831 base = Align(PC,4);
832 address = if add then (base + imm32) else (base - imm32);
833 data = MemU[address,4];
834 if t == 15 then
835 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
836 elsif UnalignedSupport() || address<1:0> = ‘00’ then
837 R[t] = data;
838 else // Can only apply before ARMv7
839 if CurrentInstrSet() == InstrSet_ARM then
840 R[t] = ROR(data, 8*UInt(address<1:0>));
841 else
842 R[t] = bits(32) UNKNOWN;
843 }
844#endif
845
846 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000847 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000848 if (!success)
849 return false;
850
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000851 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000852 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000853 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000854 if (!success)
855 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000856
857 // PC relative immediate load context
858 EmulateInstruction::Context context = {EmulateInstruction::eContextRegisterPlusOffset,
859 eRegisterKindGeneric,
860 LLDB_REGNUM_GENERIC_PC,
861 0};
Johnny Chenc9de9102011-02-11 19:12:30 +0000862 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000863 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000864 bool add; // +imm32 or -imm32?
865 addr_t base; // the base address
866 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000867 uint32_t data; // the literal data value from the PC relative load
868 switch (encoding) {
869 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000870 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000871 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000872 add = true;
873 base = Align(pc + 4, 4);
874 context.arg2 = 4 + imm32;
875 break;
876 case eEncodingT2:
877 Rt = Bits32(opcode, 15, 12);
878 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
879 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000880 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000881 return false;
882 base = Align(pc + 4, 4);
Johnny Chen809742e2011-01-28 00:32:27 +0000883 context.arg2 = 4 + imm32;
Johnny Chen788e0552011-01-27 22:52:23 +0000884 break;
885 default:
886 return false;
887 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000888
889 if (add)
890 address = base + imm32;
891 else
892 address = base - imm32;
893 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000894 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000895 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000896
897 if (Rt == 15)
898 {
899 if (Bits32(address, 1, 0) == 0)
900 {
901 // In ARMv5T and above, this is an interworking branch.
902 if (!LoadWritePC(context, data))
903 return false;
904 }
905 else
906 return false;
907 }
908 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
909 {
910 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
911 return false;
912 }
913 else // We don't handle ARM for now.
914 return false;
915
916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000917 return false;
918 }
919 return true;
920}
921
Johnny Chen5b442b72011-01-27 19:34:30 +0000922// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000923// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000924bool
925EmulateInstructionARM::EmulateAddSPImmediate (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000926{
927#if 0
928 // ARM pseudo code...
929 if (ConditionPassed())
930 {
931 EncodingSpecificOperations();
932 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
933 if d == 15 then // Can only occur for ARM encoding
934 ALUWritePC(result); // setflags is always FALSE here
935 else
936 R[d] = result;
937 if setflags then
938 APSR.N = result<31>;
939 APSR.Z = IsZeroBit(result);
940 APSR.C = carry;
941 APSR.V = overflow;
942 }
943#endif
944
945 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000946 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000947 if (!success)
948 return false;
949
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000950 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000951 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000952 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000953 if (!success)
954 return false;
955 uint32_t imm32; // the immediate operand
956 switch (encoding) {
957 case eEncodingT2:
958 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
959 break;
960 default:
961 return false;
962 }
963 addr_t sp_offset = imm32;
964 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
965
966 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
967 eRegisterKindGeneric,
968 LLDB_REGNUM_GENERIC_SP,
969 sp_offset };
970
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000971 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000972 return false;
973 }
974 return true;
975}
976
977// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000978// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000979bool
980EmulateInstructionARM::EmulateAddSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000981{
982#if 0
983 // ARM pseudo code...
984 if (ConditionPassed())
985 {
986 EncodingSpecificOperations();
987 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
988 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
989 if d == 15 then
990 ALUWritePC(result); // setflags is always FALSE here
991 else
992 R[d] = result;
993 if setflags then
994 APSR.N = result<31>;
995 APSR.Z = IsZeroBit(result);
996 APSR.C = carry;
997 APSR.V = overflow;
998 }
999#endif
1000
1001 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001002 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001003 if (!success)
1004 return false;
1005
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001006 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001007 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001008 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001009 if (!success)
1010 return false;
1011 uint32_t Rm; // the second operand
1012 switch (encoding) {
1013 case eEncodingT2:
1014 Rm = Bits32(opcode, 6, 3);
1015 break;
1016 default:
1017 return false;
1018 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001019 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001020 if (!success)
1021 return false;
1022
1023 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1024
1025 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1026 eRegisterKindGeneric,
1027 LLDB_REGNUM_GENERIC_SP,
1028 reg_value };
1029
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001030 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001031 return false;
1032 }
1033 return true;
1034}
1035
Johnny Chen9b8d7832011-02-02 01:13:56 +00001036// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1037// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1038// from Thumb to ARM.
1039// BLX (immediate)
1040bool
1041EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1042{
1043#if 0
1044 // ARM pseudo code...
1045 if (ConditionPassed())
1046 {
1047 EncodingSpecificOperations();
1048 if CurrentInstrSet() == InstrSet_ARM then
1049 LR = PC - 4;
1050 else
1051 LR = PC<31:1> : '1';
1052 if targetInstrSet == InstrSet_ARM then
1053 targetAddress = Align(PC,4) + imm32;
1054 else
1055 targetAddress = PC + imm32;
1056 SelectInstrSet(targetInstrSet);
1057 BranchWritePC(targetAddress);
1058 }
1059#endif
1060
1061 bool success = false;
1062 const uint32_t opcode = OpcodeAsUnsigned (&success);
1063 if (!success)
1064 return false;
1065
1066 if (ConditionPassed())
1067 {
1068 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1069 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001070 if (!success)
1071 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001072 addr_t lr; // next instruction address
1073 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001074 int32_t imm32; // PC-relative offset
1075 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001076 case eEncodingT1:
1077 {
1078 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001079 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001080 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001081 uint32_t J1 = Bit32(opcode, 13);
1082 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001083 uint32_t imm11 = Bits32(opcode, 10, 0);
1084 uint32_t I1 = !(J1 ^ S);
1085 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001086 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001087 imm32 = llvm::SignExtend32<25>(imm25);
1088 target = pc + 4 + imm32;
1089 context.arg1 = 4 + imm32; // signed offset
1090 context.arg2 = eModeThumb; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +00001091 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001092 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001093 break;
1094 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001095 case eEncodingT2:
1096 {
1097 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001098 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001099 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001100 uint32_t J1 = Bit32(opcode, 13);
1101 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001102 uint32_t imm10L = Bits32(opcode, 10, 1);
1103 uint32_t I1 = !(J1 ^ S);
1104 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001105 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001106 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001107 target = Align(pc + 4, 4) + imm32;
1108 context.arg1 = 4 + imm32; // signed offset
1109 context.arg2 = eModeARM; // target instruction set
Johnny Chen098ae2d2011-02-12 00:50:05 +00001110 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001111 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001112 break;
1113 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001114 case eEncodingA1:
1115 lr = pc + 4; // return address
1116 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001117 target = Align(pc + 8, 4) + imm32;
1118 context.arg1 = 8 + imm32; // signed offset
1119 context.arg2 = eModeARM; // target instruction set
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001120 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001121 case eEncodingA2:
1122 lr = pc + 4; // return address
1123 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1124 target = pc + 8 + imm32;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001125 context.arg1 = 8 + imm32; // signed offset
1126 context.arg2 = eModeThumb; // target instruction set
Johnny Chen9b8d7832011-02-02 01:13:56 +00001127 break;
1128 default:
1129 return false;
1130 }
1131 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1132 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001133 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001134 return false;
1135 }
1136 return true;
1137}
1138
1139// Branch with Link and Exchange (register) calls a subroutine at an address and
1140// instruction set specified by a register.
1141// BLX (register)
1142bool
1143EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1144{
1145#if 0
1146 // ARM pseudo code...
1147 if (ConditionPassed())
1148 {
1149 EncodingSpecificOperations();
1150 target = R[m];
1151 if CurrentInstrSet() == InstrSet_ARM then
1152 next_instr_addr = PC - 4;
1153 LR = next_instr_addr;
1154 else
1155 next_instr_addr = PC - 2;
1156 LR = next_instr_addr<31:1> : ‘1’;
1157 BXWritePC(target);
1158 }
1159#endif
1160
1161 bool success = false;
1162 const uint32_t opcode = OpcodeAsUnsigned (&success);
1163 if (!success)
1164 return false;
1165
1166 if (ConditionPassed())
1167 {
1168 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1169 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1170 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001171 if (!success)
1172 return false;
1173 uint32_t Rm; // the register with the target address
1174 switch (encoding) {
1175 case eEncodingT1:
1176 lr = (pc + 2) | 1u; // return address
1177 Rm = Bits32(opcode, 6, 3);
1178 // if m == 15 then UNPREDICTABLE;
1179 if (Rm == 15)
1180 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001181 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001182 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001183 break;
1184 case eEncodingA1:
1185 lr = pc + 4; // return address
1186 Rm = Bits32(opcode, 3, 0);
1187 // if m == 15 then UNPREDICTABLE;
1188 if (Rm == 15)
1189 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001190 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001191 default:
1192 return false;
1193 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001194 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1195 if (!success)
1196 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001197 context.arg0 = eRegisterKindDWARF;
1198 context.arg1 = dwarf_r0 + Rm;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001199 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1200 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001201 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001202 return false;
1203 }
1204 return true;
1205}
1206
Johnny Chenab3b3512011-02-12 00:10:51 +00001207// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1208// BX
1209bool
1210EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1211{
1212#if 0
1213 // ARM pseudo code...
1214 if (ConditionPassed())
1215 {
1216 EncodingSpecificOperations();
1217 BXWritePC(R[m]);
1218 }
1219#endif
1220
1221 bool success = false;
1222 const uint32_t opcode = OpcodeAsUnsigned (&success);
1223 if (!success)
1224 return false;
1225
1226 if (ConditionPassed())
1227 {
1228 EmulateInstruction::Context context = { EmulateInstruction::eContextAbsoluteBranchRegister, 0, 0, 0};
1229 uint32_t Rm; // the register with the target address
1230 switch (encoding) {
1231 case eEncodingT1:
1232 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001233 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001234 return false;
1235 break;
1236 case eEncodingA1:
1237 Rm = Bits32(opcode, 3, 0);
1238 break;
1239 default:
1240 return false;
1241 }
1242 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1243 if (!success)
1244 return false;
1245 context.arg0 = eRegisterKindDWARF;
1246 context.arg1 = dwarf_r0 + Rm;
1247 if (!BXWritePC(context, target))
1248 return false;
1249 }
1250 return true;
1251}
1252
Johnny Chen0d0148e2011-01-28 02:26:08 +00001253// Set r7 to point to some ip offset.
1254// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001255bool
1256EmulateInstructionARM::EmulateSubR7IPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001257{
1258#if 0
1259 // ARM pseudo code...
1260 if (ConditionPassed())
1261 {
1262 EncodingSpecificOperations();
1263 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1264 if d == 15 then // Can only occur for ARM encoding
1265 ALUWritePC(result); // setflags is always FALSE here
1266 else
1267 R[d] = result;
1268 if setflags then
1269 APSR.N = result<31>;
1270 APSR.Z = IsZeroBit(result);
1271 APSR.C = carry;
1272 APSR.V = overflow;
1273 }
1274#endif
1275
1276 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001277 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001278 if (!success)
1279 return false;
1280
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001281 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001282 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001283 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001284 if (!success)
1285 return false;
1286 uint32_t imm32;
1287 switch (encoding) {
1288 case eEncodingA1:
1289 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1290 break;
1291 default:
1292 return false;
1293 }
1294 addr_t ip_offset = imm32;
1295 addr_t addr = ip - ip_offset; // the adjusted ip value
1296
1297 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1298 eRegisterKindDWARF,
1299 dwarf_r12,
1300 -ip_offset };
1301
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001302 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001303 return false;
1304 }
1305 return true;
1306}
1307
1308// Set ip to point to some stack offset.
1309// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001310bool
1311EmulateInstructionARM::EmulateSubIPSPImmediate (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001312{
1313#if 0
1314 // ARM pseudo code...
1315 if (ConditionPassed())
1316 {
1317 EncodingSpecificOperations();
1318 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1319 if d == 15 then // Can only occur for ARM encoding
1320 ALUWritePC(result); // setflags is always FALSE here
1321 else
1322 R[d] = result;
1323 if setflags then
1324 APSR.N = result<31>;
1325 APSR.Z = IsZeroBit(result);
1326 APSR.C = carry;
1327 APSR.V = overflow;
1328 }
1329#endif
1330
1331 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001332 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001333 if (!success)
1334 return false;
1335
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001336 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001337 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001338 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001339 if (!success)
1340 return false;
1341 uint32_t imm32;
1342 switch (encoding) {
1343 case eEncodingA1:
1344 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1345 break;
1346 default:
1347 return false;
1348 }
1349 addr_t sp_offset = imm32;
1350 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1351
1352 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
1353 eRegisterKindGeneric,
1354 LLDB_REGNUM_GENERIC_SP,
1355 -sp_offset };
1356
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001357 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001358 return false;
1359 }
1360 return true;
1361}
1362
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001363// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001364bool
1365EmulateInstructionARM::EmulateSubSPImmdiate (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001366{
1367#if 0
1368 // ARM pseudo code...
1369 if (ConditionPassed())
1370 {
1371 EncodingSpecificOperations();
1372 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1373 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001374 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001375 else
1376 R[d] = result;
1377 if setflags then
1378 APSR.N = result<31>;
1379 APSR.Z = IsZeroBit(result);
1380 APSR.C = carry;
1381 APSR.V = overflow;
1382 }
1383#endif
1384
1385 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001386 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001387 if (!success)
1388 return false;
1389
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001390 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001391 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001392 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001393 if (!success)
1394 return false;
1395 uint32_t imm32;
1396 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001397 case eEncodingT1:
1398 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001399 case eEncodingT2:
1400 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1401 break;
1402 case eEncodingT3:
1403 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1404 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001405 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001406 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001407 break;
1408 default:
1409 return false;
1410 }
1411 addr_t sp_offset = imm32;
1412 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1413
1414 EmulateInstruction::Context context = { EmulateInstruction::eContextAdjustStackPointer,
1415 eRegisterKindGeneric,
1416 LLDB_REGNUM_GENERIC_SP,
Johnny Chen5b442b72011-01-27 19:34:30 +00001417 -sp_offset };
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001418
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001419 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001420 return false;
1421 }
1422 return true;
1423}
1424
Johnny Chen08c25e82011-01-31 18:02:28 +00001425// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001426bool
1427EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001428{
1429#if 0
1430 // ARM pseudo code...
1431 if (ConditionPassed())
1432 {
1433 EncodingSpecificOperations();
1434 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1435 address = if index then offset_addr else R[n];
1436 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1437 if wback then R[n] = offset_addr;
1438 }
1439#endif
1440
1441 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001442 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001443 if (!success)
1444 return false;
1445
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001446 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001447 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001448 const uint32_t addr_byte_size = GetAddressByteSize();
1449 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001450 if (!success)
1451 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001452 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001453 uint32_t imm12;
1454 switch (encoding) {
1455 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001456 Rt = Bits32(opcode, 15, 12);
1457 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001458 break;
1459 default:
1460 return false;
1461 }
1462 addr_t sp_offset = imm12;
1463 addr_t addr = sp - sp_offset;
1464
1465 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
Johnny Chen91d99862011-01-25 19:07:04 +00001466 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001467 {
Johnny Chen91d99862011-01-25 19:07:04 +00001468 context.arg1 = dwarf_r0 + Rt; // arg1 in the context is the DWARF register number
1469 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001470 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001471 if (!success)
1472 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001473 if (!WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001474 return false;
1475 }
1476 else
1477 {
1478 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
1479 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001480 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001481 if (!success)
1482 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001483 if (!WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001484 return false;
1485 }
1486
1487 context.type = EmulateInstruction::eContextAdjustStackPointer;
1488 context.arg0 = eRegisterKindGeneric;
1489 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001490 context.arg2 = -sp_offset;
Johnny Chence1ca772011-01-25 01:13:00 +00001491
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001492 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001493 return false;
1494 }
1495 return true;
1496}
1497
Johnny Chen08c25e82011-01-31 18:02:28 +00001498// Vector Push stores multiple extension registers to the stack.
1499// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001500bool
1501EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001502{
1503#if 0
1504 // ARM pseudo code...
1505 if (ConditionPassed())
1506 {
1507 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1508 address = SP - imm32;
1509 SP = SP - imm32;
1510 if single_regs then
1511 for r = 0 to regs-1
1512 MemA[address,4] = S[d+r]; address = address+4;
1513 else
1514 for r = 0 to regs-1
1515 // Store as two word-aligned words in the correct order for current endianness.
1516 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1517 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1518 address = address+8;
1519 }
1520#endif
1521
1522 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001523 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001524 if (!success)
1525 return false;
1526
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001527 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001528 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001529 const uint32_t addr_byte_size = GetAddressByteSize();
1530 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001531 if (!success)
1532 return false;
1533 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001534 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001535 uint32_t imm32; // stack offset
1536 uint32_t regs; // number of registers
1537 switch (encoding) {
1538 case eEncodingT1:
1539 case eEncodingA1:
1540 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001541 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001542 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1543 // If UInt(imm8) is odd, see "FSTMX".
1544 regs = Bits32(opcode, 7, 0) / 2;
1545 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1546 if (regs == 0 || regs > 16 || (d + regs) > 32)
1547 return false;
1548 break;
1549 case eEncodingT2:
1550 case eEncodingA2:
1551 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001552 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001553 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1554 regs = Bits32(opcode, 7, 0);
1555 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1556 if (regs == 0 || regs > 16 || (d + regs) > 32)
1557 return false;
1558 break;
1559 default:
1560 return false;
1561 }
1562 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1563 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1564 addr_t sp_offset = imm32;
1565 addr_t addr = sp - sp_offset;
1566 uint32_t i;
1567
1568 EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
1569 for (i=d; i<regs; ++i)
1570 {
1571 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1572 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1573 // uint64_t to accommodate 64-bit registers.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001574 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001575 if (!success)
1576 return false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001577 if (!WriteMemoryUnsigned (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001578 return false;
1579 addr += reg_byte_size;
1580 }
1581
1582 context.type = EmulateInstruction::eContextAdjustStackPointer;
1583 context.arg0 = eRegisterKindGeneric;
1584 context.arg1 = LLDB_REGNUM_GENERIC_SP;
Johnny Chen5b442b72011-01-27 19:34:30 +00001585 context.arg2 = -sp_offset;
Johnny Chen799dfd02011-01-26 23:14:33 +00001586
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001587 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001588 return false;
1589 }
1590 return true;
1591}
1592
Johnny Chen587a0a42011-02-01 18:35:28 +00001593// Vector Pop loads multiple extension registers from the stack.
1594// It also updates SP to point just above the loaded data.
1595bool
1596EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1597{
1598#if 0
1599 // ARM pseudo code...
1600 if (ConditionPassed())
1601 {
1602 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1603 address = SP;
1604 SP = SP + imm32;
1605 if single_regs then
1606 for r = 0 to regs-1
1607 S[d+r] = MemA[address,4]; address = address+4;
1608 else
1609 for r = 0 to regs-1
1610 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1611 // Combine the word-aligned words in the correct order for current endianness.
1612 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1613 }
1614#endif
1615
1616 bool success = false;
1617 const uint32_t opcode = OpcodeAsUnsigned (&success);
1618 if (!success)
1619 return false;
1620
1621 if (ConditionPassed())
1622 {
1623 const uint32_t addr_byte_size = GetAddressByteSize();
1624 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1625 if (!success)
1626 return false;
1627 bool single_regs;
1628 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1629 uint32_t imm32; // stack offset
1630 uint32_t regs; // number of registers
1631 switch (encoding) {
1632 case eEncodingT1:
1633 case eEncodingA1:
1634 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001635 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001636 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1637 // If UInt(imm8) is odd, see "FLDMX".
1638 regs = Bits32(opcode, 7, 0) / 2;
1639 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1640 if (regs == 0 || regs > 16 || (d + regs) > 32)
1641 return false;
1642 break;
1643 case eEncodingT2:
1644 case eEncodingA2:
1645 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001646 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001647 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1648 regs = Bits32(opcode, 7, 0);
1649 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1650 if (regs == 0 || regs > 16 || (d + regs) > 32)
1651 return false;
1652 break;
1653 default:
1654 return false;
1655 }
1656 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1657 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1658 addr_t sp_offset = imm32;
1659 addr_t addr = sp;
1660 uint32_t i;
1661 uint64_t data; // uint64_t to accomodate 64-bit registers.
1662
1663 EmulateInstruction::Context context = { EmulateInstruction::eContextPopRegisterOffStack, eRegisterKindDWARF, 0, 0 };
1664 for (i=d; i<regs; ++i)
1665 {
1666 context.arg1 = start_reg + i; // arg1 in the context is the DWARF register number
1667 context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
1668 data = ReadMemoryUnsigned(context, addr, reg_byte_size, 0, &success);
1669 if (!success)
1670 return false;
1671 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, context.arg1, data))
1672 return false;
1673 addr += reg_byte_size;
1674 }
1675
1676 context.type = EmulateInstruction::eContextAdjustStackPointer;
1677 context.arg0 = eRegisterKindGeneric;
1678 context.arg1 = LLDB_REGNUM_GENERIC_SP;
1679 context.arg2 = sp_offset;
1680
1681 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1682 return false;
1683 }
1684 return true;
1685}
1686
Johnny Chenb77be412011-02-04 00:40:18 +00001687// SVC (previously SWI)
1688bool
1689EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1690{
1691#if 0
1692 // ARM pseudo code...
1693 if (ConditionPassed())
1694 {
1695 EncodingSpecificOperations();
1696 CallSupervisor();
1697 }
1698#endif
1699
1700 bool success = false;
1701 const uint32_t opcode = OpcodeAsUnsigned (&success);
1702 if (!success)
1703 return false;
1704
1705 if (ConditionPassed())
1706 {
1707 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1708 addr_t lr; // next instruction address
1709 if (!success)
1710 return false;
1711 uint32_t imm32; // the immediate constant
1712 uint32_t mode; // ARM or Thumb mode
1713 switch (encoding) {
1714 case eEncodingT1:
1715 lr = (pc + 2) | 1u; // return address
1716 imm32 = Bits32(opcode, 7, 0);
1717 mode = eModeThumb;
1718 break;
1719 case eEncodingA1:
1720 lr = pc + 4; // return address
1721 imm32 = Bits32(opcode, 23, 0);
1722 mode = eModeARM;
1723 break;
1724 default:
1725 return false;
1726 }
1727 EmulateInstruction::Context context = { EmulateInstruction::eContextSupervisorCall, mode, imm32, 0};
1728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1729 return false;
1730 }
1731 return true;
1732}
1733
Johnny Chenc315f862011-02-05 00:46:10 +00001734// If Then makes up to four following instructions (the IT block) conditional.
1735bool
1736EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1737{
1738#if 0
1739 // ARM pseudo code...
1740 EncodingSpecificOperations();
1741 ITSTATE.IT<7:0> = firstcond:mask;
1742#endif
1743
1744 bool success = false;
1745 const uint32_t opcode = OpcodeAsUnsigned (&success);
1746 if (!success)
1747 return false;
1748
1749 m_it_session.InitIT(Bits32(opcode, 7, 0));
1750 return true;
1751}
1752
Johnny Chen3b620b32011-02-07 20:11:47 +00001753// Branch causes a branch to a target address.
1754bool
1755EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1756{
1757#if 0
1758 // ARM pseudo code...
1759 if (ConditionPassed())
1760 {
1761 EncodingSpecificOperations();
1762 BranchWritePC(PC + imm32);
1763 }
1764#endif
1765
1766 bool success = false;
1767 const uint32_t opcode = OpcodeAsUnsigned (&success);
1768 if (!success)
1769 return false;
1770
Johnny Chen9ee056b2011-02-08 00:06:35 +00001771 if (ConditionPassed())
1772 {
1773 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1774 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001775 if (!success)
1776 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001777 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001778 int32_t imm32; // PC-relative offset
1779 switch (encoding) {
1780 case eEncodingT1:
1781 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1782 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1783 target = pc + 4 + imm32;
1784 context.arg1 = 4 + imm32; // signed offset
1785 context.arg2 = eModeThumb; // target instruction set
1786 break;
1787 case eEncodingT2:
1788 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1789 target = pc + 4 + imm32;
1790 context.arg1 = 4 + imm32; // signed offset
1791 context.arg2 = eModeThumb; // target instruction set
1792 break;
1793 case eEncodingT3:
1794 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1795 {
Johnny Chenbd599902011-02-10 21:39:01 +00001796 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001797 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001798 uint32_t J1 = Bit32(opcode, 13);
1799 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001800 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001801 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001802 imm32 = llvm::SignExtend32<21>(imm21);
1803 target = pc + 4 + imm32;
1804 context.arg1 = eModeThumb; // target instruction set
1805 context.arg2 = 4 + imm32; // signed offset
1806 break;
1807 }
1808 case eEncodingT4:
1809 {
Johnny Chenbd599902011-02-10 21:39:01 +00001810 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001811 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001812 uint32_t J1 = Bit32(opcode, 13);
1813 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001814 uint32_t imm11 = Bits32(opcode, 10, 0);
1815 uint32_t I1 = !(J1 ^ S);
1816 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001817 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001818 imm32 = llvm::SignExtend32<25>(imm25);
1819 target = pc + 4 + imm32;
1820 context.arg1 = eModeThumb; // target instruction set
1821 context.arg2 = 4 + imm32; // signed offset
1822 break;
1823 }
1824 case eEncodingA1:
1825 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1826 target = pc + 8 + imm32;
1827 context.arg1 = eModeARM; // target instruction set
1828 context.arg2 = 8 + imm32; // signed offset
1829 break;
1830 default:
1831 return false;
1832 }
1833 if (!BranchWritePC(context, target))
1834 return false;
1835 }
1836 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001837}
1838
Johnny Chen53ebab72011-02-08 23:21:57 +00001839// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1840// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1841// CBNZ, CBZ
1842bool
1843EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1844{
1845#if 0
1846 // ARM pseudo code...
1847 EncodingSpecificOperations();
1848 if nonzero ^ IsZero(R[n]) then
1849 BranchWritePC(PC + imm32);
1850#endif
1851
1852 bool success = false;
1853 const uint32_t opcode = OpcodeAsUnsigned (&success);
1854 if (!success)
1855 return false;
1856
1857 // Read the register value from the operand register Rn.
1858 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1859 if (!success)
1860 return false;
1861
1862 EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
1863 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1864 if (!success)
1865 return false;
1866
1867 addr_t target; // target address
1868 uint32_t imm32; // PC-relative offset to branch forward
1869 bool nonzero;
1870 switch (encoding) {
1871 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001872 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001873 nonzero = BitIsSet(opcode, 11);
1874 target = pc + 4 + imm32;
1875 context.arg1 = 4 + imm32; // signed offset
1876 context.arg2 = eModeThumb; // target instruction set
1877 break;
1878 default:
1879 return false;
1880 }
1881 if (nonzero ^ (reg_val == 0))
1882 if (!BranchWritePC(context, target))
1883 return false;
1884
1885 return true;
1886}
1887
Johnny Chen26863dc2011-02-09 23:43:29 +00001888// ADD <Rdn>, <Rm>
1889// where <Rdn> the destination register is also the first operand register
1890// and <Rm> is the second operand register.
1891bool
1892EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
1893{
1894#if 0
1895 // ARM pseudo code...
1896 if ConditionPassed() then
1897 EncodingSpecificOperations();
1898 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1899 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1900 if d == 15 then
1901 ALUWritePC(result); // setflags is always FALSE here
1902 else
1903 R[d] = result;
1904 if setflags then
1905 APSR.N = result<31>;
1906 APSR.Z = IsZeroBit(result);
1907 APSR.C = carry;
1908 APSR.V = overflow;
1909#endif
1910
1911 bool success = false;
1912 const uint32_t opcode = OpcodeAsUnsigned (&success);
1913 if (!success)
1914 return false;
1915
1916 if (ConditionPassed())
1917 {
1918 uint32_t Rd, Rn, Rm;
1919 //bool setflags = false;
1920 switch (encoding)
1921 {
1922 case eEncodingT2:
1923 // setflags = FALSE
Johnny Chenbd599902011-02-10 21:39:01 +00001924 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00001925 Rm = Bits32(opcode, 6, 3);
1926 if (Rn == 15 && Rm == 15)
1927 return false;
1928 break;
1929 default:
1930 return false;
1931 }
1932
1933 int32_t result, val1, val2;
1934 // Read the first operand.
1935 if (Rn == 15)
1936 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1937 else
1938 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1939 if (!success)
1940 return false;
1941
1942 // Read the second operand.
1943 if (Rm == 15)
1944 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1945 else
1946 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1947 if (!success)
1948 return false;
1949
1950 result = val1 + val2;
1951 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate,
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001952 0,
Johnny Chen26863dc2011-02-09 23:43:29 +00001953 0,
1954 0 };
1955
1956 if (Rd == 15)
1957 {
1958 if (!ALUWritePC (context, result))
1959 return false;
1960 }
1961 else
1962 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001963 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
Johnny Chen26863dc2011-02-09 23:43:29 +00001964 return false;
1965 }
1966 }
1967 return true;
1968}
1969
Johnny Chene4a4d302011-02-11 21:53:58 +00001970// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00001971bool
1972EmulateInstructionARM::EmulateCmpRnImm (ARMEncoding encoding)
1973{
1974#if 0
1975 // ARM pseudo code...
1976 if ConditionPassed() then
1977 EncodingSpecificOperations();
1978 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
1979 APSR.N = result<31>;
1980 APSR.Z = IsZeroBit(result);
1981 APSR.C = carry;
1982 APSR.V = overflow;
1983#endif
1984
1985 bool success = false;
1986 const uint32_t opcode = OpcodeAsUnsigned (&success);
1987 if (!success)
1988 return false;
1989
1990 uint32_t Rn; // the first operand
1991 uint32_t imm32; // the immediate value to be compared with
1992 switch (encoding) {
1993 case eEncodingT1:
1994 Rn = Bits32(opcode, 10, 8);
1995 imm32 = Bits32(opcode, 7, 0);
1996 break;
1997 default:
1998 return false;
1999 }
2000 // Read the register value from the operand register Rn.
2001 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2002 if (!success)
2003 return false;
2004
Johnny Chend4dc4442011-02-11 02:02:56 +00002005 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2006 m_new_inst_cpsr = m_inst_cpsr;
2007 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2008 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2009 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2010 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2011 if (m_new_inst_cpsr != m_inst_cpsr)
2012 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00002013 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
Johnny Chend4dc4442011-02-11 02:02:56 +00002014 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2015 return false;
2016 }
2017 return true;
2018}
2019
Johnny Chene4a4d302011-02-11 21:53:58 +00002020// CMP (register)
2021bool
2022EmulateInstructionARM::EmulateCmpRnRm (ARMEncoding encoding)
2023{
2024#if 0
2025 // ARM pseudo code...
2026 if ConditionPassed() then
2027 EncodingSpecificOperations();
2028 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2029 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2030 APSR.N = result<31>;
2031 APSR.Z = IsZeroBit(result);
2032 APSR.C = carry;
2033 APSR.V = overflow;
2034#endif
2035
2036 bool success = false;
2037 const uint32_t opcode = OpcodeAsUnsigned (&success);
2038 if (!success)
2039 return false;
2040
2041 uint32_t Rn; // the first operand
2042 uint32_t Rm; // the second operand
2043 switch (encoding) {
2044 case eEncodingT1:
2045 Rn = Bits32(opcode, 2, 0);
2046 Rm = Bits32(opcode, 5, 3);
2047 break;
2048 case eEncodingT2:
2049 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2050 Rm = Bits32(opcode, 6, 3);
2051 if (Rn < 8 && Rm < 8)
2052 return false;
2053 if (Rn == 15 || Rm == 15)
2054 return false;
2055 break;
2056 default:
2057 return false;
2058 }
2059 // Read the register value from register Rn.
2060 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2061 if (!success)
2062 return false;
2063 // Read the register value from register Rm.
2064 // The register value is not being shifted since we don't handle ARM for now.
2065 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2066 if (!success)
2067 return false;
2068
Johnny Chene4a4d302011-02-11 21:53:58 +00002069 AddWithCarryResult res = AddWithCarry(reg_val1, reg_val2, 1);
2070 m_new_inst_cpsr = m_inst_cpsr;
2071 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(res.result, CPSR_N));
2072 SetBit32(m_new_inst_cpsr, CPSR_Z, res.result == 0 ? 1 : 0);
2073 SetBit32(m_new_inst_cpsr, CPSR_C, res.carry_out);
2074 SetBit32(m_new_inst_cpsr, CPSR_V, res.overflow);
2075 if (m_new_inst_cpsr != m_inst_cpsr)
2076 {
Johnny Chen33bf6ab2011-02-14 20:39:01 +00002077 EmulateInstruction::Context context = { EmulateInstruction::eContextImmediate, 0, 0, 0};
Johnny Chene4a4d302011-02-11 21:53:58 +00002078 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2079 return false;
2080 }
2081 return true;
2082}
2083
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002084// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002085// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002086// can be written back to the base register.
2087bool
2088EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2089{
2090#if 0
2091 // ARM pseudo code...
2092 if ConditionPassed()
2093 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2094 address = R[n];
2095
2096 for i = 0 to 14
2097 if registers<i> == '1' then
2098 R[i] = MemA[address, 4]; address = address + 4;
2099 if registers<15> == '1' then
2100 LoadWritePC (MemA[address, 4]);
2101
2102 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2103 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2104
2105#endif
2106
2107 bool success = false;
2108 const uint32_t opcode = OpcodeAsUnsigned (&success);
2109 if (!success)
2110 return false;
2111
2112 if (ConditionPassed())
2113 {
2114 uint32_t n;
2115 uint32_t registers = 0;
2116 bool wback;
2117 const uint32_t addr_byte_size = GetAddressByteSize();
2118 switch (encoding)
2119 {
2120 case eEncodingT1:
2121 n = Bits32 (opcode, 10, 8);
2122 registers = Bits32 (opcode, 7, 0);
2123 wback = BitIsClear (registers, n);
2124 // if BitCount(registers) < 1 then UNPREDICTABLE;
2125 if (BitCount(registers) < 1)
2126 return false;
2127 break;
2128 case eEncodingT2:
2129 n = Bits32 (opcode, 19, 16);
2130 registers = Bits32 (opcode, 15, 0);
2131 wback = BitIsSet (opcode, 21);
2132 if ((n == 15)
2133 || (BitCount (registers) < 2)
2134 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2135 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002136 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002137 return false;
2138 if (wback
2139 && BitIsSet (registers, n))
2140 return false;
2141 break;
2142 case eEncodingA1:
2143 n = Bits32 (opcode, 19, 16);
2144 registers = Bits32 (opcode, 15, 0);
2145 wback = BitIsSet (opcode, 21);
2146 if ((n == 15)
2147 || (BitCount (registers) < 1))
2148 return false;
2149 break;
2150 default:
2151 return false;
2152 }
2153
2154 int32_t offset = 0;
2155 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2156 if (!success)
2157 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002158
2159 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2160 eRegisterKindDWARF,
2161 dwarf_r0 + n,
2162 offset };
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002163
2164 for (int i = 0; i < 14; ++i)
2165 {
2166 if (BitIsSet (registers, i))
2167 {
Caroline Tice85aab332011-02-08 23:56:10 +00002168 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2169 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002170 if (wback && (n == 13)) // Pop Instruction
2171 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2172
2173 // R[i] = MemA [address, 4]; address = address + 4;
2174 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2175 if (!success)
2176 return false;
2177
2178 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2179 return false;
2180
2181 offset += addr_byte_size;
2182 }
2183 }
2184
2185 if (BitIsSet (registers, 15))
2186 {
2187 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002188 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2189 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002190 uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
2191 if (!success)
2192 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002193 // In ARMv5T and above, this is an interworking branch.
2194 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002195 return false;
2196 }
2197
2198 if (wback && BitIsClear (registers, n))
2199 {
Caroline Ticefa172202011-02-11 22:49:54 +00002200 // R[n] = R[n] + 4 * BitCount (registers)
2201 int32_t offset = addr_byte_size * BitCount (registers);
2202 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice85aab332011-02-08 23:56:10 +00002203 context.arg2 = offset;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002204
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002205 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2206 return false;
2207 }
2208 if (wback && BitIsSet (registers, n))
2209 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002210 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002211 }
2212 return true;
2213}
Caroline Tice713c2662011-02-11 17:59:55 +00002214
2215// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2216// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2217// can optionally be written back tot he base registers.
2218bool
2219EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2220{
2221#if 0
2222 // ARM pseudo code...
2223 if ConditionPassed() then
2224 EncodingSpecificOperations();
2225 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002226
Caroline Tice713c2662011-02-11 17:59:55 +00002227 for i = 0 to 14
2228 if registers<i> == ’1’ then
2229 R[i] = MemA[address,4]; address = address + 4;
2230
2231 if registers<15> == ’1’ then
2232 LoadWritePC(MemA[address,4]);
2233
2234 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2235 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2236#endif
2237
2238 bool success = false;
2239 const uint32_t opcode = OpcodeAsUnsigned (&success);
2240 if (!success)
2241 return false;
2242
2243 if (ConditionPassed())
2244 {
2245 uint32_t n;
2246 uint32_t registers = 0;
2247 bool wback;
2248 const uint32_t addr_byte_size = GetAddressByteSize();
2249
2250 // EncodingSpecificOperations();
2251 switch (encoding)
2252 {
2253 case eEncodingA1:
2254 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2255 n = Bits32 (opcode, 19, 16);
2256 registers = Bits32 (opcode, 15, 0);
2257 wback = BitIsSet (opcode, 21);
2258
2259 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2260 if ((n == 15) || (BitCount (registers) < 1))
2261 return false;
2262
2263 break;
2264
2265 default:
2266 return false;
2267 }
2268 // address = R[n] - 4*BitCount(registers) + 4;
2269
2270 int32_t offset = 0;
2271 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2272
2273 if (!success)
2274 return false;
2275
2276 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2277
2278 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2279 eRegisterKindDWARF,
2280 dwarf_r0 + n,
2281 offset };
2282
2283 // for i = 0 to 14
2284 for (int i = 0; i < 14; ++i)
2285 {
2286 // if registers<i> == ’1’ then
2287 if (BitIsSet (registers, i))
2288 {
2289 // R[i] = MemA[address,4]; address = address + 4;
2290 context.arg2 = offset;
2291 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2292 if (!success)
2293 return false;
2294 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2295 return false;
2296 offset += addr_byte_size;
2297 }
2298 }
2299
2300 // if registers<15> == ’1’ then
2301 // LoadWritePC(MemA[address,4]);
2302 if (BitIsSet (registers, 15))
2303 {
2304 context.arg2 = offset;
2305 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2306 if (!success)
2307 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002308 // In ARMv5T and above, this is an interworking branch.
2309 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002310 return false;
2311 }
2312
2313 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2314 if (wback && BitIsClear (registers, n))
2315 {
Caroline Tice713c2662011-02-11 17:59:55 +00002316 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2317 if (!success)
2318 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002319
2320 offset = (addr_byte_size * BitCount (registers)) * -1;
2321 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2322 context.arg2 = offset;
2323 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002324 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2325 return false;
2326 }
2327
2328 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2329 if (wback && BitIsSet (registers, n))
2330 return WriteBits32Unknown (n);
2331 }
2332 return true;
2333}
2334
2335// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2336// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2337// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002338bool
2339EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2340{
2341#if 0
2342 // ARM pseudo code...
2343 if ConditionPassed() then
2344 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2345 address = R[n] - 4*BitCount(registers);
2346
2347 for i = 0 to 14
2348 if registers<i> == ’1’ then
2349 R[i] = MemA[address,4]; address = address + 4;
2350 if registers<15> == ’1’ then
2351 LoadWritePC(MemA[address,4]);
2352
2353 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2354 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2355#endif
2356
2357 bool success = false;
2358 const uint32_t opcode = OpcodeAsUnsigned (&success);
2359 if (!success)
2360 return false;
2361
2362 if (ConditionPassed())
2363 {
2364 uint32_t n;
2365 uint32_t registers = 0;
2366 bool wback;
2367 const uint32_t addr_byte_size = GetAddressByteSize();
2368 switch (encoding)
2369 {
2370 case eEncodingT1:
2371 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2372 n = Bits32 (opcode, 19, 16);
2373 registers = Bits32 (opcode, 15, 0);
2374 wback = BitIsSet (opcode, 21);
2375
2376 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2377 if ((n == 15)
2378 || (BitCount (registers) < 2)
2379 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2380 return false;
2381
2382 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002383 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002384 return false;
2385
2386 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2387 if (wback && BitIsSet (registers, n))
2388 return false;
2389
2390 break;
2391
2392 case eEncodingA1:
2393 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2394 n = Bits32 (opcode, 19, 16);
2395 registers = Bits32 (opcode, 15, 0);
2396 wback = BitIsSet (opcode, 21);
2397
2398 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2399 if ((n == 15) || (BitCount (registers) < 1))
2400 return false;
2401
2402 break;
2403
2404 default:
2405 return false;
2406 }
2407
Caroline Tice713c2662011-02-11 17:59:55 +00002408 // address = R[n] - 4*BitCount(registers);
2409
Caroline Tice0b29e242011-02-08 23:16:02 +00002410 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002411 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2412
2413 if (!success)
2414 return false;
2415
2416 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice85aab332011-02-08 23:56:10 +00002417 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2418 eRegisterKindDWARF,
2419 dwarf_r0 + n,
2420 offset };
Caroline Tice0b29e242011-02-08 23:16:02 +00002421
2422 for (int i = 0; i < 14; ++i)
2423 {
2424 if (BitIsSet (registers, i))
2425 {
2426 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice85aab332011-02-08 23:56:10 +00002427 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002428 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2429 if (!success)
2430 return false;
2431
2432 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2433 return false;
2434
2435 offset += addr_byte_size;
2436 }
2437 }
2438
2439 // if registers<15> == ’1’ then
2440 // LoadWritePC(MemA[address,4]);
2441 if (BitIsSet (registers, 15))
2442 {
Caroline Tice85aab332011-02-08 23:56:10 +00002443 context.arg2 = offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002444 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2445 if (!success)
2446 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002447 // In ARMv5T and above, this is an interworking branch.
2448 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002449 return false;
2450 }
2451
2452 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2453 if (wback && BitIsClear (registers, n))
2454 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002455 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2456 if (!success)
2457 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002458
2459 offset = (addr_byte_size * BitCount (registers)) * -1;
2460 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2461 context.arg2 = offset;
2462 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002463 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2464 return false;
2465 }
2466
2467 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2468 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002469 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002470 }
2471 return true;
2472}
Caroline Tice85aab332011-02-08 23:56:10 +00002473
Caroline Tice713c2662011-02-11 17:59:55 +00002474// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2475// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2476// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002477bool
2478EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2479{
2480#if 0
2481 if ConditionPassed() then
2482 EncodingSpecificOperations();
2483 address = R[n] + 4;
2484
2485 for i = 0 to 14
2486 if registers<i> == ’1’ then
2487 R[i] = MemA[address,4]; address = address + 4;
2488 if registers<15> == ’1’ then
2489 LoadWritePC(MemA[address,4]);
2490
2491 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2492 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2493#endif
2494
2495 bool success = false;
2496 const uint32_t opcode = OpcodeAsUnsigned (&success);
2497 if (!success)
2498 return false;
2499
2500 if (ConditionPassed())
2501 {
2502 uint32_t n;
2503 uint32_t registers = 0;
2504 bool wback;
2505 const uint32_t addr_byte_size = GetAddressByteSize();
2506 switch (encoding)
2507 {
2508 case eEncodingA1:
2509 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2510 n = Bits32 (opcode, 19, 16);
2511 registers = Bits32 (opcode, 15, 0);
2512 wback = BitIsSet (opcode, 21);
2513
2514 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2515 if ((n == 15) || (BitCount (registers) < 1))
2516 return false;
2517
2518 break;
2519 default:
2520 return false;
2521 }
2522 // address = R[n] + 4;
2523
2524 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002525 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2526
2527 if (!success)
2528 return false;
2529
2530 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00002531
2532 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
2533 eRegisterKindDWARF,
2534 dwarf_r0 + n,
2535 offset };
2536
2537 for (int i = 0; i < 14; ++i)
2538 {
2539 if (BitIsSet (registers, i))
2540 {
2541 // R[i] = MemA[address,4]; address = address + 4;
2542
2543 context.arg2 = offset;
2544 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2545 if (!success)
2546 return false;
2547
2548 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2549 return false;
2550
2551 offset += addr_byte_size;
2552 }
2553 }
2554
2555 // if registers<15> == ’1’ then
2556 // LoadWritePC(MemA[address,4]);
2557 if (BitIsSet (registers, 15))
2558 {
2559 context.arg2 = offset;
2560 uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
2561 if (!success)
2562 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002563 // In ARMv5T and above, this is an interworking branch.
2564 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00002565 return false;
2566 }
2567
2568 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2569 if (wback && BitIsClear (registers, n))
2570 {
Caroline Tice85aab332011-02-08 23:56:10 +00002571 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2572 if (!success)
2573 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002574
2575 offset = addr_byte_size * BitCount (registers);
2576 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2577 context.arg2 = offset;
2578 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00002579 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2580 return false;
2581 }
2582
2583 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2584 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002585 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00002586 }
2587 return true;
2588}
Caroline Tice0b29e242011-02-08 23:16:02 +00002589
Johnny Chenef21b592011-02-10 01:52:38 +00002590// Load Register (immediate) calculates an address from a base register value and
2591// an immediate offset, loads a word from memory, and writes to a register.
2592// LDR (immediate, Thumb)
2593bool
2594EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
2595{
2596#if 0
2597 // ARM pseudo code...
2598 if (ConditionPassed())
2599 {
2600 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
2601 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2602 address = if index then offset_addr else R[n];
2603 data = MemU[address,4];
2604 if wback then R[n] = offset_addr;
2605 if t == 15 then
2606 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
2607 elsif UnalignedSupport() || address<1:0> = '00' then
2608 R[t] = data;
2609 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
2610 }
2611#endif
2612
2613 bool success = false;
2614 const uint32_t opcode = OpcodeAsUnsigned (&success);
2615 if (!success)
2616 return false;
2617
2618 if (ConditionPassed())
2619 {
2620 uint32_t Rt; // the destination register
2621 uint32_t Rn; // the base register
2622 uint32_t imm32; // the immediate offset used to form the address
2623 addr_t offset_addr; // the offset address
2624 addr_t address; // the calculated address
2625 uint32_t data; // the literal data value from memory load
2626 bool add, index, wback;
2627 switch (encoding) {
2628 case eEncodingT1:
2629 Rt = Bits32(opcode, 5, 3);
2630 Rn = Bits32(opcode, 2, 0);
2631 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
2632 // index = TRUE; add = TRUE; wback = FALSE
2633 add = true;
2634 index = true;
2635 wback = false;
2636 break;
2637 default:
2638 return false;
2639 }
2640 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2641 if (!success)
2642 return false;
2643 if (add)
2644 offset_addr = base + imm32;
2645 else
2646 offset_addr = base - imm32;
2647
2648 address = (index ? offset_addr : base);
2649
2650 if (wback)
2651 {
2652 EmulateInstruction::Context ctx = { EmulateInstruction::eContextRegisterPlusOffset,
2653 eRegisterKindDWARF,
2654 dwarf_r0 + Rn,
2655 (int32_t) (offset_addr - base)};
2656 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
2657 return false;
2658 }
2659
2660 // Prepare to write to the Rt register.
2661 EmulateInstruction::Context context = {EmulateInstruction::eContextImmediate,
2662 0,
2663 0,
2664 0};
2665
2666 // Read memory from the address.
2667 data = ReadMemoryUnsigned(context, address, 4, 0, &success);
2668 if (!success)
2669 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00002670
2671 if (Rt == 15)
2672 {
2673 if (Bits32(address, 1, 0) == 0)
2674 {
2675 if (!LoadWritePC(context, data))
2676 return false;
2677 }
2678 else
2679 return false;
2680 }
2681 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
2682 {
2683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
2684 return false;
2685 }
2686 else
2687 return false;
2688 }
2689 return true;
2690}
2691
Caroline Ticefa172202011-02-11 22:49:54 +00002692// STM stores multiple registers to consecutive memory locations using an address from a base register. The
2693// consecutive memory locations start at this address, and teh address just above the last of those locations can
2694// optionally be written back to the base register.
2695bool
2696EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
2697{
2698#if 0
2699 if ConditionPassed() then
2700 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2701 address = R[n];
2702
2703 for i = 0 to 14
2704 if registers<i> == ’1’ then
2705 if i == n && wback && i != LowestSetBit(registers) then
2706 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2707 else
2708 MemA[address,4] = R[i];
2709 address = address + 4;
2710
2711 if registers<15> == ’1’ then // Only possible for encoding A1
2712 MemA[address,4] = PCStoreValue();
2713 if wback then R[n] = R[n] + 4*BitCount(registers);
2714#endif
2715
2716 bool success = false;
2717 const uint32_t opcode = OpcodeAsUnsigned (&success);
2718 if (!success)
2719 return false;
2720
2721 if (ConditionPassed ())
2722 {
2723 uint32_t n;
2724 uint32_t registers = 0;
2725 bool wback;
2726 const uint32_t addr_byte_size = GetAddressByteSize();
2727
2728 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2729 switch (encoding)
2730 {
2731 case eEncodingT1:
2732 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
2733 n = Bits32 (opcode, 10, 8);
2734 registers = Bits32 (opcode, 7, 0);
2735 wback = true;
2736
2737 // if BitCount(registers) < 1 then UNPREDICTABLE;
2738 if (BitCount (registers) < 1)
2739 return false;
2740
2741 break;
2742
2743 case eEncodingT2:
2744 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
2745 n = Bits32 (opcode, 19, 16);
2746 registers = Bits32 (opcode, 15, 0);
2747 wback = BitIsSet (opcode, 21);
2748
2749 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
2750 if ((n == 15) || (BitCount (registers) < 2))
2751 return false;
2752
2753 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2754 if (wback && BitIsSet (registers, n))
2755 return false;
2756
2757 break;
2758
2759 case eEncodingA1:
2760 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2761 n = Bits32 (opcode, 19, 16);
2762 registers = Bits32 (opcode, 15, 0);
2763 wback = BitIsSet (opcode, 21);
2764
2765 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2766 if ((n == 15) || (BitCount (registers) < 1))
2767 return false;
2768
2769 break;
2770
2771 default:
2772 return false;
2773 }
2774
2775 // address = R[n];
2776 int32_t offset = 0;
2777 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2778 if (!success)
2779 return false;
2780
2781 EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterStore,
2782 eRegisterKindDWARF,
2783 dwarf_r0 + n,
2784 offset };
2785
2786 // for i = 0 to 14
2787 for (int i = 0; i < 14; ++i)
2788 {
2789 int lowest_set_bit = 14;
2790 // if registers<i> == ’1’ then
2791 if (BitIsSet (registers, i))
2792 {
2793 if (i < lowest_set_bit)
2794 lowest_set_bit = i;
2795 // if i == n && wback && i != LowestSetBit(registers) then
2796 if ((i == n) && wback && (i != lowest_set_bit))
2797 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
2798 WriteBits32UnknownToMemory (address + offset);
2799 else
2800 {
2801 // MemA[address,4] = R[i];
2802 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
2803 if (!success)
2804 return false;
2805
2806 context.arg1 = dwarf_r0 + i;
2807 context.arg2 = address + offset;
2808 if (!WriteMemoryUnsigned (context, address + offset, data, addr_byte_size))
2809 return false;
2810 }
2811
2812 // address = address + 4;
2813 offset += addr_byte_size;
2814 }
2815 }
2816
2817 // if registers<15> == ’1’ then // Only possible for encoding A1
2818 // MemA[address,4] = PCStoreValue();
2819 if (BitIsSet (registers, 15))
2820 {
2821 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
2822 if (!success)
2823 return false;
2824
2825 context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
2826 context.arg2 = address + offset - sp; // arg2 in the context is the stack pointer offset
2827 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
2828 if (!success)
2829 return false;
2830
2831 if (!WriteMemoryUnsigned (context, address + offset, pc + 8, addr_byte_size))
2832 return false;
2833 }
2834
2835 // if wback then R[n] = R[n] + 4*BitCount(registers);
2836 if (wback)
2837 {
2838 offset = addr_byte_size * BitCount (registers);
2839 context.type = EmulateInstruction::eContextAdjustBaseRegister;
2840 context.arg1 = dwarf_r0 + n;
2841 context.arg2 = offset;
2842 addr_t data = address + offset;
2843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
2844 return false;
2845 }
2846 }
2847 return true;
2848}
2849
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002850EmulateInstructionARM::ARMOpcode*
2851EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00002852{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002853 static ARMOpcode
2854 g_arm_opcodes[] =
2855 {
2856 //----------------------------------------------------------------------
2857 // Prologue instructions
2858 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00002859
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002860 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002861 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePush, "push <registers>" },
2862 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePush, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00002863
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002864 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002865 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #<const>" },
2866 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubR7IPImmediate, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00002867 // copy the stack pointer to ip
Johnny Chenc28a76d2011-02-01 18:51:48 +00002868 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMovRdSP, "mov ip, sp" },
2869 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add ip, sp, #<const>" },
2870 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubIPSPImmediate, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00002871
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002872 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002873 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00002874
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002875 // push one register
2876 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00002877 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00002878
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002879 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00002880 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2881 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00002882
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002883 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00002884 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002885 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00002886
Johnny Chenc28a76d2011-02-01 18:51:48 +00002887 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
2888 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePop, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00002889 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002890 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
2891
2892 //----------------------------------------------------------------------
2893 // Supervisor Call (previously Software Interrupt)
2894 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002895 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
2896
2897 //----------------------------------------------------------------------
2898 // Branch instructions
2899 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002900 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00002901 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
2902 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
2903 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
2904 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00002905 // for example, "bx lr"
2906 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002907
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002908 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00002909 // Data-processing instructions
2910 //----------------------------------------------------------------------
2911 // move bitwise not
2912 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
2913
2914 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002915 // Load instructions
2916 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00002917 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00002918 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00002919 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00002920 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
2921
2922 //----------------------------------------------------------------------
2923 // Store instructions
2924 //----------------------------------------------------------------------
2925 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002926
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002927 };
2928 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
2929
2930 for (size_t i=0; i<k_num_arm_opcodes; ++i)
2931 {
2932 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
2933 return &g_arm_opcodes[i];
2934 }
2935 return NULL;
2936}
Greg Clayton64c84432011-01-21 22:02:52 +00002937
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002938
2939EmulateInstructionARM::ARMOpcode*
2940EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00002941{
Johnny Chenfdd179e2011-01-31 20:09:28 +00002942
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002943 static ARMOpcode
2944 g_thumb_opcodes[] =
2945 {
2946 //----------------------------------------------------------------------
2947 // Prologue instructions
2948 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00002949
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002950 // push register(s)
Johnny Chenc28a76d2011-02-01 18:51:48 +00002951 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePush, "push <registers>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00002952 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <registers>" },
2953 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePush, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00002954
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002955 // set r7 to point to a stack offset
Johnny Chenc28a76d2011-02-01 18:51:48 +00002956 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdSPImmediate, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002957 // copy the stack pointer to r7
Johnny Chenc28a76d2011-02-01 18:51:48 +00002958 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00002959 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
2960 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00002961
Johnny Chenc9de9102011-02-11 19:12:30 +00002962 // PC-relative load into register (see also EmulateAddSPRm)
2963 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00002964
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002965 // adjust the stack pointer
Johnny Chenc28a76d2011-02-01 18:51:48 +00002966 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPRm, "add sp, <Rm>"},
2967 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSubSPImmdiate, "add sp, sp, #imm"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002968 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "sub.w sp, sp, #<const>"},
2969 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSubSPImmdiate, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002970
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002971 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00002972 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
2973 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00002974
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002975 //----------------------------------------------------------------------
2976 // Epilogue instructions
2977 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00002978
Johnny Chenc28a76d2011-02-01 18:51:48 +00002979 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddSPImmediate, "add sp, #imm"},
2980 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePop, "pop <registers>"},
Johnny Chend6c13f02011-02-08 20:36:34 +00002981 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <registers>" },
2982 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePop, "pop.w <register>" },
2983 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
2984 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00002985
2986 //----------------------------------------------------------------------
2987 // Supervisor Call (previously Software Interrupt)
2988 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00002989 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
2990
2991 //----------------------------------------------------------------------
2992 // If Then makes up to four following instructions conditional.
2993 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00002994 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
2995
2996 //----------------------------------------------------------------------
2997 // Branch instructions
2998 //----------------------------------------------------------------------
2999 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
3000 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
3001 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00003002 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003003 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00003004 // J1 == J2 == 1
3005 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
3006 // J1 == J2 == 1
3007 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
3008 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00003009 // for example, "bx lr"
3010 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00003011 // compare and branch
3012 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003013
3014 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00003015 // Data-processing instructions
3016 //----------------------------------------------------------------------
3017 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
3018 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00003019 // move from high register to high register
3020 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
3021 // move from low register to low register
3022 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00003023 // move immediate
3024 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdImm, "movs|mov<c> <Rd>, #imm8"},
3025 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMovRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00003026 // move bitwise not
3027 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00003028 // compare a register with immediate
3029 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00003030 // compare Rn with Rm (Rn and Rm both from r0-r7)
3031 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
3032 // compare Rn with Rm (Rn and Rm not both from r0-r7)
3033 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCmpRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00003034
3035 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003036 // Load instructions
3037 //----------------------------------------------------------------------
3038 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00003039 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00003040 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00003041 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
3042 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00003043 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
3044
3045 //----------------------------------------------------------------------
3046 // Store instructions
3047 //----------------------------------------------------------------------
3048 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
3049 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003050
Greg Clayton2b8e8b02011-02-01 00:49:32 +00003051 };
3052
3053 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
3054 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
3055 {
3056 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
3057 return &g_thumb_opcodes[i];
3058 }
3059 return NULL;
3060}
Greg Clayton64c84432011-01-21 22:02:52 +00003061
Greg Clayton31e2a382011-01-30 20:03:56 +00003062bool
3063EmulateInstructionARM::SetTargetTriple (const ConstString &triple)
3064{
3065 m_arm_isa = 0;
3066 const char *triple_cstr = triple.GetCString();
3067 if (triple_cstr)
3068 {
3069 const char *dash = ::strchr (triple_cstr, '-');
3070 if (dash)
3071 {
3072 std::string arch (triple_cstr, dash);
3073 const char *arch_cstr = arch.c_str();
3074 if (strcasecmp(arch_cstr, "armv4t") == 0)
3075 m_arm_isa = ARMv4T;
3076 else if (strcasecmp(arch_cstr, "armv4") == 0)
3077 m_arm_isa = ARMv4;
3078 else if (strcasecmp(arch_cstr, "armv5tej") == 0)
3079 m_arm_isa = ARMv5TEJ;
3080 else if (strcasecmp(arch_cstr, "armv5te") == 0)
3081 m_arm_isa = ARMv5TE;
3082 else if (strcasecmp(arch_cstr, "armv5t") == 0)
3083 m_arm_isa = ARMv5T;
3084 else if (strcasecmp(arch_cstr, "armv6k") == 0)
3085 m_arm_isa = ARMv6K;
3086 else if (strcasecmp(arch_cstr, "armv6") == 0)
3087 m_arm_isa = ARMv6;
3088 else if (strcasecmp(arch_cstr, "armv6t2") == 0)
3089 m_arm_isa = ARMv6T2;
3090 else if (strcasecmp(arch_cstr, "armv7") == 0)
3091 m_arm_isa = ARMv7;
3092 else if (strcasecmp(arch_cstr, "armv8") == 0)
3093 m_arm_isa = ARMv8;
3094 }
3095 }
3096 return m_arm_isa != 0;
3097}
3098
3099
Greg Clayton64c84432011-01-21 22:02:52 +00003100bool
3101EmulateInstructionARM::ReadInstruction ()
3102{
3103 bool success = false;
3104 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
3105 if (success)
3106 {
3107 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
3108 if (success)
3109 {
3110 Context read_inst_context = {eContextReadOpcode, 0, 0};
3111 if (m_inst_cpsr & MASK_CPSR_T)
3112 {
3113 m_inst_mode = eModeThumb;
3114 uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
3115
3116 if (success)
3117 {
3118 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
3119 {
3120 m_inst.opcode_type = eOpcode16;
3121 m_inst.opcode.inst16 = thumb_opcode;
3122 }
3123 else
3124 {
3125 m_inst.opcode_type = eOpcode32;
3126 m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
3127 }
3128 }
3129 }
3130 else
3131 {
3132 m_inst_mode = eModeARM;
3133 m_inst.opcode_type = eOpcode32;
3134 m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
3135 }
3136 }
3137 }
3138 if (!success)
3139 {
3140 m_inst_mode = eModeInvalid;
3141 m_inst_pc = LLDB_INVALID_ADDRESS;
3142 }
3143 return success;
3144}
3145
Johnny Chenee9b1f72011-02-09 01:00:31 +00003146uint32_t
3147EmulateInstructionARM::ArchVersion ()
3148{
3149 return m_arm_isa;
3150}
3151
Greg Clayton64c84432011-01-21 22:02:52 +00003152bool
3153EmulateInstructionARM::ConditionPassed ()
3154{
3155 if (m_inst_cpsr == 0)
3156 return false;
3157
3158 const uint32_t cond = CurrentCond ();
3159
3160 if (cond == UINT32_MAX)
3161 return false;
3162
3163 bool result = false;
3164 switch (UnsignedBits(cond, 3, 1))
3165 {
3166 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
3167 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
3168 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
3169 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
3170 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
3171 case 5:
3172 {
3173 bool n = (m_inst_cpsr & MASK_CPSR_N);
3174 bool v = (m_inst_cpsr & MASK_CPSR_V);
3175 result = n == v;
3176 }
3177 break;
3178 case 6:
3179 {
3180 bool n = (m_inst_cpsr & MASK_CPSR_N);
3181 bool v = (m_inst_cpsr & MASK_CPSR_V);
3182 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
3183 }
3184 break;
3185 case 7:
3186 result = true;
3187 break;
3188 }
3189
3190 if (cond & 1)
3191 result = !result;
3192 return result;
3193}
3194
Johnny Chen9ee056b2011-02-08 00:06:35 +00003195uint32_t
3196EmulateInstructionARM::CurrentCond ()
3197{
3198 switch (m_inst_mode)
3199 {
3200 default:
3201 case eModeInvalid:
3202 break;
3203
3204 case eModeARM:
3205 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
3206
3207 case eModeThumb:
3208 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
3209 // 'cond' field of the encoding.
3210 if (m_inst.opcode_type == eOpcode16 &&
3211 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
3212 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
3213 {
3214 return Bits32(m_inst.opcode.inst16, 11, 7);
3215 }
3216 else if (m_inst.opcode_type == eOpcode32 &&
3217 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
3218 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
3219 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
3220 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
3221 {
3222 return Bits32(m_inst.opcode.inst32, 25, 22);
3223 }
3224
3225 return m_it_session.GetCond();
3226 }
3227 return UINT32_MAX; // Return invalid value
3228}
3229
Johnny Chen9ee056b2011-02-08 00:06:35 +00003230bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00003231EmulateInstructionARM::InITBlock()
3232{
3233 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
3234}
3235
3236bool
3237EmulateInstructionARM::LastInITBlock()
3238{
3239 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
3240}
3241
3242bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00003243EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
3244{
3245 addr_t target;
3246
Johnny Chenee9b1f72011-02-09 01:00:31 +00003247 // Check the current instruction set.
3248 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00003249 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003250 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00003251 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003252
Johnny Chen9ee056b2011-02-08 00:06:35 +00003253 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003254 return false;
3255
3256 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003257}
3258
3259// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
3260bool
3261EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
3262{
3263 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00003264 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
3265 // we want to record it and issue a WriteRegister callback so the clients
3266 // can track the mode changes accordingly.
3267 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003268
3269 if (BitIsSet(addr, 0))
3270 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003271 if (CurrentInstrSet() != eModeThumb)
3272 {
3273 SelectInstrSet(eModeThumb);
3274 cpsr_changed = true;
3275 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003276 target = addr & 0xfffffffe;
3277 context.arg2 = eModeThumb;
3278 }
3279 else if (BitIsClear(addr, 1))
3280 {
Johnny Chen0f309db2011-02-09 19:11:32 +00003281 if (CurrentInstrSet() != eModeARM)
3282 {
3283 SelectInstrSet(eModeARM);
3284 cpsr_changed = true;
3285 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003286 target = addr & 0xfffffffc;
3287 context.arg2 = eModeARM;
3288 }
3289 else
3290 return false; // address<1:0> == '10' => UNPREDICTABLE
3291
Johnny Chen0f309db2011-02-09 19:11:32 +00003292 if (cpsr_changed)
3293 {
Johnny Chen558133b2011-02-09 23:59:17 +00003294 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00003295 return false;
3296 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00003297 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00003298 return false;
3299
3300 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00003301}
Greg Clayton64c84432011-01-21 22:02:52 +00003302
Johnny Chenee9b1f72011-02-09 01:00:31 +00003303// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
3304bool
3305EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
3306{
3307 if (ArchVersion() >= ARMv5T)
3308 return BXWritePC(context, addr);
3309 else
3310 return BranchWritePC((const Context)context, addr);
3311}
3312
Johnny Chen26863dc2011-02-09 23:43:29 +00003313// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
3314bool
3315EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
3316{
3317 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
3318 return BXWritePC(context, addr);
3319 else
3320 return BranchWritePC((const Context)context, addr);
3321}
3322
Johnny Chenee9b1f72011-02-09 01:00:31 +00003323EmulateInstructionARM::Mode
3324EmulateInstructionARM::CurrentInstrSet ()
3325{
3326 return m_inst_mode;
3327}
3328
3329// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00003330// ReadInstruction() is performed. This function has a side effect of updating
3331// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00003332bool
3333EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
3334{
Johnny Chen558133b2011-02-09 23:59:17 +00003335 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003336 switch (arm_or_thumb)
3337 {
3338 default:
3339 return false;
3340 eModeARM:
3341 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003342 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003343 break;
3344 eModeThumb:
3345 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00003346 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00003347 break;
3348 }
3349 return true;
3350}
3351
Johnny Chenef21b592011-02-10 01:52:38 +00003352// This function returns TRUE if the processor currently provides support for
3353// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
3354// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
3355bool
3356EmulateInstructionARM::UnalignedSupport()
3357{
3358 return (ArchVersion() >= ARMv7);
3359}
3360
Johnny Chenbf6ad172011-02-11 01:29:53 +00003361// The main addition and subtraction instructions can produce status information
3362// about both unsigned carry and signed overflow conditions. This status
3363// information can be used to synthesize multi-word additions and subtractions.
3364EmulateInstructionARM::AddWithCarryResult
3365EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
3366{
3367 uint32_t result;
3368 uint8_t carry_out;
3369 uint8_t overflow;
3370
3371 uint64_t unsigned_sum = x + y + carry_in;
3372 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
3373
3374 result = UnsignedBits(unsigned_sum, 31, 0);
3375 carry_out = (result == unsigned_sum ? 0 : 1);
3376 overflow = ((int32_t)result == signed_sum ? 0 : 1);
3377
3378 AddWithCarryResult res = { result, carry_out, overflow };
3379 return res;
3380}
3381
Greg Clayton64c84432011-01-21 22:02:52 +00003382bool
3383EmulateInstructionARM::EvaluateInstruction ()
3384{
Johnny Chenc315f862011-02-05 00:46:10 +00003385 // Advance the ITSTATE bits to their values for the next instruction.
3386 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
3387 m_it_session.ITAdvance();
3388
Johnny Chen357c30f2011-02-14 22:04:25 +00003389 // If the flags have changed, flush it out.
3390 if (m_new_inst_cpsr != m_inst_cpsr)
3391 m_inst_cpsr = m_new_inst_cpsr;
3392
Greg Clayton64c84432011-01-21 22:02:52 +00003393 return false;
3394}