blob: 2ea12e20d8f95af14715f3a6eb614414e4bffcae [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 Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
27#define APSR_C Bit32(m_inst_cpsr, CPSR_C)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V)
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{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000150 EmulateInstruction::Context context;
151 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
152 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000153
154 uint32_t random_data = rand ();
155 const uint32_t addr_byte_size = GetAddressByteSize();
156
Caroline Ticecc96eb52011-02-17 19:20:40 +0000157 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000158 return false;
159
160 return true;
161}
162
Caroline Tice713c2662011-02-11 17:59:55 +0000163// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
164bool
165EmulateInstructionARM::WriteBits32Unknown (int n)
166{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000167 EmulateInstruction::Context context;
168 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
169 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000170
Johnny Chen62ff6f52011-02-11 18:11:22 +0000171 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000172 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
173
174 if (!success)
175 return false;
176
177 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
178 return false;
179
180 return true;
181}
182
Johnny Chen08c25e82011-01-31 18:02:28 +0000183// Push Multiple Registers stores multiple registers to the stack, storing to
184// consecutive memory locations ending just below the address in SP, and updates
185// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000186bool
Johnny Chen9f687722011-02-18 00:02:28 +0000187EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000188{
189#if 0
190 // ARM pseudo code...
191 if (ConditionPassed())
192 {
193 EncodingSpecificOperations();
194 NullCheckIfThumbEE(13);
195 address = SP - 4*BitCount(registers);
196
197 for (i = 0 to 14)
198 {
199 if (registers<i> == ’1’)
200 {
201 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
202 MemA[address,4] = bits(32) UNKNOWN;
203 else
204 MemA[address,4] = R[i];
205 address = address + 4;
206 }
207 }
208
209 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
210 MemA[address,4] = PCStoreValue();
211
212 SP = SP - 4*BitCount(registers);
213 }
214#endif
215
216 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000217 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000218 if (!success)
219 return false;
220
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000222 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t addr_byte_size = GetAddressByteSize();
224 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000225 if (!success)
226 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000227 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000228 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000230 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000231 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000233 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000234 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 // if BitCount(registers) < 1 then UNPREDICTABLE;
236 if (BitCount(registers) < 1)
237 return false;
238 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000239 case eEncodingT2:
240 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000241 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000242 // if BitCount(registers) < 2 then UNPREDICTABLE;
243 if (BitCount(registers) < 2)
244 return false;
245 break;
246 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000249 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000253 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000254 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000255 // Instead of return false, let's handle the following case as well,
256 // which amounts to pushing one reg onto the full descending stacks.
257 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000258 break;
259 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000261 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000262 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000263 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000266 default:
267 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 }
Johnny Chence1ca772011-01-25 01:13:00 +0000269 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000270 addr_t addr = sp - sp_offset;
271 uint32_t i;
272
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000273 EmulateInstruction::Context context;
274 context.type = EmulateInstruction::eContextPushRegisterOnStack;
275 Register dwarf_reg;
276 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000277 for (i=0; i<15; ++i)
278 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000279 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000280 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000281 dwarf_reg.num = dwarf_r0 + i;
282 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
283 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000284 if (!success)
285 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000286 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000287 return false;
288 addr += addr_byte_size;
289 }
290 }
291
Johnny Chen7c1bf922011-02-08 23:49:37 +0000292 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000293 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000294 dwarf_reg.num = dwarf_pc;
295 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000296 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000297 if (!success)
298 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000299 if (!MemAWrite (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000300 return false;
301 }
302
303 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000304 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000305
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000306 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000307 return false;
308 }
309 return true;
310}
311
Johnny Chenef85e912011-01-31 23:07:40 +0000312// Pop Multiple Registers loads multiple registers from the stack, loading from
313// consecutive memory locations staring at the address in SP, and updates
314// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000315bool
Johnny Chen9f687722011-02-18 00:02:28 +0000316EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000317{
318#if 0
319 // ARM pseudo code...
320 if (ConditionPassed())
321 {
322 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
323 address = SP;
324 for i = 0 to 14
325 if registers<i> == ‘1’ then
326 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
327 if registers<15> == ‘1’ then
328 if UnalignedAllowed then
329 LoadWritePC(MemU[address,4]);
330 else
331 LoadWritePC(MemA[address,4]);
332 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
333 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
334 }
335#endif
336
337 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000338 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000339 if (!success)
340 return false;
341
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000343 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 const uint32_t addr_byte_size = GetAddressByteSize();
345 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000346 if (!success)
347 return false;
348 uint32_t registers = 0;
349 uint32_t Rt; // the destination register
350 switch (encoding) {
351 case eEncodingT1:
352 registers = Bits32(opcode, 7, 0);
353 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000354 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000355 registers |= (1u << 15);
356 // if BitCount(registers) < 1 then UNPREDICTABLE;
357 if (BitCount(registers) < 1)
358 return false;
359 break;
360 case eEncodingT2:
361 // Ignore bit 13.
362 registers = Bits32(opcode, 15, 0) & ~0x2000;
363 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000364 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000365 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000366 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
367 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
368 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000369 break;
370 case eEncodingT3:
371 Rt = Bits32(opcode, 15, 12);
372 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000373 if (Rt == 13)
374 return false;
375 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000376 return false;
377 registers = (1u << Rt);
378 break;
379 case eEncodingA1:
380 registers = Bits32(opcode, 15, 0);
381 // Instead of return false, let's handle the following case as well,
382 // which amounts to popping one reg from the full descending stacks.
383 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
384
385 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000386 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000387 return false;
388 break;
389 case eEncodingA2:
390 Rt = Bits32(opcode, 15, 12);
391 // if t == 13 then UNPREDICTABLE;
392 if (Rt == dwarf_sp)
393 return false;
394 registers = (1u << Rt);
395 break;
396 default:
397 return false;
398 }
399 addr_t sp_offset = addr_byte_size * BitCount (registers);
400 addr_t addr = sp;
401 uint32_t i, data;
402
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000403 EmulateInstruction::Context context;
404 context.type = EmulateInstruction::eContextPopRegisterOffStack;
405 Register dwarf_reg;
406 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000407 for (i=0; i<15; ++i)
408 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000409 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 dwarf_reg.num = dwarf_r0 + i;
412 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000413 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000414 if (!success)
415 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000416 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000417 return false;
418 addr += addr_byte_size;
419 }
420 }
421
Johnny Chen7c1bf922011-02-08 23:49:37 +0000422 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000423 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000424 dwarf_reg.num = dwarf_pc;
425 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000426 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000427 if (!success)
428 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000429 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000430 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000431 return false;
432 addr += addr_byte_size;
433 }
434
435 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000436 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000437
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
Johnny Chen9f687722011-02-18 00:02:28 +0000447EmulateInstructionARM::EmulateADDRdSPImm (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
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000494 EmulateInstruction::Context context;
495 context.type = EmulateInstruction::eContextRegisterPlusOffset;
496 Register sp_reg;
497 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
498 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000499
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501 return false;
502 }
503 return true;
504}
505
Johnny Chen2ccad832011-01-28 19:57:25 +0000506// Set r7 or ip to the current stack pointer.
507// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508bool
Johnny Chen9f687722011-02-18 00:02:28 +0000509EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000510{
511#if 0
512 // ARM pseudo code...
513 if (ConditionPassed())
514 {
515 EncodingSpecificOperations();
516 result = R[m];
517 if d == 15 then
518 ALUWritePC(result); // setflags is always FALSE here
519 else
520 R[d] = result;
521 if setflags then
522 APSR.N = result<31>;
523 APSR.Z = IsZeroBit(result);
524 // APSR.C unchanged
525 // APSR.V unchanged
526 }
527#endif
528
529 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000530 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000531 //if (!success)
532 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000533
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000535 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000537 if (!success)
538 return false;
539 uint32_t Rd; // the destination register
540 switch (encoding) {
541 case eEncodingT1:
542 Rd = 7;
543 break;
544 case eEncodingA1:
545 Rd = 12;
546 break;
547 default:
548 return false;
549 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000550
551 EmulateInstruction::Context context;
552 context.type = EmulateInstruction::eContextRegisterPlusOffset;
553 Register sp_reg;
554 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
555 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000556
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000557 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000558 return false;
559 }
560 return true;
561}
562
Johnny Chen1c13b622011-01-29 00:11:15 +0000563// Move from high register (r8-r15) to low register (r0-r7).
564// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000565bool
Johnny Chen9f687722011-02-18 00:02:28 +0000566EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000567{
Johnny Chen9f687722011-02-18 00:02:28 +0000568 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000569}
570
571// Move from register to register.
572// MOV (register)
573bool
Johnny Chen9f687722011-02-18 00:02:28 +0000574EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000575{
Johnny Chen1c13b622011-01-29 00:11:15 +0000576#if 0
577 // ARM pseudo code...
578 if (ConditionPassed())
579 {
580 EncodingSpecificOperations();
581 result = R[m];
582 if d == 15 then
583 ALUWritePC(result); // setflags is always FALSE here
584 else
585 R[d] = result;
586 if setflags then
587 APSR.N = result<31>;
588 APSR.Z = IsZeroBit(result);
589 // APSR.C unchanged
590 // APSR.V unchanged
591 }
592#endif
593
594 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000595 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000596 if (!success)
597 return false;
598
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 {
601 uint32_t Rm; // the source register
602 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000603 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 switch (encoding) {
605 case eEncodingT1:
606 Rm = Bits32(opcode, 6, 3);
Johnny Chenbd599902011-02-10 21:39:01 +0000607 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 1);
Johnny Chen338bf542011-02-10 19:29:03 +0000608 setflags = false;
609 break;
610 case eEncodingT2:
611 Rm = Bits32(opcode, 5, 3);
612 Rd = Bits32(opcode, 2, 1);
613 setflags = true;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 break;
615 default:
616 return false;
617 }
Johnny Chenca67d1c2011-02-17 01:35:27 +0000618 uint32_t result = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000619 if (!success)
620 return false;
621
622 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000623 EmulateInstruction::Context context;
624 context.type = EmulateInstruction::eContextRegisterPlusOffset;
625 Register dwarf_reg;
626 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
627 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000628
Johnny Chen10530c22011-02-17 22:37:12 +0000629 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000630 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000631 }
632 return true;
633}
634
Johnny Chen357c30f2011-02-14 22:04:25 +0000635// Move (immediate) writes an immediate value to the destination register. It
636// can optionally update the condition flags based on the value.
637// MOV (immediate)
638bool
Johnny Chen9f687722011-02-18 00:02:28 +0000639EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000640{
641#if 0
642 // ARM pseudo code...
643 if (ConditionPassed())
644 {
645 EncodingSpecificOperations();
646 result = imm32;
647 if d == 15 then // Can only occur for ARM encoding
648 ALUWritePC(result); // setflags is always FALSE here
649 else
650 R[d] = result;
651 if setflags then
652 APSR.N = result<31>;
653 APSR.Z = IsZeroBit(result);
654 APSR.C = carry;
655 // APSR.V unchanged
656 }
657#endif
658 bool success = false;
659 const uint32_t opcode = OpcodeAsUnsigned (&success);
660 if (!success)
661 return false;
662
663 if (ConditionPassed())
664 {
665 uint32_t Rd; // the destination register
666 uint32_t imm12; // some intermediate result
667 uint32_t imm32; // the immediate value to be written to Rd
668 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
669 bool setflags;
670 switch (encoding) {
671 case eEncodingT1:
672 Rd = Bits32(opcode, 11, 8);
673 setflags = !InITBlock();
674 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000675 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000676 break;
677 case eEncodingT2:
678 Rd = Bits32(opcode, 15, 12);
679 setflags = BitIsSet(opcode, 20);
680 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000681 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000682 if (BadReg(Rd))
683 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000684 break;
685 default:
686 return false;
687 }
688 uint32_t result = imm32;
689
690 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000691 EmulateInstruction::Context context;
692 context.type = EmulateInstruction::eContextImmediate;
693 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000694
Johnny Chen10530c22011-02-17 22:37:12 +0000695 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000696 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000697 }
698 return true;
699}
700
Johnny Chen28070c32011-02-12 01:27:26 +0000701// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
702// the destination register. It can optionally update the condition flags based
703// on the value.
704// MVN (immediate)
705bool
Johnny Chen9f687722011-02-18 00:02:28 +0000706EmulateInstructionARM::EmulateMVNRdImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000707{
708#if 0
709 // ARM pseudo code...
710 if (ConditionPassed())
711 {
712 EncodingSpecificOperations();
713 result = NOT(imm32);
714 if d == 15 then // Can only occur for ARM encoding
715 ALUWritePC(result); // setflags is always FALSE here
716 else
717 R[d] = result;
718 if setflags then
719 APSR.N = result<31>;
720 APSR.Z = IsZeroBit(result);
721 APSR.C = carry;
722 // APSR.V unchanged
723 }
724#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000725 bool success = false;
726 const uint32_t opcode = OpcodeAsUnsigned (&success);
727 if (!success)
728 return false;
729
730 if (ConditionPassed())
731 {
732 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000733 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
734 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
735 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000736 bool setflags;
737 switch (encoding) {
738 case eEncodingT1:
739 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000740 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000741 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000742 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000743 break;
744 case eEncodingA1:
745 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000746 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000747 imm12 = Bits32(opcode, 11, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000748 imm32 = ARMExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000749 break;
750 default:
751 return false;
752 }
753 uint32_t result = ~imm32;
754
755 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000756 EmulateInstruction::Context context;
757 context.type = EmulateInstruction::eContextImmediate;
758 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000759
Johnny Chen10530c22011-02-17 22:37:12 +0000760 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000761 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000762 }
763 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000764}
765
Johnny Chen788e0552011-01-27 22:52:23 +0000766// PC relative immediate load into register, possibly followed by ADD (SP plus register).
767// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000768bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000769EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000770{
771#if 0
772 // ARM pseudo code...
773 if (ConditionPassed())
774 {
775 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
776 base = Align(PC,4);
777 address = if add then (base + imm32) else (base - imm32);
778 data = MemU[address,4];
779 if t == 15 then
780 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
781 elsif UnalignedSupport() || address<1:0> = ‘00’ then
782 R[t] = data;
783 else // Can only apply before ARMv7
784 if CurrentInstrSet() == InstrSet_ARM then
785 R[t] = ROR(data, 8*UInt(address<1:0>));
786 else
787 R[t] = bits(32) UNKNOWN;
788 }
789#endif
790
791 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000792 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000793 if (!success)
794 return false;
795
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000796 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000797 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000798 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000799 if (!success)
800 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000801
802 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000803 EmulateInstruction::Context context;
804 context.type = EmulateInstruction::eContextRegisterPlusOffset;
805 Register pc_reg;
806 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
807 context.SetRegisterPlusOffset (pc_reg, 0);
808
Johnny Chenc9de9102011-02-11 19:12:30 +0000809 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000810 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000811 bool add; // +imm32 or -imm32?
812 addr_t base; // the base address
813 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000814 uint32_t data; // the literal data value from the PC relative load
815 switch (encoding) {
816 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000817 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000818 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000819 add = true;
820 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000821 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000822 break;
823 case eEncodingT2:
824 Rt = Bits32(opcode, 15, 12);
825 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
826 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000827 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000828 return false;
829 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000830 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000831 break;
832 default:
833 return false;
834 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000835
836 if (add)
837 address = base + imm32;
838 else
839 address = base - imm32;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000840 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000841 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000842 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000843
844 if (Rt == 15)
845 {
846 if (Bits32(address, 1, 0) == 0)
847 {
848 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000849 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000850 return false;
851 }
852 else
853 return false;
854 }
855 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
856 {
857 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
858 return false;
859 }
860 else // We don't handle ARM for now.
861 return false;
862
863 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000864 return false;
865 }
866 return true;
867}
868
Johnny Chen5b442b72011-01-27 19:34:30 +0000869// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000870// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000871bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000872EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000873{
874#if 0
875 // ARM pseudo code...
876 if (ConditionPassed())
877 {
878 EncodingSpecificOperations();
879 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
880 if d == 15 then // Can only occur for ARM encoding
881 ALUWritePC(result); // setflags is always FALSE here
882 else
883 R[d] = result;
884 if setflags then
885 APSR.N = result<31>;
886 APSR.Z = IsZeroBit(result);
887 APSR.C = carry;
888 APSR.V = overflow;
889 }
890#endif
891
892 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000893 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000894 if (!success)
895 return false;
896
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000897 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000898 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000899 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000900 if (!success)
901 return false;
902 uint32_t imm32; // the immediate operand
903 switch (encoding) {
904 case eEncodingT2:
905 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
906 break;
907 default:
908 return false;
909 }
910 addr_t sp_offset = imm32;
911 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
912
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000913 EmulateInstruction::Context context;
914 context.type = EmulateInstruction::eContextAdjustStackPointer;
915 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000916
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000917 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000918 return false;
919 }
920 return true;
921}
922
923// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000924// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000925bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000926EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000927{
928#if 0
929 // ARM pseudo code...
930 if (ConditionPassed())
931 {
932 EncodingSpecificOperations();
933 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
934 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
935 if d == 15 then
936 ALUWritePC(result); // setflags is always FALSE here
937 else
938 R[d] = result;
939 if setflags then
940 APSR.N = result<31>;
941 APSR.Z = IsZeroBit(result);
942 APSR.C = carry;
943 APSR.V = overflow;
944 }
945#endif
946
947 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000948 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000949 if (!success)
950 return false;
951
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000952 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000953 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000954 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000955 if (!success)
956 return false;
957 uint32_t Rm; // the second operand
958 switch (encoding) {
959 case eEncodingT2:
960 Rm = Bits32(opcode, 6, 3);
961 break;
962 default:
963 return false;
964 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000965 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000966 if (!success)
967 return false;
968
969 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
970
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000971 EmulateInstruction::Context context;
972 context.type = EmulateInstruction::eContextAdjustStackPointer;
973 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000974
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000975 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000976 return false;
977 }
978 return true;
979}
980
Johnny Chen9b8d7832011-02-02 01:13:56 +0000981// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
982// at a PC-relative address, and changes instruction set from ARM to Thumb, or
983// from Thumb to ARM.
984// BLX (immediate)
985bool
986EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
987{
988#if 0
989 // ARM pseudo code...
990 if (ConditionPassed())
991 {
992 EncodingSpecificOperations();
993 if CurrentInstrSet() == InstrSet_ARM then
994 LR = PC - 4;
995 else
996 LR = PC<31:1> : '1';
997 if targetInstrSet == InstrSet_ARM then
998 targetAddress = Align(PC,4) + imm32;
999 else
1000 targetAddress = PC + imm32;
1001 SelectInstrSet(targetInstrSet);
1002 BranchWritePC(targetAddress);
1003 }
1004#endif
1005
1006 bool success = false;
1007 const uint32_t opcode = OpcodeAsUnsigned (&success);
1008 if (!success)
1009 return false;
1010
1011 if (ConditionPassed())
1012 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001013 EmulateInstruction::Context context;
1014 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001015 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001016 if (!success)
1017 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001018 addr_t lr; // next instruction address
1019 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001020 int32_t imm32; // PC-relative offset
1021 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001022 case eEncodingT1:
1023 {
1024 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001025 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001026 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001027 uint32_t J1 = Bit32(opcode, 13);
1028 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001029 uint32_t imm11 = Bits32(opcode, 10, 0);
1030 uint32_t I1 = !(J1 ^ S);
1031 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001032 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001033 imm32 = llvm::SignExtend32<25>(imm25);
1034 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001035 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001036 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001037 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001038 break;
1039 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001040 case eEncodingT2:
1041 {
1042 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001043 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001044 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001045 uint32_t J1 = Bit32(opcode, 13);
1046 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001047 uint32_t imm10L = Bits32(opcode, 10, 1);
1048 uint32_t I1 = !(J1 ^ S);
1049 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001050 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001051 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001052 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001053 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001054 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001055 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001056 break;
1057 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001058 case eEncodingA1:
1059 lr = pc + 4; // return address
1060 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001061 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001062 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001063 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001064 case eEncodingA2:
1065 lr = pc + 4; // return address
1066 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1067 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001068 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001069 break;
1070 default:
1071 return false;
1072 }
1073 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1074 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001075 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001076 return false;
1077 }
1078 return true;
1079}
1080
1081// Branch with Link and Exchange (register) calls a subroutine at an address and
1082// instruction set specified by a register.
1083// BLX (register)
1084bool
1085EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1086{
1087#if 0
1088 // ARM pseudo code...
1089 if (ConditionPassed())
1090 {
1091 EncodingSpecificOperations();
1092 target = R[m];
1093 if CurrentInstrSet() == InstrSet_ARM then
1094 next_instr_addr = PC - 4;
1095 LR = next_instr_addr;
1096 else
1097 next_instr_addr = PC - 2;
1098 LR = next_instr_addr<31:1> : ‘1’;
1099 BXWritePC(target);
1100 }
1101#endif
1102
1103 bool success = false;
1104 const uint32_t opcode = OpcodeAsUnsigned (&success);
1105 if (!success)
1106 return false;
1107
1108 if (ConditionPassed())
1109 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001110 EmulateInstruction::Context context;
1111 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001112 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1113 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 if (!success)
1115 return false;
1116 uint32_t Rm; // the register with the target address
1117 switch (encoding) {
1118 case eEncodingT1:
1119 lr = (pc + 2) | 1u; // return address
1120 Rm = Bits32(opcode, 6, 3);
1121 // if m == 15 then UNPREDICTABLE;
1122 if (Rm == 15)
1123 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001124 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001125 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001126 break;
1127 case eEncodingA1:
1128 lr = pc + 4; // return address
1129 Rm = Bits32(opcode, 3, 0);
1130 // if m == 15 then UNPREDICTABLE;
1131 if (Rm == 15)
1132 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001133 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001134 default:
1135 return false;
1136 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001137 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1138 if (!success)
1139 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001140 Register dwarf_reg;
1141 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1142 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001143 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1144 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001145 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001146 return false;
1147 }
1148 return true;
1149}
1150
Johnny Chenab3b3512011-02-12 00:10:51 +00001151// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1152// BX
1153bool
1154EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1155{
1156#if 0
1157 // ARM pseudo code...
1158 if (ConditionPassed())
1159 {
1160 EncodingSpecificOperations();
1161 BXWritePC(R[m]);
1162 }
1163#endif
1164
1165 bool success = false;
1166 const uint32_t opcode = OpcodeAsUnsigned (&success);
1167 if (!success)
1168 return false;
1169
1170 if (ConditionPassed())
1171 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001172 EmulateInstruction::Context context;
1173 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001174 uint32_t Rm; // the register with the target address
1175 switch (encoding) {
1176 case eEncodingT1:
1177 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001178 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001179 return false;
1180 break;
1181 case eEncodingA1:
1182 Rm = Bits32(opcode, 3, 0);
1183 break;
1184 default:
1185 return false;
1186 }
1187 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1188 if (!success)
1189 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001190
1191 Register dwarf_reg;
1192 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001193 context.SetRegister (dwarf_reg);
1194 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001195 return false;
1196 }
1197 return true;
1198}
1199
Johnny Chen0d0148e2011-01-28 02:26:08 +00001200// Set r7 to point to some ip offset.
1201// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001202bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001203EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001204{
1205#if 0
1206 // ARM pseudo code...
1207 if (ConditionPassed())
1208 {
1209 EncodingSpecificOperations();
1210 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1211 if d == 15 then // Can only occur for ARM encoding
1212 ALUWritePC(result); // setflags is always FALSE here
1213 else
1214 R[d] = result;
1215 if setflags then
1216 APSR.N = result<31>;
1217 APSR.Z = IsZeroBit(result);
1218 APSR.C = carry;
1219 APSR.V = overflow;
1220 }
1221#endif
1222
1223 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001224 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001225 if (!success)
1226 return false;
1227
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001228 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001229 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001230 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001231 if (!success)
1232 return false;
1233 uint32_t imm32;
1234 switch (encoding) {
1235 case eEncodingA1:
1236 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1237 break;
1238 default:
1239 return false;
1240 }
1241 addr_t ip_offset = imm32;
1242 addr_t addr = ip - ip_offset; // the adjusted ip value
1243
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001244 EmulateInstruction::Context context;
1245 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1246 Register dwarf_reg;
1247 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1248 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001249
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001250 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001251 return false;
1252 }
1253 return true;
1254}
1255
1256// Set ip to point to some stack offset.
1257// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001258bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001259EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001260{
1261#if 0
1262 // ARM pseudo code...
1263 if (ConditionPassed())
1264 {
1265 EncodingSpecificOperations();
1266 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1267 if d == 15 then // Can only occur for ARM encoding
1268 ALUWritePC(result); // setflags is always FALSE here
1269 else
1270 R[d] = result;
1271 if setflags then
1272 APSR.N = result<31>;
1273 APSR.Z = IsZeroBit(result);
1274 APSR.C = carry;
1275 APSR.V = overflow;
1276 }
1277#endif
1278
1279 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001280 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001281 if (!success)
1282 return false;
1283
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001284 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001285 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001286 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001287 if (!success)
1288 return false;
1289 uint32_t imm32;
1290 switch (encoding) {
1291 case eEncodingA1:
1292 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1293 break;
1294 default:
1295 return false;
1296 }
1297 addr_t sp_offset = imm32;
1298 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1299
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001300 EmulateInstruction::Context context;
1301 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1302 Register dwarf_reg;
1303 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1304 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001305
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001306 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001307 return false;
1308 }
1309 return true;
1310}
1311
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001312// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001313bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001314EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001315{
1316#if 0
1317 // ARM pseudo code...
1318 if (ConditionPassed())
1319 {
1320 EncodingSpecificOperations();
1321 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1322 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001323 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001324 else
1325 R[d] = result;
1326 if setflags then
1327 APSR.N = result<31>;
1328 APSR.Z = IsZeroBit(result);
1329 APSR.C = carry;
1330 APSR.V = overflow;
1331 }
1332#endif
1333
1334 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001335 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001336 if (!success)
1337 return false;
1338
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001339 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001340 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001341 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001342 if (!success)
1343 return false;
1344 uint32_t imm32;
1345 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001346 case eEncodingT1:
1347 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001348 case eEncodingT2:
1349 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1350 break;
1351 case eEncodingT3:
1352 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1353 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001354 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001355 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001356 break;
1357 default:
1358 return false;
1359 }
1360 addr_t sp_offset = imm32;
1361 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1362
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001363 EmulateInstruction::Context context;
1364 context.type = EmulateInstruction::eContextAdjustStackPointer;
1365 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001366
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001367 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001368 return false;
1369 }
1370 return true;
1371}
1372
Johnny Chen08c25e82011-01-31 18:02:28 +00001373// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001374bool
1375EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001376{
1377#if 0
1378 // ARM pseudo code...
1379 if (ConditionPassed())
1380 {
1381 EncodingSpecificOperations();
1382 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1383 address = if index then offset_addr else R[n];
1384 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1385 if wback then R[n] = offset_addr;
1386 }
1387#endif
1388
1389 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001390 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001391 if (!success)
1392 return false;
1393
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001394 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001395 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001396 const uint32_t addr_byte_size = GetAddressByteSize();
1397 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001398 if (!success)
1399 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001400 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001401 uint32_t imm12;
1402 switch (encoding) {
1403 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001404 Rt = Bits32(opcode, 15, 12);
1405 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001406 break;
1407 default:
1408 return false;
1409 }
1410 addr_t sp_offset = imm12;
1411 addr_t addr = sp - sp_offset;
1412
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 EmulateInstruction::Context context;
1414 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1415 Register dwarf_reg;
1416 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001417 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001418 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001419 dwarf_reg.num = dwarf_r0 + Rt;
1420 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1421 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001422 if (!success)
1423 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001424 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001425 return false;
1426 }
1427 else
1428 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001429 dwarf_reg.num = dwarf_pc;
1430 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001431 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001432 if (!success)
1433 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001434 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001435 return false;
1436 }
1437
1438 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001439 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001440
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001441 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001442 return false;
1443 }
1444 return true;
1445}
1446
Johnny Chen08c25e82011-01-31 18:02:28 +00001447// Vector Push stores multiple extension registers to the stack.
1448// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001449bool
1450EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001451{
1452#if 0
1453 // ARM pseudo code...
1454 if (ConditionPassed())
1455 {
1456 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1457 address = SP - imm32;
1458 SP = SP - imm32;
1459 if single_regs then
1460 for r = 0 to regs-1
1461 MemA[address,4] = S[d+r]; address = address+4;
1462 else
1463 for r = 0 to regs-1
1464 // Store as two word-aligned words in the correct order for current endianness.
1465 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1466 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1467 address = address+8;
1468 }
1469#endif
1470
1471 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001472 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001473 if (!success)
1474 return false;
1475
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001476 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001477 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001478 const uint32_t addr_byte_size = GetAddressByteSize();
1479 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001480 if (!success)
1481 return false;
1482 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001483 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001484 uint32_t imm32; // stack offset
1485 uint32_t regs; // number of registers
1486 switch (encoding) {
1487 case eEncodingT1:
1488 case eEncodingA1:
1489 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001490 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001491 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1492 // If UInt(imm8) is odd, see "FSTMX".
1493 regs = Bits32(opcode, 7, 0) / 2;
1494 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1495 if (regs == 0 || regs > 16 || (d + regs) > 32)
1496 return false;
1497 break;
1498 case eEncodingT2:
1499 case eEncodingA2:
1500 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001501 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001502 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1503 regs = Bits32(opcode, 7, 0);
1504 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1505 if (regs == 0 || regs > 16 || (d + regs) > 32)
1506 return false;
1507 break;
1508 default:
1509 return false;
1510 }
1511 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1512 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1513 addr_t sp_offset = imm32;
1514 addr_t addr = sp - sp_offset;
1515 uint32_t i;
1516
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001517 EmulateInstruction::Context context;
1518 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1519 Register dwarf_reg;
1520 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001521 for (i=d; i<regs; ++i)
1522 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001523 dwarf_reg.num = start_reg + i;
1524 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001525 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001526 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001527 if (!success)
1528 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001529 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001530 return false;
1531 addr += reg_byte_size;
1532 }
1533
1534 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001535 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001536
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001537 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001538 return false;
1539 }
1540 return true;
1541}
1542
Johnny Chen587a0a42011-02-01 18:35:28 +00001543// Vector Pop loads multiple extension registers from the stack.
1544// It also updates SP to point just above the loaded data.
1545bool
1546EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1547{
1548#if 0
1549 // ARM pseudo code...
1550 if (ConditionPassed())
1551 {
1552 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1553 address = SP;
1554 SP = SP + imm32;
1555 if single_regs then
1556 for r = 0 to regs-1
1557 S[d+r] = MemA[address,4]; address = address+4;
1558 else
1559 for r = 0 to regs-1
1560 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1561 // Combine the word-aligned words in the correct order for current endianness.
1562 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1563 }
1564#endif
1565
1566 bool success = false;
1567 const uint32_t opcode = OpcodeAsUnsigned (&success);
1568 if (!success)
1569 return false;
1570
1571 if (ConditionPassed())
1572 {
1573 const uint32_t addr_byte_size = GetAddressByteSize();
1574 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1575 if (!success)
1576 return false;
1577 bool single_regs;
1578 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1579 uint32_t imm32; // stack offset
1580 uint32_t regs; // number of registers
1581 switch (encoding) {
1582 case eEncodingT1:
1583 case eEncodingA1:
1584 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001585 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001586 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1587 // If UInt(imm8) is odd, see "FLDMX".
1588 regs = Bits32(opcode, 7, 0) / 2;
1589 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1590 if (regs == 0 || regs > 16 || (d + regs) > 32)
1591 return false;
1592 break;
1593 case eEncodingT2:
1594 case eEncodingA2:
1595 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001596 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001597 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1598 regs = Bits32(opcode, 7, 0);
1599 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1600 if (regs == 0 || regs > 16 || (d + regs) > 32)
1601 return false;
1602 break;
1603 default:
1604 return false;
1605 }
1606 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1607 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1608 addr_t sp_offset = imm32;
1609 addr_t addr = sp;
1610 uint32_t i;
1611 uint64_t data; // uint64_t to accomodate 64-bit registers.
1612
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001613 EmulateInstruction::Context context;
1614 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1615 Register dwarf_reg;
1616 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001617 for (i=d; i<regs; ++i)
1618 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001619 dwarf_reg.num = start_reg + i;
1620 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001621 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001622 if (!success)
1623 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001624 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001625 return false;
1626 addr += reg_byte_size;
1627 }
1628
1629 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001630 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001631
1632 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1633 return false;
1634 }
1635 return true;
1636}
1637
Johnny Chenb77be412011-02-04 00:40:18 +00001638// SVC (previously SWI)
1639bool
1640EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1641{
1642#if 0
1643 // ARM pseudo code...
1644 if (ConditionPassed())
1645 {
1646 EncodingSpecificOperations();
1647 CallSupervisor();
1648 }
1649#endif
1650
1651 bool success = false;
1652 const uint32_t opcode = OpcodeAsUnsigned (&success);
1653 if (!success)
1654 return false;
1655
1656 if (ConditionPassed())
1657 {
1658 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1659 addr_t lr; // next instruction address
1660 if (!success)
1661 return false;
1662 uint32_t imm32; // the immediate constant
1663 uint32_t mode; // ARM or Thumb mode
1664 switch (encoding) {
1665 case eEncodingT1:
1666 lr = (pc + 2) | 1u; // return address
1667 imm32 = Bits32(opcode, 7, 0);
1668 mode = eModeThumb;
1669 break;
1670 case eEncodingA1:
1671 lr = pc + 4; // return address
1672 imm32 = Bits32(opcode, 23, 0);
1673 mode = eModeARM;
1674 break;
1675 default:
1676 return false;
1677 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001678
1679 EmulateInstruction::Context context;
1680 context.type = EmulateInstruction::eContextSupervisorCall;
1681 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001682 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1683 return false;
1684 }
1685 return true;
1686}
1687
Johnny Chenc315f862011-02-05 00:46:10 +00001688// If Then makes up to four following instructions (the IT block) conditional.
1689bool
1690EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1691{
1692#if 0
1693 // ARM pseudo code...
1694 EncodingSpecificOperations();
1695 ITSTATE.IT<7:0> = firstcond:mask;
1696#endif
1697
1698 bool success = false;
1699 const uint32_t opcode = OpcodeAsUnsigned (&success);
1700 if (!success)
1701 return false;
1702
1703 m_it_session.InitIT(Bits32(opcode, 7, 0));
1704 return true;
1705}
1706
Johnny Chen3b620b32011-02-07 20:11:47 +00001707// Branch causes a branch to a target address.
1708bool
1709EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1710{
1711#if 0
1712 // ARM pseudo code...
1713 if (ConditionPassed())
1714 {
1715 EncodingSpecificOperations();
1716 BranchWritePC(PC + imm32);
1717 }
1718#endif
1719
1720 bool success = false;
1721 const uint32_t opcode = OpcodeAsUnsigned (&success);
1722 if (!success)
1723 return false;
1724
Johnny Chen9ee056b2011-02-08 00:06:35 +00001725 if (ConditionPassed())
1726 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001727 EmulateInstruction::Context context;
1728 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001729 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001730 if (!success)
1731 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001732 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001733 int32_t imm32; // PC-relative offset
1734 switch (encoding) {
1735 case eEncodingT1:
1736 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1737 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1738 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001739 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001740 break;
1741 case eEncodingT2:
1742 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1743 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001744 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001745 break;
1746 case eEncodingT3:
1747 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1748 {
Johnny Chenbd599902011-02-10 21:39:01 +00001749 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001750 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001751 uint32_t J1 = Bit32(opcode, 13);
1752 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001753 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001754 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001755 imm32 = llvm::SignExtend32<21>(imm21);
1756 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001757 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001758 break;
1759 }
1760 case eEncodingT4:
1761 {
Johnny Chenbd599902011-02-10 21:39:01 +00001762 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001763 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001764 uint32_t J1 = Bit32(opcode, 13);
1765 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001766 uint32_t imm11 = Bits32(opcode, 10, 0);
1767 uint32_t I1 = !(J1 ^ S);
1768 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001769 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001770 imm32 = llvm::SignExtend32<25>(imm25);
1771 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001772 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001773 break;
1774 }
1775 case eEncodingA1:
1776 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1777 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001778 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001779 break;
1780 default:
1781 return false;
1782 }
1783 if (!BranchWritePC(context, target))
1784 return false;
1785 }
1786 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001787}
1788
Johnny Chen53ebab72011-02-08 23:21:57 +00001789// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1790// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1791// CBNZ, CBZ
1792bool
1793EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1794{
1795#if 0
1796 // ARM pseudo code...
1797 EncodingSpecificOperations();
1798 if nonzero ^ IsZero(R[n]) then
1799 BranchWritePC(PC + imm32);
1800#endif
1801
1802 bool success = false;
1803 const uint32_t opcode = OpcodeAsUnsigned (&success);
1804 if (!success)
1805 return false;
1806
1807 // Read the register value from the operand register Rn.
1808 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1809 if (!success)
1810 return false;
1811
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001812 EmulateInstruction::Context context;
1813 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001814 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1815 if (!success)
1816 return false;
1817
1818 addr_t target; // target address
1819 uint32_t imm32; // PC-relative offset to branch forward
1820 bool nonzero;
1821 switch (encoding) {
1822 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001823 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001824 nonzero = BitIsSet(opcode, 11);
1825 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001826 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001827 break;
1828 default:
1829 return false;
1830 }
1831 if (nonzero ^ (reg_val == 0))
1832 if (!BranchWritePC(context, target))
1833 return false;
1834
1835 return true;
1836}
1837
Johnny Chen60299ec2011-02-17 19:34:27 +00001838// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1839// A base register provides a pointer to the table, and a second register supplies an index into the table.
1840// The branch length is twice the value of the byte returned from the table.
1841//
1842// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1843// A base register provides a pointer to the table, and a second register supplies an index into the table.
1844// The branch length is twice the value of the halfword returned from the table.
1845// TBB, TBH
1846bool
1847EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1848{
1849#if 0
1850 // ARM pseudo code...
1851 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1852 if is_tbh then
1853 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1854 else
1855 halfwords = UInt(MemU[R[n]+R[m], 1]);
1856 BranchWritePC(PC + 2*halfwords);
1857#endif
1858
1859 bool success = false;
1860 const uint32_t opcode = OpcodeAsUnsigned (&success);
1861 if (!success)
1862 return false;
1863
1864 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1865 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1866 bool is_tbh; // true if table branch halfword
1867 switch (encoding) {
1868 case eEncodingT1:
1869 Rn = Bits32(opcode, 19, 16);
1870 Rm = Bits32(opcode, 3, 0);
1871 is_tbh = BitIsSet(opcode, 4);
1872 if (Rn == 13 || BadReg(Rm))
1873 return false;
1874 if (InITBlock() && !LastInITBlock())
1875 return false;
1876 break;
1877 default:
1878 return false;
1879 }
1880
1881 // Read the address of the table from the operand register Rn.
1882 // The PC can be used, in which case the table immediately follows this instruction.
1883 uint32_t base =
1884 Rn == 15 ? (ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success) + 4)
1885 : ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1886 if (!success)
1887 return false;
1888
1889 // the table index
1890 uint32_t index = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1891 if (!success)
1892 return false;
1893
1894 // the offsetted table address
1895 addr_t addr = base + (is_tbh ? index*2 : index);
1896
1897 // PC-relative offset to branch forward
1898 EmulateInstruction::Context context;
1899 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001900 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001901 if (!success)
1902 return false;
1903
1904 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1905 if (!success)
1906 return false;
1907
1908 // target address
1909 addr_t target = pc + 4 + offset;
1910 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1911 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
1912
1913 if (!BranchWritePC(context, target))
1914 return false;
1915
1916 return true;
1917}
1918
Johnny Chen8fa20592011-02-18 01:22:22 +00001919// This instruction adds an immediate value to a register value, and writes the result to the destination
1920// register. It can optionally update the condition flags based on the result.
1921bool
1922EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
1923{
1924#if 0
1925 // ARM pseudo code...
1926 if ConditionPassed() then
1927 EncodingSpecificOperations();
1928 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1929 if d == 15 then
1930 ALUWritePC(result); // setflags is always FALSE here
1931 else
1932 R[d] = result;
1933 if setflags then
1934 APSR.N = result<31>;
1935 APSR.Z = IsZeroBit(result);
1936 APSR.C = carry;
1937 APSR.V = overflow;
1938#endif
1939
1940 bool success = false;
1941 const uint32_t opcode = OpcodeAsUnsigned (&success);
1942 if (!success)
1943 return false;
1944
1945 if (ConditionPassed())
1946 {
1947 uint32_t Rd, Rn;
1948 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
1949 bool setflags;
1950 switch (encoding)
1951 {
1952 case eEncodingA1:
1953 Rd = Bits32(opcode, 15, 12);
1954 Rn = Bits32(opcode, 19, 16);
1955 setflags = BitIsSet(opcode, 20);
1956 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1957 break;
1958 default:
1959 return false;
1960 }
1961
1962 int32_t val1;
1963 // Read the first operand.
1964 if (Rn == 15)
1965 {
1966 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1967 if (encoding == eEncodingT1 || encoding == eEncodingT2)
1968 val1 += 4;
1969 else
1970 val1 += 8;
1971 }
1972 else
1973 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1974 if (!success)
1975 return false;
1976
1977 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1978
1979 EmulateInstruction::Context context;
1980 context.type = EmulateInstruction::eContextImmediate;
1981 context.SetNoArgs ();
1982
1983 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1984 return false;
1985 }
1986 return true;
1987}
1988
Johnny Chend761dcf2011-02-17 22:03:29 +00001989// This instruction adds a register value and an optionally-shifted register value, and writes the result
1990// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001991bool
Johnny Chen9f687722011-02-18 00:02:28 +00001992EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001993{
1994#if 0
1995 // ARM pseudo code...
1996 if ConditionPassed() then
1997 EncodingSpecificOperations();
1998 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1999 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2000 if d == 15 then
2001 ALUWritePC(result); // setflags is always FALSE here
2002 else
2003 R[d] = result;
2004 if setflags then
2005 APSR.N = result<31>;
2006 APSR.Z = IsZeroBit(result);
2007 APSR.C = carry;
2008 APSR.V = overflow;
2009#endif
2010
2011 bool success = false;
2012 const uint32_t opcode = OpcodeAsUnsigned (&success);
2013 if (!success)
2014 return false;
2015
2016 if (ConditionPassed())
2017 {
2018 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002019 ARM_ShifterType shift_t;
2020 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002021 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002022 switch (encoding)
2023 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002024 case eEncodingT1:
2025 Rd = Bits32(opcode, 2, 0);
2026 Rn = Bits32(opcode, 5, 3);
2027 Rm = Bits32(opcode, 8, 6);
2028 setflags = !InITBlock();
2029 shift_t = SRType_LSL;
2030 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002031 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002032 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002033 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002034 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002035 shift_t = SRType_LSL;
2036 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002037 if (Rn == 15 && Rm == 15)
2038 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002039 if (Rd == 15 && InITBlock() && !LastInITBlock())
2040 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002041 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002042 case eEncodingA1:
2043 Rd = Bits32(opcode, 15, 12);
2044 Rn = Bits32(opcode, 19, 16);
2045 Rm = Bits32(opcode, 3, 0);
2046 setflags = BitIsSet(opcode, 20);
2047 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2048 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002049 default:
2050 return false;
2051 }
2052
Johnny Chen8fa20592011-02-18 01:22:22 +00002053 int32_t val1, val2;
Johnny Chen26863dc2011-02-09 23:43:29 +00002054 // Read the first operand.
2055 if (Rn == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00002056 {
Johnny Chen26863dc2011-02-09 23:43:29 +00002057 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00002058 if (encoding == eEncodingT1 || encoding == eEncodingT2)
2059 val1 += 4;
2060 else
2061 val1 += 8;
2062 }
Johnny Chen26863dc2011-02-09 23:43:29 +00002063 else
2064 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2065 if (!success)
2066 return false;
2067
2068 // Read the second operand.
2069 if (Rm == 15)
Johnny Chend761dcf2011-02-17 22:03:29 +00002070 {
Johnny Chen26863dc2011-02-09 23:43:29 +00002071 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chend761dcf2011-02-17 22:03:29 +00002072 if (encoding == eEncodingT1 || encoding == eEncodingT2)
2073 val1 += 4;
2074 else
2075 val1 += 8;
2076 }
Johnny Chen26863dc2011-02-09 23:43:29 +00002077 else
2078 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2079 if (!success)
2080 return false;
2081
Johnny Chene97c0d52011-02-18 19:32:20 +00002082 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002083 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002084
2085 EmulateInstruction::Context context;
2086 context.type = EmulateInstruction::eContextImmediate;
2087 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002088
Johnny Chen10530c22011-02-17 22:37:12 +00002089 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002090 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002091 }
2092 return true;
2093}
2094
Johnny Chene4a4d302011-02-11 21:53:58 +00002095// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002096bool
Johnny Chen9f687722011-02-18 00:02:28 +00002097EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002098{
2099#if 0
2100 // ARM pseudo code...
2101 if ConditionPassed() then
2102 EncodingSpecificOperations();
2103 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2104 APSR.N = result<31>;
2105 APSR.Z = IsZeroBit(result);
2106 APSR.C = carry;
2107 APSR.V = overflow;
2108#endif
2109
2110 bool success = false;
2111 const uint32_t opcode = OpcodeAsUnsigned (&success);
2112 if (!success)
2113 return false;
2114
2115 uint32_t Rn; // the first operand
2116 uint32_t imm32; // the immediate value to be compared with
2117 switch (encoding) {
2118 case eEncodingT1:
2119 Rn = Bits32(opcode, 10, 8);
2120 imm32 = Bits32(opcode, 7, 0);
2121 break;
2122 default:
2123 return false;
2124 }
2125 // Read the register value from the operand register Rn.
2126 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2127 if (!success)
2128 return false;
2129
Johnny Chen10530c22011-02-17 22:37:12 +00002130 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2131
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002132 EmulateInstruction::Context context;
2133 context.type = EmulateInstruction::eContextImmediate;
2134 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002135 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2136 return false;
2137
Johnny Chend4dc4442011-02-11 02:02:56 +00002138 return true;
2139}
2140
Johnny Chene4a4d302011-02-11 21:53:58 +00002141// CMP (register)
2142bool
Johnny Chen9f687722011-02-18 00:02:28 +00002143EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002144{
2145#if 0
2146 // ARM pseudo code...
2147 if ConditionPassed() then
2148 EncodingSpecificOperations();
2149 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2150 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2151 APSR.N = result<31>;
2152 APSR.Z = IsZeroBit(result);
2153 APSR.C = carry;
2154 APSR.V = overflow;
2155#endif
2156
2157 bool success = false;
2158 const uint32_t opcode = OpcodeAsUnsigned (&success);
2159 if (!success)
2160 return false;
2161
2162 uint32_t Rn; // the first operand
2163 uint32_t Rm; // the second operand
2164 switch (encoding) {
2165 case eEncodingT1:
2166 Rn = Bits32(opcode, 2, 0);
2167 Rm = Bits32(opcode, 5, 3);
2168 break;
2169 case eEncodingT2:
2170 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2171 Rm = Bits32(opcode, 6, 3);
2172 if (Rn < 8 && Rm < 8)
2173 return false;
2174 if (Rn == 15 || Rm == 15)
2175 return false;
2176 break;
2177 default:
2178 return false;
2179 }
2180 // Read the register value from register Rn.
2181 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2182 if (!success)
2183 return false;
2184 // Read the register value from register Rm.
2185 // The register value is not being shifted since we don't handle ARM for now.
2186 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2187 if (!success)
2188 return false;
2189
Johnny Chen10530c22011-02-17 22:37:12 +00002190 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2191
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002192 EmulateInstruction::Context context;
2193 context.type = EmulateInstruction::eContextImmediate;
2194 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002195 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2196 return false;
2197
Johnny Chene4a4d302011-02-11 21:53:58 +00002198 return true;
2199}
2200
Johnny Chen82f16aa2011-02-15 20:10:55 +00002201// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2202// shifting in copies of its sign bit, and writes the result to the destination register. It can
2203// optionally update the condition flags based on the result.
2204bool
2205EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2206{
2207#if 0
2208 // ARM pseudo code...
2209 if ConditionPassed() then
2210 EncodingSpecificOperations();
2211 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2212 if d == 15 then // Can only occur for ARM encoding
2213 ALUWritePC(result); // setflags is always FALSE here
2214 else
2215 R[d] = result;
2216 if setflags then
2217 APSR.N = result<31>;
2218 APSR.Z = IsZeroBit(result);
2219 APSR.C = carry;
2220 // APSR.V unchanged
2221#endif
2222
Johnny Chen41a0a152011-02-16 01:27:54 +00002223 return EmulateShiftImm(encoding, SRType_ASR);
2224}
2225
2226// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2227// shifting in copies of its sign bit, and writes the result to the destination register.
2228// The variable number of bits is read from the bottom byte of a register. It can optionally update
2229// the condition flags based on the result.
2230bool
2231EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2232{
2233#if 0
2234 // ARM pseudo code...
2235 if ConditionPassed() then
2236 EncodingSpecificOperations();
2237 shift_n = UInt(R[m]<7:0>);
2238 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2239 R[d] = result;
2240 if setflags then
2241 APSR.N = result<31>;
2242 APSR.Z = IsZeroBit(result);
2243 APSR.C = carry;
2244 // APSR.V unchanged
2245#endif
2246
2247 return EmulateShiftReg(encoding, SRType_ASR);
2248}
2249
2250// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2251// shifting in zeros, and writes the result to the destination register. It can optionally
2252// update the condition flags based on the result.
2253bool
2254EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2255{
2256#if 0
2257 // ARM pseudo code...
2258 if ConditionPassed() then
2259 EncodingSpecificOperations();
2260 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2261 if d == 15 then // Can only occur for ARM encoding
2262 ALUWritePC(result); // setflags is always FALSE here
2263 else
2264 R[d] = result;
2265 if setflags then
2266 APSR.N = result<31>;
2267 APSR.Z = IsZeroBit(result);
2268 APSR.C = carry;
2269 // APSR.V unchanged
2270#endif
2271
2272 return EmulateShiftImm(encoding, SRType_LSL);
2273}
2274
2275// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2276// shifting in zeros, and writes the result to the destination register. The variable number
2277// of bits is read from the bottom byte of a register. It can optionally update the condition
2278// flags based on the result.
2279bool
2280EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2281{
2282#if 0
2283 // ARM pseudo code...
2284 if ConditionPassed() then
2285 EncodingSpecificOperations();
2286 shift_n = UInt(R[m]<7:0>);
2287 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2288 R[d] = result;
2289 if setflags then
2290 APSR.N = result<31>;
2291 APSR.Z = IsZeroBit(result);
2292 APSR.C = carry;
2293 // APSR.V unchanged
2294#endif
2295
2296 return EmulateShiftReg(encoding, SRType_LSL);
2297}
2298
2299// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2300// shifting in zeros, and writes the result to the destination register. It can optionally
2301// update the condition flags based on the result.
2302bool
2303EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2304{
2305#if 0
2306 // ARM pseudo code...
2307 if ConditionPassed() then
2308 EncodingSpecificOperations();
2309 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2310 if d == 15 then // Can only occur for ARM encoding
2311 ALUWritePC(result); // setflags is always FALSE here
2312 else
2313 R[d] = result;
2314 if setflags then
2315 APSR.N = result<31>;
2316 APSR.Z = IsZeroBit(result);
2317 APSR.C = carry;
2318 // APSR.V unchanged
2319#endif
2320
2321 return EmulateShiftImm(encoding, SRType_LSR);
2322}
2323
2324// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2325// shifting in zeros, and writes the result to the destination register. The variable number
2326// of bits is read from the bottom byte of a register. It can optionally update the condition
2327// flags based on the result.
2328bool
2329EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2330{
2331#if 0
2332 // ARM pseudo code...
2333 if ConditionPassed() then
2334 EncodingSpecificOperations();
2335 shift_n = UInt(R[m]<7:0>);
2336 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2337 R[d] = result;
2338 if setflags then
2339 APSR.N = result<31>;
2340 APSR.Z = IsZeroBit(result);
2341 APSR.C = carry;
2342 // APSR.V unchanged
2343#endif
2344
2345 return EmulateShiftReg(encoding, SRType_LSR);
2346}
2347
Johnny Cheneeab4852011-02-16 22:14:44 +00002348// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2349// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2350// It can optionally update the condition flags based on the result.
2351bool
2352EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2353{
2354#if 0
2355 // ARM pseudo code...
2356 if ConditionPassed() then
2357 EncodingSpecificOperations();
2358 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2359 if d == 15 then // Can only occur for ARM encoding
2360 ALUWritePC(result); // setflags is always FALSE here
2361 else
2362 R[d] = result;
2363 if setflags then
2364 APSR.N = result<31>;
2365 APSR.Z = IsZeroBit(result);
2366 APSR.C = carry;
2367 // APSR.V unchanged
2368#endif
2369
2370 return EmulateShiftImm(encoding, SRType_ROR);
2371}
2372
2373// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2374// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2375// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2376// flags based on the result.
2377bool
2378EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2379{
2380#if 0
2381 // ARM pseudo code...
2382 if ConditionPassed() then
2383 EncodingSpecificOperations();
2384 shift_n = UInt(R[m]<7:0>);
2385 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2386 R[d] = result;
2387 if setflags then
2388 APSR.N = result<31>;
2389 APSR.Z = IsZeroBit(result);
2390 APSR.C = carry;
2391 // APSR.V unchanged
2392#endif
2393
2394 return EmulateShiftReg(encoding, SRType_ROR);
2395}
2396
2397// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2398// with the carry flag shifted into bit [31].
2399//
2400// RRX can optionally update the condition flags based on the result.
2401// In that case, bit [0] is shifted into the carry flag.
2402bool
2403EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2404{
2405#if 0
2406 // ARM pseudo code...
2407 if ConditionPassed() then
2408 EncodingSpecificOperations();
2409 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2410 if d == 15 then // Can only occur for ARM encoding
2411 ALUWritePC(result); // setflags is always FALSE here
2412 else
2413 R[d] = result;
2414 if setflags then
2415 APSR.N = result<31>;
2416 APSR.Z = IsZeroBit(result);
2417 APSR.C = carry;
2418 // APSR.V unchanged
2419#endif
2420
2421 return EmulateShiftImm(encoding, SRType_RRX);
2422}
2423
Johnny Chen41a0a152011-02-16 01:27:54 +00002424bool
2425EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2426{
2427 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2428
Johnny Chen82f16aa2011-02-15 20:10:55 +00002429 bool success = false;
2430 const uint32_t opcode = OpcodeAsUnsigned (&success);
2431 if (!success)
2432 return false;
2433
2434 if (ConditionPassed())
2435 {
Johnny Chene7f89532011-02-15 23:22:46 +00002436 uint32_t Rd; // the destination register
2437 uint32_t Rm; // the first operand register
2438 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002439 uint32_t carry; // the carry bit after the shift operation
2440 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002441
2442 // Special case handling!
2443 // A8.6.139 ROR (immediate) -- Encoding T1
2444 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2445 {
2446 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2447 // have the same decoding of bit fields as the other Thumb2 shift operations.
2448 encoding = eEncodingT2;
2449 }
2450
Johnny Chen82f16aa2011-02-15 20:10:55 +00002451 switch (encoding) {
2452 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002453 // Due to the above special case handling!
2454 assert(shift_type != SRType_ROR);
2455
Johnny Chen82f16aa2011-02-15 20:10:55 +00002456 Rd = Bits32(opcode, 2, 0);
2457 Rm = Bits32(opcode, 5, 3);
2458 setflags = !InITBlock();
2459 imm5 = Bits32(opcode, 10, 6);
2460 break;
2461 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002462 // A8.6.141 RRX
2463 assert(shift_type != SRType_RRX);
2464
Johnny Chen82f16aa2011-02-15 20:10:55 +00002465 Rd = Bits32(opcode, 11, 8);
2466 Rm = Bits32(opcode, 3, 0);
2467 setflags = BitIsSet(opcode, 20);
2468 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2469 if (BadReg(Rd) || BadReg(Rm))
2470 return false;
2471 break;
2472 case eEncodingA1:
2473 Rd = Bits32(opcode, 15, 12);
2474 Rm = Bits32(opcode, 3, 0);
2475 setflags = BitIsSet(opcode, 20);
2476 imm5 = Bits32(opcode, 11, 7);
2477 break;
2478 default:
2479 return false;
2480 }
2481
Johnny Cheneeab4852011-02-16 22:14:44 +00002482 // A8.6.139 ROR (immediate)
2483 if (shift_type == SRType_ROR && imm5 == 0)
2484 shift_type = SRType_RRX;
2485
Johnny Chen82f16aa2011-02-15 20:10:55 +00002486 // Get the first operand.
2487 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2488 if (!success)
2489 return false;
2490
Johnny Cheneeab4852011-02-16 22:14:44 +00002491 // Decode the shift amount if not RRX.
2492 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002493
Johnny Chene97c0d52011-02-18 19:32:20 +00002494 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002495
2496 // The context specifies that an immediate is to be moved into Rd.
2497 EmulateInstruction::Context context;
2498 context.type = EmulateInstruction::eContextImmediate;
2499 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002500
Johnny Chen10530c22011-02-17 22:37:12 +00002501 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002502 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002503 }
2504 return true;
2505}
2506
Johnny Chene7f89532011-02-15 23:22:46 +00002507bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002508EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002509{
Johnny Chen41a0a152011-02-16 01:27:54 +00002510 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002511
2512 bool success = false;
2513 const uint32_t opcode = OpcodeAsUnsigned (&success);
2514 if (!success)
2515 return false;
2516
2517 if (ConditionPassed())
2518 {
2519 uint32_t Rd; // the destination register
2520 uint32_t Rn; // the first operand register
2521 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2522 uint32_t carry; // the carry bit after the shift operation
2523 bool setflags;
2524 switch (encoding) {
2525 case eEncodingT1:
2526 Rd = Bits32(opcode, 2, 0);
2527 Rn = Rd;
2528 Rm = Bits32(opcode, 5, 3);
2529 setflags = !InITBlock();
2530 break;
2531 case eEncodingT2:
2532 Rd = Bits32(opcode, 11, 8);
2533 Rn = Bits32(opcode, 19, 16);
2534 Rm = Bits32(opcode, 3, 0);
2535 setflags = BitIsSet(opcode, 20);
2536 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2537 return false;
2538 break;
2539 case eEncodingA1:
2540 Rd = Bits32(opcode, 15, 12);
2541 Rn = Bits32(opcode, 3, 0);
2542 Rm = Bits32(opcode, 11, 8);
2543 setflags = BitIsSet(opcode, 20);
2544 if (Rd == 15 || Rn == 15 || Rm == 15)
2545 return false;
2546 break;
2547 default:
2548 return false;
2549 }
2550
2551 // Get the first operand.
2552 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2553 if (!success)
2554 return false;
2555 // Get the Rm register content.
2556 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2557 if (!success)
2558 return false;
2559
2560 // Get the shift amount.
2561 uint32_t amt = Bits32(val, 7, 0);
2562
Johnny Chene97c0d52011-02-18 19:32:20 +00002563 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002564
2565 // The context specifies that an immediate is to be moved into Rd.
2566 EmulateInstruction::Context context;
2567 context.type = EmulateInstruction::eContextImmediate;
2568 context.SetNoArgs ();
2569
Johnny Chen10530c22011-02-17 22:37:12 +00002570 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002571 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002572 }
2573 return true;
2574}
2575
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002576// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002577// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002578// can be written back to the base register.
2579bool
2580EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2581{
2582#if 0
2583 // ARM pseudo code...
2584 if ConditionPassed()
2585 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2586 address = R[n];
2587
2588 for i = 0 to 14
2589 if registers<i> == '1' then
2590 R[i] = MemA[address, 4]; address = address + 4;
2591 if registers<15> == '1' then
2592 LoadWritePC (MemA[address, 4]);
2593
2594 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2595 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2596
2597#endif
2598
2599 bool success = false;
2600 const uint32_t opcode = OpcodeAsUnsigned (&success);
2601 if (!success)
2602 return false;
2603
2604 if (ConditionPassed())
2605 {
2606 uint32_t n;
2607 uint32_t registers = 0;
2608 bool wback;
2609 const uint32_t addr_byte_size = GetAddressByteSize();
2610 switch (encoding)
2611 {
2612 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002613 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002614 n = Bits32 (opcode, 10, 8);
2615 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002616 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002617 wback = BitIsClear (registers, n);
2618 // if BitCount(registers) < 1 then UNPREDICTABLE;
2619 if (BitCount(registers) < 1)
2620 return false;
2621 break;
2622 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002623 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2624 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002625 n = Bits32 (opcode, 19, 16);
2626 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002627 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002628 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002629
2630 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002631 if ((n == 15)
2632 || (BitCount (registers) < 2)
2633 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2634 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002635
2636 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002637 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002638 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002639
2640 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002641 if (wback
2642 && BitIsSet (registers, n))
2643 return false;
2644 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002645
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002646 case eEncodingA1:
2647 n = Bits32 (opcode, 19, 16);
2648 registers = Bits32 (opcode, 15, 0);
2649 wback = BitIsSet (opcode, 21);
2650 if ((n == 15)
2651 || (BitCount (registers) < 1))
2652 return false;
2653 break;
2654 default:
2655 return false;
2656 }
2657
2658 int32_t offset = 0;
2659 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2660 if (!success)
2661 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002662
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002663 EmulateInstruction::Context context;
2664 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2665 Register dwarf_reg;
2666 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2667 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002668
2669 for (int i = 0; i < 14; ++i)
2670 {
2671 if (BitIsSet (registers, i))
2672 {
Caroline Tice85aab332011-02-08 23:56:10 +00002673 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002674 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002675 if (wback && (n == 13)) // Pop Instruction
2676 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2677
2678 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002679 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002680 if (!success)
2681 return false;
2682
2683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2684 return false;
2685
2686 offset += addr_byte_size;
2687 }
2688 }
2689
2690 if (BitIsSet (registers, 15))
2691 {
2692 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002693 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002694 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002695 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002696 if (!success)
2697 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002698 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002699 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002700 return false;
2701 }
2702
2703 if (wback && BitIsClear (registers, n))
2704 {
Caroline Ticefa172202011-02-11 22:49:54 +00002705 // R[n] = R[n] + 4 * BitCount (registers)
2706 int32_t offset = addr_byte_size * BitCount (registers);
2707 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002708 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002709
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002710 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2711 return false;
2712 }
2713 if (wback && BitIsSet (registers, n))
2714 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002715 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002716 }
2717 return true;
2718}
Caroline Tice713c2662011-02-11 17:59:55 +00002719
2720// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2721// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2722// can optionally be written back tot he base registers.
2723bool
2724EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2725{
2726#if 0
2727 // ARM pseudo code...
2728 if ConditionPassed() then
2729 EncodingSpecificOperations();
2730 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002731
Caroline Tice713c2662011-02-11 17:59:55 +00002732 for i = 0 to 14
2733 if registers<i> == ’1’ then
2734 R[i] = MemA[address,4]; address = address + 4;
2735
2736 if registers<15> == ’1’ then
2737 LoadWritePC(MemA[address,4]);
2738
2739 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2740 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2741#endif
2742
2743 bool success = false;
2744 const uint32_t opcode = OpcodeAsUnsigned (&success);
2745 if (!success)
2746 return false;
2747
2748 if (ConditionPassed())
2749 {
2750 uint32_t n;
2751 uint32_t registers = 0;
2752 bool wback;
2753 const uint32_t addr_byte_size = GetAddressByteSize();
2754
2755 // EncodingSpecificOperations();
2756 switch (encoding)
2757 {
2758 case eEncodingA1:
2759 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2760 n = Bits32 (opcode, 19, 16);
2761 registers = Bits32 (opcode, 15, 0);
2762 wback = BitIsSet (opcode, 21);
2763
2764 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2765 if ((n == 15) || (BitCount (registers) < 1))
2766 return false;
2767
2768 break;
2769
2770 default:
2771 return false;
2772 }
2773 // address = R[n] - 4*BitCount(registers) + 4;
2774
2775 int32_t offset = 0;
2776 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2777
2778 if (!success)
2779 return false;
2780
2781 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2782
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002783 EmulateInstruction::Context context;
2784 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2785 Register dwarf_reg;
2786 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2787 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002788
2789 // for i = 0 to 14
2790 for (int i = 0; i < 14; ++i)
2791 {
2792 // if registers<i> == ’1’ then
2793 if (BitIsSet (registers, i))
2794 {
2795 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002796 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002797 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002798 if (!success)
2799 return false;
2800 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2801 return false;
2802 offset += addr_byte_size;
2803 }
2804 }
2805
2806 // if registers<15> == ’1’ then
2807 // LoadWritePC(MemA[address,4]);
2808 if (BitIsSet (registers, 15))
2809 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002810 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002811 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002812 if (!success)
2813 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002814 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002815 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002816 return false;
2817 }
2818
2819 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2820 if (wback && BitIsClear (registers, n))
2821 {
Caroline Tice713c2662011-02-11 17:59:55 +00002822 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2823 if (!success)
2824 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002825
2826 offset = (addr_byte_size * BitCount (registers)) * -1;
2827 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002828 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002829 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002830 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2831 return false;
2832 }
2833
2834 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2835 if (wback && BitIsSet (registers, n))
2836 return WriteBits32Unknown (n);
2837 }
2838 return true;
2839}
2840
2841// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2842// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2843// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002844bool
2845EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2846{
2847#if 0
2848 // ARM pseudo code...
2849 if ConditionPassed() then
2850 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2851 address = R[n] - 4*BitCount(registers);
2852
2853 for i = 0 to 14
2854 if registers<i> == ’1’ then
2855 R[i] = MemA[address,4]; address = address + 4;
2856 if registers<15> == ’1’ then
2857 LoadWritePC(MemA[address,4]);
2858
2859 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2860 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2861#endif
2862
2863 bool success = false;
2864 const uint32_t opcode = OpcodeAsUnsigned (&success);
2865 if (!success)
2866 return false;
2867
2868 if (ConditionPassed())
2869 {
2870 uint32_t n;
2871 uint32_t registers = 0;
2872 bool wback;
2873 const uint32_t addr_byte_size = GetAddressByteSize();
2874 switch (encoding)
2875 {
2876 case eEncodingT1:
2877 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2878 n = Bits32 (opcode, 19, 16);
2879 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002880 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002881 wback = BitIsSet (opcode, 21);
2882
2883 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2884 if ((n == 15)
2885 || (BitCount (registers) < 2)
2886 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2887 return false;
2888
2889 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002890 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002891 return false;
2892
2893 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2894 if (wback && BitIsSet (registers, n))
2895 return false;
2896
2897 break;
2898
2899 case eEncodingA1:
2900 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2901 n = Bits32 (opcode, 19, 16);
2902 registers = Bits32 (opcode, 15, 0);
2903 wback = BitIsSet (opcode, 21);
2904
2905 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2906 if ((n == 15) || (BitCount (registers) < 1))
2907 return false;
2908
2909 break;
2910
2911 default:
2912 return false;
2913 }
2914
Caroline Tice713c2662011-02-11 17:59:55 +00002915 // address = R[n] - 4*BitCount(registers);
2916
Caroline Tice0b29e242011-02-08 23:16:02 +00002917 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002918 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2919
2920 if (!success)
2921 return false;
2922
2923 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002924 EmulateInstruction::Context context;
2925 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2926 Register dwarf_reg;
2927 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2928 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002929
2930 for (int i = 0; i < 14; ++i)
2931 {
2932 if (BitIsSet (registers, i))
2933 {
2934 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002935 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002936 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002937 if (!success)
2938 return false;
2939
2940 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2941 return false;
2942
2943 offset += addr_byte_size;
2944 }
2945 }
2946
2947 // if registers<15> == ’1’ then
2948 // LoadWritePC(MemA[address,4]);
2949 if (BitIsSet (registers, 15))
2950 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002951 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002952 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002953 if (!success)
2954 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002955 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002956 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002957 return false;
2958 }
2959
2960 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2961 if (wback && BitIsClear (registers, n))
2962 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002963 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2964 if (!success)
2965 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002966
2967 offset = (addr_byte_size * BitCount (registers)) * -1;
2968 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002969 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002970 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002971 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2972 return false;
2973 }
2974
2975 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2976 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002977 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002978 }
2979 return true;
2980}
Caroline Tice85aab332011-02-08 23:56:10 +00002981
Caroline Tice713c2662011-02-11 17:59:55 +00002982// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2983// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2984// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002985bool
2986EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2987{
2988#if 0
2989 if ConditionPassed() then
2990 EncodingSpecificOperations();
2991 address = R[n] + 4;
2992
2993 for i = 0 to 14
2994 if registers<i> == ’1’ then
2995 R[i] = MemA[address,4]; address = address + 4;
2996 if registers<15> == ’1’ then
2997 LoadWritePC(MemA[address,4]);
2998
2999 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3000 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3001#endif
3002
3003 bool success = false;
3004 const uint32_t opcode = OpcodeAsUnsigned (&success);
3005 if (!success)
3006 return false;
3007
3008 if (ConditionPassed())
3009 {
3010 uint32_t n;
3011 uint32_t registers = 0;
3012 bool wback;
3013 const uint32_t addr_byte_size = GetAddressByteSize();
3014 switch (encoding)
3015 {
3016 case eEncodingA1:
3017 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3018 n = Bits32 (opcode, 19, 16);
3019 registers = Bits32 (opcode, 15, 0);
3020 wback = BitIsSet (opcode, 21);
3021
3022 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3023 if ((n == 15) || (BitCount (registers) < 1))
3024 return false;
3025
3026 break;
3027 default:
3028 return false;
3029 }
3030 // address = R[n] + 4;
3031
3032 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003033 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3034
3035 if (!success)
3036 return false;
3037
3038 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003039
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003040 EmulateInstruction::Context context;
3041 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3042 Register dwarf_reg;
3043 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3044 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003045
3046 for (int i = 0; i < 14; ++i)
3047 {
3048 if (BitIsSet (registers, i))
3049 {
3050 // R[i] = MemA[address,4]; address = address + 4;
3051
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003052 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003053 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003054 if (!success)
3055 return false;
3056
3057 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3058 return false;
3059
3060 offset += addr_byte_size;
3061 }
3062 }
3063
3064 // if registers<15> == ’1’ then
3065 // LoadWritePC(MemA[address,4]);
3066 if (BitIsSet (registers, 15))
3067 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003068 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003069 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003070 if (!success)
3071 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003072 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003073 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003074 return false;
3075 }
3076
3077 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3078 if (wback && BitIsClear (registers, n))
3079 {
Caroline Tice85aab332011-02-08 23:56:10 +00003080 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3081 if (!success)
3082 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003083
3084 offset = addr_byte_size * BitCount (registers);
3085 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003086 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003087 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003088 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3089 return false;
3090 }
3091
3092 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3093 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003094 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003095 }
3096 return true;
3097}
Caroline Tice0b29e242011-02-08 23:16:02 +00003098
Johnny Chenef21b592011-02-10 01:52:38 +00003099// Load Register (immediate) calculates an address from a base register value and
3100// an immediate offset, loads a word from memory, and writes to a register.
3101// LDR (immediate, Thumb)
3102bool
3103EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3104{
3105#if 0
3106 // ARM pseudo code...
3107 if (ConditionPassed())
3108 {
3109 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3110 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3111 address = if index then offset_addr else R[n];
3112 data = MemU[address,4];
3113 if wback then R[n] = offset_addr;
3114 if t == 15 then
3115 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3116 elsif UnalignedSupport() || address<1:0> = '00' then
3117 R[t] = data;
3118 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3119 }
3120#endif
3121
3122 bool success = false;
3123 const uint32_t opcode = OpcodeAsUnsigned (&success);
3124 if (!success)
3125 return false;
3126
3127 if (ConditionPassed())
3128 {
3129 uint32_t Rt; // the destination register
3130 uint32_t Rn; // the base register
3131 uint32_t imm32; // the immediate offset used to form the address
3132 addr_t offset_addr; // the offset address
3133 addr_t address; // the calculated address
3134 uint32_t data; // the literal data value from memory load
3135 bool add, index, wback;
3136 switch (encoding) {
3137 case eEncodingT1:
3138 Rt = Bits32(opcode, 5, 3);
3139 Rn = Bits32(opcode, 2, 0);
3140 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3141 // index = TRUE; add = TRUE; wback = FALSE
3142 add = true;
3143 index = true;
3144 wback = false;
3145 break;
3146 default:
3147 return false;
3148 }
3149 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3150 if (!success)
3151 return false;
3152 if (add)
3153 offset_addr = base + imm32;
3154 else
3155 offset_addr = base - imm32;
3156
3157 address = (index ? offset_addr : base);
3158
3159 if (wback)
3160 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003161 EmulateInstruction::Context ctx;
3162 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3163 Register dwarf_reg;
3164 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3165 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3166
Johnny Chenef21b592011-02-10 01:52:38 +00003167 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3168 return false;
3169 }
3170
3171 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003172 EmulateInstruction::Context context;
3173 context.type = EmulateInstruction::eContextImmediate;
3174 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003175
3176 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003177 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003178 if (!success)
3179 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003180
3181 if (Rt == 15)
3182 {
3183 if (Bits32(address, 1, 0) == 0)
3184 {
Johnny Chen668b4512011-02-15 21:08:58 +00003185 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003186 return false;
3187 }
3188 else
3189 return false;
3190 }
3191 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3192 {
3193 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3194 return false;
3195 }
3196 else
3197 return false;
3198 }
3199 return true;
3200}
3201
Caroline Ticeaf556562011-02-15 18:42:15 +00003202// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3203// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3204// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003205bool
3206EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3207{
3208#if 0
3209 if ConditionPassed() then
3210 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3211 address = R[n];
3212
3213 for i = 0 to 14
3214 if registers<i> == ’1’ then
3215 if i == n && wback && i != LowestSetBit(registers) then
3216 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3217 else
3218 MemA[address,4] = R[i];
3219 address = address + 4;
3220
3221 if registers<15> == ’1’ then // Only possible for encoding A1
3222 MemA[address,4] = PCStoreValue();
3223 if wback then R[n] = R[n] + 4*BitCount(registers);
3224#endif
3225
3226 bool success = false;
3227 const uint32_t opcode = OpcodeAsUnsigned (&success);
3228 if (!success)
3229 return false;
3230
3231 if (ConditionPassed ())
3232 {
3233 uint32_t n;
3234 uint32_t registers = 0;
3235 bool wback;
3236 const uint32_t addr_byte_size = GetAddressByteSize();
3237
3238 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3239 switch (encoding)
3240 {
3241 case eEncodingT1:
3242 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3243 n = Bits32 (opcode, 10, 8);
3244 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003245 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003246 wback = true;
3247
3248 // if BitCount(registers) < 1 then UNPREDICTABLE;
3249 if (BitCount (registers) < 1)
3250 return false;
3251
3252 break;
3253
3254 case eEncodingT2:
3255 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3256 n = Bits32 (opcode, 19, 16);
3257 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003258 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003259 wback = BitIsSet (opcode, 21);
3260
3261 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3262 if ((n == 15) || (BitCount (registers) < 2))
3263 return false;
3264
3265 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3266 if (wback && BitIsSet (registers, n))
3267 return false;
3268
3269 break;
3270
3271 case eEncodingA1:
3272 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3273 n = Bits32 (opcode, 19, 16);
3274 registers = Bits32 (opcode, 15, 0);
3275 wback = BitIsSet (opcode, 21);
3276
3277 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3278 if ((n == 15) || (BitCount (registers) < 1))
3279 return false;
3280
3281 break;
3282
3283 default:
3284 return false;
3285 }
3286
3287 // address = R[n];
3288 int32_t offset = 0;
3289 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3290 if (!success)
3291 return false;
3292
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003293 EmulateInstruction::Context context;
3294 context.type = EmulateInstruction::eContextRegisterStore;
3295 Register base_reg;
3296 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003297
3298 // for i = 0 to 14
3299 for (int i = 0; i < 14; ++i)
3300 {
3301 int lowest_set_bit = 14;
3302 // if registers<i> == ’1’ then
3303 if (BitIsSet (registers, i))
3304 {
3305 if (i < lowest_set_bit)
3306 lowest_set_bit = i;
3307 // if i == n && wback && i != LowestSetBit(registers) then
3308 if ((i == n) && wback && (i != lowest_set_bit))
3309 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3310 WriteBits32UnknownToMemory (address + offset);
3311 else
3312 {
3313 // MemA[address,4] = R[i];
3314 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3315 if (!success)
3316 return false;
3317
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003318 Register data_reg;
3319 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3320 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003321 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003322 return false;
3323 }
3324
3325 // address = address + 4;
3326 offset += addr_byte_size;
3327 }
3328 }
3329
3330 // if registers<15> == ’1’ then // Only possible for encoding A1
3331 // MemA[address,4] = PCStoreValue();
3332 if (BitIsSet (registers, 15))
3333 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003334 Register pc_reg;
3335 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3336 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003337 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3338 if (!success)
3339 return false;
3340
Caroline Ticecc96eb52011-02-17 19:20:40 +00003341 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003342 return false;
3343 }
3344
3345 // if wback then R[n] = R[n] + 4*BitCount(registers);
3346 if (wback)
3347 {
3348 offset = addr_byte_size * BitCount (registers);
3349 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003350 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003351 addr_t data = address + offset;
3352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3353 return false;
3354 }
3355 }
3356 return true;
3357}
3358
Caroline Ticeaf556562011-02-15 18:42:15 +00003359// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3360// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3361// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003362bool
3363EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3364{
3365#if 0
3366 if ConditionPassed() then
3367 EncodingSpecificOperations();
3368 address = R[n] - 4*BitCount(registers) + 4;
3369
3370 for i = 0 to 14
3371 if registers<i> == ’1’ then
3372 if i == n && wback && i != LowestSetBit(registers) then
3373 MemA[address,4] = bits(32) UNKNOWN;
3374 else
3375 MemA[address,4] = R[i];
3376 address = address + 4;
3377
3378 if registers<15> == ’1’ then
3379 MemA[address,4] = PCStoreValue();
3380
3381 if wback then R[n] = R[n] - 4*BitCount(registers);
3382#endif
3383
3384 bool success = false;
3385 const uint32_t opcode = OpcodeAsUnsigned (&success);
3386 if (!success)
3387 return false;
3388
3389 if (ConditionPassed ())
3390 {
3391 uint32_t n;
3392 uint32_t registers = 0;
3393 bool wback;
3394 const uint32_t addr_byte_size = GetAddressByteSize();
3395
3396 // EncodingSpecificOperations();
3397 switch (encoding)
3398 {
3399 case eEncodingA1:
3400 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3401 n = Bits32 (opcode, 19, 16);
3402 registers = Bits32 (opcode, 15, 0);
3403 wback = BitIsSet (opcode, 21);
3404
3405 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3406 if ((n == 15) || (BitCount (registers) < 1))
3407 return false;
3408 break;
3409 default:
3410 return false;
3411 }
3412
3413 // address = R[n] - 4*BitCount(registers) + 4;
3414 int32_t offset = 0;
3415 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3416 if (!success)
3417 return false;
3418
3419 address = address - (addr_byte_size * BitCount (registers)) + 4;
3420
3421 EmulateInstruction::Context context;
3422 context.type = EmulateInstruction::eContextRegisterStore;
3423 Register base_reg;
3424 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3425
3426 // for i = 0 to 14
3427 for (int i = 0; i < 14; ++i)
3428 {
3429 int lowest_bit_set = 14;
3430 // if registers<i> == ’1’ then
3431 if (BitIsSet (registers, i))
3432 {
3433 if (i < lowest_bit_set)
3434 lowest_bit_set = i;
3435 //if i == n && wback && i != LowestSetBit(registers) then
3436 if ((i == n) && wback && (i != lowest_bit_set))
3437 // MemA[address,4] = bits(32) UNKNOWN;
3438 WriteBits32UnknownToMemory (address + offset);
3439 else
3440 {
3441 // MemA[address,4] = R[i];
3442 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3443 if (!success)
3444 return false;
3445
3446 Register data_reg;
3447 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3448 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003449 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003450 return false;
3451 }
3452
3453 // address = address + 4;
3454 offset += addr_byte_size;
3455 }
3456 }
3457
3458 // if registers<15> == ’1’ then
3459 // MemA[address,4] = PCStoreValue();
3460 if (BitIsSet (registers, 15))
3461 {
3462 Register pc_reg;
3463 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3464 context.SetRegisterPlusOffset (pc_reg, 8);
3465 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3466 if (!success)
3467 return false;
3468
Caroline Ticecc96eb52011-02-17 19:20:40 +00003469 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003470 return false;
3471 }
3472
3473 // if wback then R[n] = R[n] - 4*BitCount(registers);
3474 if (wback)
3475 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003476 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003477 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3478 context.SetImmediateSigned (offset);
3479 addr_t data = address + offset;
3480 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3481 return false;
3482 }
3483 }
3484 return true;
3485}
3486
Caroline Ticeaf556562011-02-15 18:42:15 +00003487// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3488// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3489// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003490bool
3491EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3492{
3493#if 0
3494 if ConditionPassed() then
3495 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3496 address = R[n] - 4*BitCount(registers);
3497
3498 for i = 0 to 14
3499 if registers<i> == ’1’ then
3500 if i == n && wback && i != LowestSetBit(registers) then
3501 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3502 else
3503 MemA[address,4] = R[i];
3504 address = address + 4;
3505
3506 if registers<15> == ’1’ then // Only possible for encoding A1
3507 MemA[address,4] = PCStoreValue();
3508
3509 if wback then R[n] = R[n] - 4*BitCount(registers);
3510#endif
3511
3512
3513 bool success = false;
3514 const uint32_t opcode = OpcodeAsUnsigned (&success);
3515 if (!success)
3516 return false;
3517
3518 if (ConditionPassed ())
3519 {
3520 uint32_t n;
3521 uint32_t registers = 0;
3522 bool wback;
3523 const uint32_t addr_byte_size = GetAddressByteSize();
3524
3525 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3526 switch (encoding)
3527 {
3528 case eEncodingT1:
3529 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3530 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3531 {
3532 // See PUSH
3533 }
3534 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3535 n = Bits32 (opcode, 19, 16);
3536 registers = Bits32 (opcode, 15, 0);
3537 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3538 wback = BitIsSet (opcode, 21);
3539 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3540 if ((n == 15) || BitCount (registers) < 2)
3541 return false;
3542 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3543 if (wback && BitIsSet (registers, n))
3544 return false;
3545 break;
3546
3547 case eEncodingA1:
3548 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3549 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3550 {
3551 // See Push
3552 }
3553 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3554 n = Bits32 (opcode, 19, 16);
3555 registers = Bits32 (opcode, 15, 0);
3556 wback = BitIsSet (opcode, 21);
3557 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3558 if ((n == 15) || BitCount (registers) < 1)
3559 return false;
3560 break;
3561
3562 default:
3563 return false;
3564 }
3565
3566 // address = R[n] - 4*BitCount(registers);
3567
3568 int32_t offset = 0;
3569 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3570 if (!success)
3571 return false;
3572
3573 address = address - (addr_byte_size * BitCount (registers));
3574
3575 EmulateInstruction::Context context;
3576 context.type = EmulateInstruction::eContextRegisterStore;
3577 Register base_reg;
3578 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3579
3580 // for i = 0 to 14
3581 for (int i = 0; i < 14; ++i)
3582 {
3583 uint32_t lowest_set_bit = 14;
3584 // if registers<i> == ’1’ then
3585 if (BitIsSet (registers, i))
3586 {
3587 if (i < lowest_set_bit)
3588 lowest_set_bit = i;
3589 // if i == n && wback && i != LowestSetBit(registers) then
3590 if ((i == n) && wback && (i != lowest_set_bit))
3591 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3592 WriteBits32UnknownToMemory (address + offset);
3593 else
3594 {
3595 // MemA[address,4] = R[i];
3596 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3597 if (!success)
3598 return false;
3599
3600 Register data_reg;
3601 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3602 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003603 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003604 return false;
3605 }
3606
3607 // address = address + 4;
3608 offset += addr_byte_size;
3609 }
3610 }
3611
3612 // if registers<15> == ’1’ then // Only possible for encoding A1
3613 // MemA[address,4] = PCStoreValue();
3614 if (BitIsSet (registers, 15))
3615 {
3616 Register pc_reg;
3617 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3618 context.SetRegisterPlusOffset (pc_reg, 8);
3619 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3620 if (!success)
3621 return false;
3622
Caroline Ticecc96eb52011-02-17 19:20:40 +00003623 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003624 return false;
3625 }
3626
3627 // if wback then R[n] = R[n] - 4*BitCount(registers);
3628 if (wback)
3629 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003630 offset = (addr_byte_size * BitCount (registers)) * -1;
3631 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3632 context.SetImmediateSigned (offset);
3633 addr_t data = address + offset;
3634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3635 return false;
3636 }
3637 }
3638 return true;
3639}
3640
3641// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3642// from a base register. The consecutive memory locations start just above this address, and the address of the last
3643// of those locations can optionally be written back to the base register.
3644bool
3645EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3646{
3647#if 0
3648 if ConditionPassed() then
3649 EncodingSpecificOperations();
3650 address = R[n] + 4;
3651
3652 for i = 0 to 14
3653 if registers<i> == ’1’ then
3654 if i == n && wback && i != LowestSetBit(registers) then
3655 MemA[address,4] = bits(32) UNKNOWN;
3656 else
3657 MemA[address,4] = R[i];
3658 address = address + 4;
3659
3660 if registers<15> == ’1’ then
3661 MemA[address,4] = PCStoreValue();
3662
3663 if wback then R[n] = R[n] + 4*BitCount(registers);
3664#endif
3665
3666 bool success = false;
3667 const uint32_t opcode = OpcodeAsUnsigned (&success);
3668 if (!success)
3669 return false;
3670
3671 if (ConditionPassed())
3672 {
3673 uint32_t n;
3674 uint32_t registers = 0;
3675 bool wback;
3676 const uint32_t addr_byte_size = GetAddressByteSize();
3677
3678 // EncodingSpecificOperations();
3679 switch (encoding)
3680 {
3681 case eEncodingA1:
3682 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3683 n = Bits32 (opcode, 19, 16);
3684 registers = Bits32 (opcode, 15, 0);
3685 wback = BitIsSet (opcode, 21);
3686
3687 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3688 if ((n == 15) && (BitCount (registers) < 1))
3689 return false;
3690 break;
3691 default:
3692 return false;
3693 }
3694 // address = R[n] + 4;
3695
3696 int32_t offset = 0;
3697 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3698 if (!success)
3699 return false;
3700
3701 address = address + addr_byte_size;
3702
3703 EmulateInstruction::Context context;
3704 context.type = EmulateInstruction::eContextRegisterStore;
3705 Register base_reg;
3706 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3707
3708 uint32_t lowest_set_bit = 14;
3709 // for i = 0 to 14
3710 for (int i = 0; i < 14; ++i)
3711 {
3712 // if registers<i> == ’1’ then
3713 if (BitIsSet (registers, i))
3714 {
3715 if (i < lowest_set_bit)
3716 lowest_set_bit = i;
3717 // if i == n && wback && i != LowestSetBit(registers) then
3718 if ((i == n) && wback && (i != lowest_set_bit))
3719 // MemA[address,4] = bits(32) UNKNOWN;
3720 WriteBits32UnknownToMemory (address + offset);
3721 // else
3722 else
3723 {
3724 // MemA[address,4] = R[i];
3725 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3726 if (!success)
3727 return false;
3728
3729 Register data_reg;
3730 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3731 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003732 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003733 return false;
3734 }
3735
3736 // address = address + 4;
3737 offset += addr_byte_size;
3738 }
3739 }
3740
3741 // if registers<15> == ’1’ then
3742 // MemA[address,4] = PCStoreValue();
3743 if (BitIsSet (registers, 15))
3744 {
3745 Register pc_reg;
3746 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3747 context.SetRegisterPlusOffset (pc_reg, 8);
3748 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3749 if (!success)
3750 return false;
3751
Caroline Ticecc96eb52011-02-17 19:20:40 +00003752 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003753 return false;
3754 }
3755
3756 // if wback then R[n] = R[n] + 4*BitCount(registers);
3757 if (wback)
3758 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003759 offset = addr_byte_size * BitCount (registers);
3760 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3761 context.SetImmediateSigned (offset);
3762 addr_t data = address + offset;
3763 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3764 return false;
3765 }
3766 }
3767 return true;
3768}
Caroline Tice7fac8572011-02-15 22:53:54 +00003769
3770// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3771// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3772bool
3773EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3774{
3775#if 0
3776 if ConditionPassed() then
3777 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3778 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3779 address = if index then offset_addr else R[n];
3780 if UnalignedSupport() || address<1:0> == ’00’ then
3781 MemU[address,4] = R[t];
3782 else // Can only occur before ARMv7
3783 MemU[address,4] = bits(32) UNKNOWN;
3784 if wback then R[n] = offset_addr;
3785#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003786
Caroline Tice7fac8572011-02-15 22:53:54 +00003787 bool success = false;
3788 const uint32_t opcode = OpcodeAsUnsigned (&success);
3789 if (!success)
3790 return false;
3791
3792 if (ConditionPassed())
3793 {
3794 const uint32_t addr_byte_size = GetAddressByteSize();
3795
3796 uint32_t t;
3797 uint32_t n;
3798 uint32_t imm32;
3799 bool index;
3800 bool add;
3801 bool wback;
3802 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3803 switch (encoding)
3804 {
3805 case eEncodingT1:
3806 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3807 t = Bits32 (opcode, 2, 0);
3808 n = Bits32 (opcode, 5, 3);
3809 imm32 = Bits32 (opcode, 10, 6) << 2;
3810
3811 // index = TRUE; add = TRUE; wback = FALSE;
3812 index = true;
3813 add = false;
3814 wback = false;
3815 break;
3816
3817 case eEncodingT2:
3818 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3819 t = Bits32 (opcode, 10, 8);
3820 n = 13;
3821 imm32 = Bits32 (opcode, 7, 0) << 2;
3822
3823 // index = TRUE; add = TRUE; wback = FALSE;
3824 index = true;
3825 add = true;
3826 wback = false;
3827 break;
3828
3829 case eEncodingT3:
3830 // if Rn == ’1111’ then UNDEFINED;
3831 if (Bits32 (opcode, 19, 16) == 15)
3832 return false;
3833
3834 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3835 t = Bits32 (opcode, 15, 12);
3836 n = Bits32 (opcode, 19, 16);
3837 imm32 = Bits32 (opcode, 11, 0);
3838
3839 // index = TRUE; add = TRUE; wback = FALSE;
3840 index = true;
3841 add = true;
3842 wback = false;
3843
3844 // if t == 15 then UNPREDICTABLE;
3845 if (t == 15)
3846 return false;
3847 break;
3848
3849 case eEncodingT4:
3850 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3851 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3852 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3853 if ((Bits32 (opcode, 19, 16) == 15)
3854 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3855 return false;
3856
3857 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3858 t = Bits32 (opcode, 15, 12);
3859 n = Bits32 (opcode, 19, 16);
3860 imm32 = Bits32 (opcode, 7, 0);
3861
3862 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3863 index = BitIsSet (opcode, 10);
3864 add = BitIsSet (opcode, 9);
3865 wback = BitIsSet (opcode, 8);
3866
3867 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3868 if ((t == 15) || (wback && (n == t)))
3869 return false;
3870 break;
3871
3872 default:
3873 return false;
3874 }
3875
3876 addr_t offset_addr;
3877 addr_t address;
3878
3879 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3880 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3881 if (!success)
3882 return false;
3883
3884 if (add)
3885 offset_addr = base_address + imm32;
3886 else
3887 offset_addr = base_address - imm32;
3888
3889 // address = if index then offset_addr else R[n];
3890 if (index)
3891 address = offset_addr;
3892 else
3893 address = base_address;
3894
3895 EmulateInstruction::Context context;
3896 context.type = eContextRegisterStore;
3897 Register base_reg;
3898 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3899
3900 // if UnalignedSupport() || address<1:0> == ’00’ then
3901 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3902 {
3903 // MemU[address,4] = R[t];
3904 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3905 if (!success)
3906 return false;
3907
3908 Register data_reg;
3909 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3910 int32_t offset = address - base_address;
3911 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003912 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003913 return false;
3914 }
3915 else
3916 {
3917 // MemU[address,4] = bits(32) UNKNOWN;
3918 WriteBits32UnknownToMemory (address);
3919 }
3920
3921 // if wback then R[n] = offset_addr;
3922 if (wback)
3923 {
3924 context.type = eContextRegisterLoad;
3925 context.SetAddress (offset_addr);
3926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3927 return false;
3928 }
3929 }
3930 return true;
3931}
Caroline Ticeaf556562011-02-15 18:42:15 +00003932
Caroline Tice3fd63e92011-02-16 00:33:43 +00003933// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3934// word from a register to memory. The offset register value can optionally be shifted.
3935bool
3936EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3937{
3938#if 0
3939 if ConditionPassed() then
3940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3941 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3942 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3943 address = if index then offset_addr else R[n];
3944 if t == 15 then // Only possible for encoding A1
3945 data = PCStoreValue();
3946 else
3947 data = R[t];
3948 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3949 MemU[address,4] = data;
3950 else // Can only occur before ARMv7
3951 MemU[address,4] = bits(32) UNKNOWN;
3952 if wback then R[n] = offset_addr;
3953#endif
3954
3955 bool success = false;
3956 const uint32_t opcode = OpcodeAsUnsigned (&success);
3957 if (!success)
3958 return false;
3959
3960 if (ConditionPassed())
3961 {
3962 const uint32_t addr_byte_size = GetAddressByteSize();
3963
3964 uint32_t t;
3965 uint32_t n;
3966 uint32_t m;
3967 ARM_ShifterType shift_t;
3968 uint32_t shift_n;
3969 bool index;
3970 bool add;
3971 bool wback;
3972
3973 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3974 switch (encoding)
3975 {
3976 case eEncodingT1:
3977 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3978 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3979 t = Bits32 (opcode, 2, 0);
3980 n = Bits32 (opcode, 5, 3);
3981 m = Bits32 (opcode, 8, 6);
3982
3983 // index = TRUE; add = TRUE; wback = FALSE;
3984 index = true;
3985 add = true;
3986 wback = false;
3987
3988 // (shift_t, shift_n) = (SRType_LSL, 0);
3989 shift_t = SRType_LSL;
3990 shift_n = 0;
3991 break;
3992
3993 case eEncodingT2:
3994 // if Rn == ’1111’ then UNDEFINED;
3995 if (Bits32 (opcode, 19, 16) == 15)
3996 return false;
3997
3998 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3999 t = Bits32 (opcode, 15, 12);
4000 n = Bits32 (opcode, 19, 16);
4001 m = Bits32 (opcode, 3, 0);
4002
4003 // index = TRUE; add = TRUE; wback = FALSE;
4004 index = true;
4005 add = true;
4006 wback = false;
4007
4008 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4009 shift_t = SRType_LSL;
4010 shift_n = Bits32 (opcode, 5, 4);
4011
4012 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4013 if ((t == 15) || (BadReg (m)))
4014 return false;
4015 break;
4016
4017 case eEncodingA1:
4018 {
4019 // if P == ’0’ && W == ’1’ then SEE STRT;
4020 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4021 t = Bits32 (opcode, 15, 12);
4022 n = Bits32 (opcode, 19, 16);
4023 m = Bits32 (opcode, 3, 0);
4024
4025 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4026 index = BitIsSet (opcode, 24);
4027 add = BitIsSet (opcode, 23);
4028 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4029
4030 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4031 uint32_t typ = Bits32 (opcode, 6, 5);
4032 uint32_t imm5 = Bits32 (opcode, 11, 7);
4033 shift_n = DecodeImmShift(typ, imm5, shift_t);
4034
4035 // if m == 15 then UNPREDICTABLE;
4036 if (m == 15)
4037 return false;
4038
4039 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4040 if (wback && ((n == 15) || (n == t)))
4041 return false;
4042
4043 break;
4044 }
4045 default:
4046 return false;
4047 }
4048
4049 addr_t offset_addr;
4050 addr_t address;
4051 int32_t offset = 0;
4052
4053 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4054 if (!success)
4055 return false;
4056
4057 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4058 if (!success)
4059 return false;
4060
4061 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004062 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004063
4064 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4065 if (add)
4066 offset_addr = base_address + offset;
4067 else
4068 offset_addr = base_address - offset;
4069
4070 // address = if index then offset_addr else R[n];
4071 if (index)
4072 address = offset_addr;
4073 else
4074 address = base_address;
4075
4076 uint32_t data;
4077 // if t == 15 then // Only possible for encoding A1
4078 if (t == 15)
4079 // data = PCStoreValue();
4080 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4081 else
4082 // data = R[t];
4083 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4084
4085 if (!success)
4086 return false;
4087
4088 EmulateInstruction::Context context;
4089 context.type = eContextRegisterStore;
4090
4091 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4092 if (UnalignedSupport ()
4093 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4094 || CurrentInstrSet() == eModeARM)
4095 {
4096 // MemU[address,4] = data;
4097
4098 Register base_reg;
4099 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4100
4101 Register data_reg;
4102 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4103
4104 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004105 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004106 return false;
4107
4108 }
4109 else
4110 // MemU[address,4] = bits(32) UNKNOWN;
4111 WriteBits32UnknownToMemory (address);
4112
4113 // if wback then R[n] = offset_addr;
4114 if (wback)
4115 {
4116 context.type = eContextRegisterLoad;
4117 context.SetAddress (offset_addr);
4118 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4119 return false;
4120 }
4121
4122 }
4123 return true;
4124}
Caroline Tice73a29de2011-02-16 20:22:22 +00004125
4126bool
4127EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4128{
4129#if 0
4130 if ConditionPassed() then
4131 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4132 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4133 address = if index then offset_addr else R[n];
4134 MemU[address,1] = R[t]<7:0>;
4135 if wback then R[n] = offset_addr;
4136#endif
4137
4138
4139 bool success = false;
4140 const uint32_t opcode = OpcodeAsUnsigned (&success);
4141 if (!success)
4142 return false;
4143
4144 if (ConditionPassed ())
4145 {
4146 uint32_t t;
4147 uint32_t n;
4148 uint32_t imm32;
4149 bool index;
4150 bool add;
4151 bool wback;
4152 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4153 switch (encoding)
4154 {
4155 case eEncodingT1:
4156 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4157 t = Bits32 (opcode, 2, 0);
4158 n = Bits32 (opcode, 5, 3);
4159 imm32 = Bits32 (opcode, 10, 6);
4160
4161 // index = TRUE; add = TRUE; wback = FALSE;
4162 index = true;
4163 add = true;
4164 wback = false;
4165 break;
4166
4167 case eEncodingT2:
4168 // if Rn == ’1111’ then UNDEFINED;
4169 if (Bits32 (opcode, 19, 16) == 15)
4170 return false;
4171
4172 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4173 t = Bits32 (opcode, 15, 12);
4174 n = Bits32 (opcode, 19, 16);
4175 imm32 = Bits32 (opcode, 11, 0);
4176
4177 // index = TRUE; add = TRUE; wback = FALSE;
4178 index = true;
4179 add = true;
4180 wback = false;
4181
4182 // if BadReg(t) then UNPREDICTABLE;
4183 if (BadReg (t))
4184 return false;
4185 break;
4186
4187 case eEncodingT3:
4188 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4189 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4190 if (Bits32 (opcode, 19, 16) == 15)
4191 return false;
4192
4193 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4194 t = Bits32 (opcode, 15, 12);
4195 n = Bits32 (opcode, 19, 16);
4196 imm32 = Bits32 (opcode, 7, 0);
4197
4198 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4199 index = BitIsSet (opcode, 10);
4200 add = BitIsSet (opcode, 9);
4201 wback = BitIsSet (opcode, 8);
4202
4203 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4204 if ((BadReg (t)) || (wback && (n == t)))
4205 return false;
4206 break;
4207
4208 default:
4209 return false;
4210 }
4211
4212 addr_t offset_addr;
4213 addr_t address;
4214 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4215 if (!success)
4216 return false;
4217
4218 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4219 if (add)
4220 offset_addr = base_address + imm32;
4221 else
4222 offset_addr = base_address - imm32;
4223
4224 // address = if index then offset_addr else R[n];
4225 if (index)
4226 address = offset_addr;
4227 else
4228 address = base_address;
4229
Caroline Ticecc96eb52011-02-17 19:20:40 +00004230 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004231 Register base_reg;
4232 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4233
4234 Register data_reg;
4235 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4236
4237 EmulateInstruction::Context context;
4238 context.type = eContextRegisterStore;
4239 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4240
4241 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4242 if (!success)
4243 return false;
4244
4245 data = Bits32 (data, 7, 0);
4246
Caroline Ticecc96eb52011-02-17 19:20:40 +00004247 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004248 return false;
4249
4250 // if wback then R[n] = offset_addr;
4251 if (wback)
4252 {
4253 context.type = eContextRegisterLoad;
4254 context.SetAddress (offset_addr);
4255 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4256 return false;
4257 }
4258
4259 }
4260
4261 return true;
4262}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004263
Johnny Chene97c0d52011-02-18 19:32:20 +00004264// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4265// to the destination register. It can optionally update the condition flags based on the result.
4266bool
4267EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4268{
4269#if 0
4270 // ARM pseudo code...
4271 if ConditionPassed() then
4272 EncodingSpecificOperations();
4273 result = R[n] AND imm32;
4274 if d == 15 then // Can only occur for ARM encoding
4275 ALUWritePC(result); // setflags is always FALSE here
4276 else
4277 R[d] = result;
4278 if setflags then
4279 APSR.N = result<31>;
4280 APSR.Z = IsZeroBit(result);
4281 APSR.C = carry;
4282 // APSR.V unchanged
4283#endif
4284
4285 bool success = false;
4286 const uint32_t opcode = OpcodeAsUnsigned (&success);
4287 if (!success)
4288 return false;
4289
4290 if (ConditionPassed())
4291 {
4292 uint32_t Rd, Rn;
4293 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4294 bool setflags;
4295 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4296 switch (encoding)
4297 {
4298 case eEncodingT1:
4299 Rd = Bits32(opcode, 11, 8);
4300 Rn = Bits32(opcode, 19, 16);
4301 setflags = BitIsSet(opcode, 20);
4302 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
4303 // TODO: Emulate TST (immediate)
4304 if (Rd == 15 && setflags)
4305 return false;
4306 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4307 return false;
4308 break;
4309 case eEncodingA1:
4310 Rd = Bits32(opcode, 15, 12);
4311 Rn = Bits32(opcode, 19, 16);
4312 setflags = BitIsSet(opcode, 20);
4313 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4314 // TODO: Emulate SUBS PC, LR and related instructions.
4315 if (Rd == 15 && setflags)
4316 return false;
4317 break;
4318 default:
4319 return false;
4320 }
4321
4322 int32_t val1;
4323 // Read the first operand.
4324 if (Rn == 15)
4325 {
4326 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4327 if (encoding == eEncodingT1)
4328 val1 += 4;
4329 else
4330 val1 += 8;
4331 }
4332 else
4333 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
4334 if (!success)
4335 return false;
4336
4337 uint32_t result = val1 & imm32;
4338
4339 EmulateInstruction::Context context;
4340 context.type = EmulateInstruction::eContextImmediate;
4341 context.SetNoArgs ();
4342
4343 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4344 return false;
4345 }
4346 return true;
4347}
4348
4349// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4350// and writes the result to the destination register. It can optionally update the condition flags
4351// based on the result.
4352bool
4353EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4354{
4355#if 0
4356 // ARM pseudo code...
4357 if ConditionPassed() then
4358 EncodingSpecificOperations();
4359 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4360 result = R[n] AND shifted;
4361 if d == 15 then // Can only occur for ARM encoding
4362 ALUWritePC(result); // setflags is always FALSE here
4363 else
4364 R[d] = result;
4365 if setflags then
4366 APSR.N = result<31>;
4367 APSR.Z = IsZeroBit(result);
4368 APSR.C = carry;
4369 // APSR.V unchanged
4370#endif
4371
4372 bool success = false;
4373 const uint32_t opcode = OpcodeAsUnsigned (&success);
4374 if (!success)
4375 return false;
4376
4377 if (ConditionPassed())
4378 {
4379 uint32_t Rd, Rn, Rm;
4380 ARM_ShifterType shift_t;
4381 uint32_t shift_n; // the shift applied to the value read from Rm
4382 bool setflags;
4383 uint32_t carry;
4384 switch (encoding)
4385 {
4386 case eEncodingT1:
4387 Rd = Rn = Bits32(opcode, 2, 0);
4388 Rm = Bits32(opcode, 5, 3);
4389 setflags = !InITBlock();
4390 shift_t = SRType_LSL;
4391 shift_n = 0;
4392 case eEncodingT2:
4393 Rd = Bits32(opcode, 11, 8);
4394 Rn = Bits32(opcode, 19, 16);
4395 Rm = Bits32(opcode, 3, 0);
4396 setflags = BitIsSet(opcode, 20);
4397 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6), shift_t);
4398 // TODO: Emulate TST (register)
4399 if (Rd == 15 && setflags)
4400 return false;
4401 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4402 return false;
4403 break;
4404 case eEncodingA1:
4405 Rd = Bits32(opcode, 15, 12);
4406 Rn = Bits32(opcode, 19, 16);
4407 Rm = Bits32(opcode, 3, 0);
4408 setflags = BitIsSet(opcode, 20);
4409 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4410 // TODO: Emulate SUBS PC, LR and related instructions.
4411 if (Rd == 15 && setflags)
4412 return false;
4413 break;
4414 default:
4415 return false;
4416 }
4417
4418 int32_t val1, val2;
4419 // Read the first operand.
4420 if (Rn == 15)
4421 {
4422 val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4423 if (encoding == eEncodingT1 || encoding == eEncodingT2)
4424 val1 += 4;
4425 else
4426 val1 += 8;
4427 }
4428 else
4429 val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
4430 if (!success)
4431 return false;
4432
4433 // Read the second operand.
4434 if (Rm == 15)
4435 {
4436 val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4437 if (encoding == eEncodingT1 || encoding == eEncodingT2)
4438 val1 += 4;
4439 else
4440 val1 += 8;
4441 }
4442 else
4443 val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
4444 if (!success)
4445 return false;
4446
4447 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4448 uint32_t result = val1 & shifted;
4449
4450 EmulateInstruction::Context context;
4451 context.type = EmulateInstruction::eContextImmediate;
4452 context.SetNoArgs ();
4453
4454 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4455 return false;
4456 }
4457 return true;
4458}
4459
Caroline Tice4d729c52011-02-18 00:55:53 +00004460// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
Johnny Chene92b27c2011-02-18 01:26:39 +00004461// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Tice4d729c52011-02-18 00:55:53 +00004462bool
4463EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4464{
4465#if 0
4466 if ConditionPassed() then
4467 EncodingSpecificOperations();
4468 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4469 address = if index then offset_addr else R[n];
4470 data = MemU[address,4];
4471 if wback then R[n] = offset_addr;
4472 if t == 15 then
4473 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4474 elsif UnalignedSupport() || address<1:0> = ’00’ then
4475 R[t] = data;
4476 else // Can only apply before ARMv7
4477 R[t] = ROR(data, 8*UInt(address<1:0>));
4478#endif
4479
4480 bool success = false;
4481 const uint32_t opcode = OpcodeAsUnsigned (&success);
4482 if (!success)
4483 return false;
4484
4485 if (ConditionPassed ())
4486 {
4487 const uint32_t addr_byte_size = GetAddressByteSize();
4488
4489 uint32_t t;
4490 uint32_t n;
4491 uint32_t imm32;
4492 bool index;
4493 bool add;
4494 bool wback;
4495
4496 switch (encoding)
4497 {
4498 case eEncodingA1:
4499 // if Rn == ’1111’ then SEE LDR (literal);
4500 // if P == ’0’ && W == ’1’ then SEE LDRT;
4501 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4502 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4503 t = Bits32 (opcode, 15, 12);
4504 n = Bits32 (opcode, 19, 16);
4505 imm32 = Bits32 (opcode, 11, 0);
4506
4507 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4508 index = BitIsSet (opcode, 24);
4509 add = BitIsSet (opcode, 23);
4510 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4511
4512 // if wback && n == t then UNPREDICTABLE;
4513 if (wback && (n == t))
4514 return false;
4515
4516 break;
4517
4518 default:
4519 return false;
4520 }
4521
4522 addr_t address;
4523 addr_t offset_addr;
4524 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4525 if (!success)
4526 return false;
4527
4528 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4529 if (add)
4530 offset_addr = base_address + imm32;
4531 else
4532 offset_addr = base_address - imm32;
4533
4534 // address = if index then offset_addr else R[n];
4535 if (index)
4536 address = offset_addr;
4537 else
4538 address = base_address;
4539
4540 // data = MemU[address,4];
4541
4542 Register base_reg;
4543 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4544
4545 EmulateInstruction::Context context;
4546 context.type = eContextRegisterLoad;
4547 context.SetRegisterPlusOffset (base_reg, address - base_address);
4548
4549 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4550 if (!success)
4551 return false;
4552
4553 // if wback then R[n] = offset_addr;
4554 if (wback)
4555 {
4556 context.type = eContextAdjustBaseRegister;
4557 context.SetAddress (offset_addr);
4558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4559 return false;
4560 }
4561
4562 // if t == 15 then
4563 if (t == 15)
4564 {
4565 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4566 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4567 {
4568 // LoadWritePC (data);
4569 context.type = eContextRegisterLoad;
4570 context.SetRegisterPlusOffset (base_reg, address - base_address);
4571 LoadWritePC (context, data);
4572 }
4573 else
4574 return false;
4575 }
4576 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4577 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4578 {
4579 // R[t] = data;
4580 context.type = eContextRegisterLoad;
4581 context.SetRegisterPlusOffset (base_reg, address - base_address);
4582 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4583 return false;
4584 }
4585 // else // Can only apply before ARMv7
4586 else
4587 {
4588 // R[t] = ROR(data, 8*UInt(address<1:0>));
4589 data = ROR (data, Bits32 (address, 1, 0));
4590 context.type = eContextRegisterLoad;
4591 context.SetImmediate (data);
4592 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4593 return false;
4594 }
4595
4596 }
4597 return true;
4598}
4599
Caroline Ticefe479112011-02-18 18:52:37 +00004600// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4601// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4602bool
4603EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4604{
4605#if 0
4606 if ConditionPassed() then
4607 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4608 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4609 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4610 address = if index then offset_addr else R[n];
4611 data = MemU[address,4];
4612 if wback then R[n] = offset_addr;
4613 if t == 15 then
4614 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4615 elsif UnalignedSupport() || address<1:0> = ’00’ then
4616 R[t] = data;
4617 else // Can only apply before ARMv7
4618 if CurrentInstrSet() == InstrSet_ARM then
4619 R[t] = ROR(data, 8*UInt(address<1:0>));
4620 else
4621 R[t] = bits(32) UNKNOWN;
4622#endif
4623
4624 bool success = false;
4625 const uint32_t opcode = OpcodeAsUnsigned (&success);
4626 if (!success)
4627 return false;
4628
4629 if (ConditionPassed ())
4630 {
4631 const uint32_t addr_byte_size = GetAddressByteSize();
4632
4633 uint32_t t;
4634 uint32_t n;
4635 uint32_t m;
4636 bool index;
4637 bool add;
4638 bool wback;
4639 ARM_ShifterType shift_t;
4640 uint32_t shift_n;
4641
4642 switch (encoding)
4643 {
4644 case eEncodingT1:
4645 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4646 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4647 t = Bits32 (opcode, 2, 0);
4648 n = Bits32 (opcode, 5, 3);
4649 m = Bits32 (opcode, 8, 6);
4650
4651 // index = TRUE; add = TRUE; wback = FALSE;
4652 index = true;
4653 add = true;
4654 wback = false;
4655
4656 // (shift_t, shift_n) = (SRType_LSL, 0);
4657 shift_t = SRType_LSL;
4658 shift_n = 0;
4659
4660 break;
4661
4662 case eEncodingT2:
4663 // if Rn == ’1111’ then SEE LDR (literal);
4664 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4665 t = Bits32 (opcode, 15, 12);
4666 n = Bits32 (opcode, 19, 16);
4667 m = Bits32 (opcode, 3, 0);
4668
4669 // index = TRUE; add = TRUE; wback = FALSE;
4670 index = true;
4671 add = true;
4672 wback = false;
4673
4674 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4675 shift_t = SRType_LSL;
4676 shift_n = Bits32 (opcode, 5, 4);
4677
4678 // if BadReg(m) then UNPREDICTABLE;
4679 if (BadReg (m))
4680 return false;
4681
4682 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4683 if ((t == 15) && InITBlock() && !LastInITBlock())
4684 return false;
4685
4686 break;
4687
4688 case eEncodingA1:
4689 {
4690 // if P == ’0’ && W == ’1’ then SEE LDRT;
4691 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4692 t = Bits32 (opcode, 15, 12);
4693 n = Bits32 (opcode, 19, 16);
4694 m = Bits32 (opcode, 3, 0);
4695
4696 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4697 index = BitIsSet (opcode, 24);
4698 add = BitIsSet (opcode, 23);
4699 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4700
4701 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4702 uint32_t type = Bits32 (opcode, 6, 5);
4703 uint32_t imm5 = Bits32 (opcode, 11, 7);
4704 shift_n = DecodeImmShift (type, imm5, shift_t);
4705
4706 // if m == 15 then UNPREDICTABLE;
4707 if (m == 15)
4708 return false;
4709
4710 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4711 if (wback && ((n == 15) || (n == t)))
4712 return false;
4713 }
4714 break;
4715
4716
4717 default:
4718 return false;
4719 }
4720
4721 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4722 if (!success)
4723 return false;
4724
4725 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4726 if (!success)
4727 return false;
4728
4729 addr_t offset_addr;
4730 addr_t address;
4731
4732 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
4733 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
4734
4735 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4736 if (add)
4737 offset_addr = Rn + offset;
4738 else
4739 offset_addr = Rn - offset;
4740
4741 // address = if index then offset_addr else R[n];
4742 if (index)
4743 address = offset_addr;
4744 else
4745 address = Rn;
4746
4747 // data = MemU[address,4];
4748 Register base_reg;
4749 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4750
4751 EmulateInstruction::Context context;
4752 context.type = eContextRegisterLoad;
4753 context.SetRegisterPlusOffset (base_reg, address - Rn);
4754
4755 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4756 if (!success)
4757 return false;
4758
4759 // if wback then R[n] = offset_addr;
4760 if (wback)
4761 {
4762 context.type = eContextAdjustBaseRegister;
4763 context.SetAddress (offset_addr);
4764 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4765 return false;
4766 }
4767
4768 // if t == 15 then
4769 if (t == 15)
4770 {
4771 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4772 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4773 {
4774 context.type = eContextRegisterLoad;
4775 context.SetRegisterPlusOffset (base_reg, address - Rn);
4776 LoadWritePC (context, data);
4777 }
4778 else
4779 return false;
4780 }
4781 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4782 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4783 {
4784 // R[t] = data;
4785 context.type = eContextRegisterLoad;
4786 context.SetRegisterPlusOffset (base_reg, address - Rn);
4787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4788 return false;
4789 }
4790 else // Can only apply before ARMv7
4791 {
4792 // if CurrentInstrSet() == InstrSet_ARM then
4793 if (CurrentInstrSet () == eModeARM)
4794 {
4795 // R[t] = ROR(data, 8*UInt(address<1:0>));
4796 data = ROR (data, Bits32 (address, 1, 0));
4797 context.type = eContextRegisterLoad;
4798 context.SetImmediate (data);
4799 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4800 return false;
4801 }
4802 else
4803 {
4804 // R[t] = bits(32) UNKNOWN;
4805 WriteBits32Unknown (t);
4806 }
4807 }
4808 }
4809 return true;
4810}
Caroline Tice21b604b2011-02-18 21:06:04 +00004811
4812// LDRB (immediate, Thumb)
4813bool
4814EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
4815{
4816#if 0
4817 if ConditionPassed() then
4818 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4819 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4820 address = if index then offset_addr else R[n];
4821 R[t] = ZeroExtend(MemU[address,1], 32);
4822 if wback then R[n] = offset_addr;
4823#endif
4824
4825 bool success = false;
4826 const uint32_t opcode = OpcodeAsUnsigned (&success);
4827 if (!success)
4828 return false;
4829
4830 if (ConditionPassed ())
4831 {
4832 uint32_t t;
4833 uint32_t n;
4834 uint32_t imm32;
4835 bool index;
4836 bool add;
4837 bool wback;
4838
4839 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4840 switch (encoding)
4841 {
4842 case eEncodingT1:
4843 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4844 t = Bits32 (opcode, 2, 0);
4845 n = Bits32 (opcode, 5, 3);
4846 imm32 = Bits32 (opcode, 10, 6);
4847
4848 // index = TRUE; add = TRUE; wback = FALSE;
4849 index = true;
4850 add = true;
4851 wback= false;
4852
4853 break;
4854
4855 case eEncodingT2:
4856 // if Rt == ’1111’ then SEE PLD;
4857 // if Rn == ’1111’ then SEE LDRB (literal);
4858 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4859 t = Bits32 (opcode, 15, 12);
4860 n = Bits32 (opcode, 19, 16);
4861 imm32 = Bits32 (opcode, 11, 0);
4862
4863 // index = TRUE; add = TRUE; wback = FALSE;
4864 index = true;
4865 add = true;
4866 wback = false;
4867
4868 // if t == 13 then UNPREDICTABLE;
4869 if (t == 13)
4870 return false;
4871
4872 break;
4873
4874 case eEncodingT3:
4875 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
4876 // if Rn == ’1111’ then SEE LDRB (literal);
4877 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
4878 // if P == ’0’ && W == ’0’ then UNDEFINED;
4879 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
4880 return false;
4881
4882 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4883 t = Bits32 (opcode, 15, 12);
4884 n = Bits32 (opcode, 19, 16);
4885 imm32 = Bits32 (opcode, 7, 0);
4886
4887 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4888 index = BitIsSet (opcode, 10);
4889 add = BitIsSet (opcode, 9);
4890 wback = BitIsSet (opcode, 8);
4891
4892 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
4893 if (BadReg (t) || (wback && (n == t)))
4894 return false;
4895
4896 break;
4897
4898 default:
4899 return false;
4900 }
4901
4902 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4903 if (!success)
4904 return false;
4905
4906 addr_t address;
4907 addr_t offset_addr;
4908
4909 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4910 if (add)
4911 offset_addr = Rn + imm32;
4912 else
4913 offset_addr = Rn - imm32;
4914
4915 // address = if index then offset_addr else R[n];
4916 if (index)
4917 address = offset_addr;
4918 else
4919 address = Rn;
4920
4921 // R[t] = ZeroExtend(MemU[address,1], 32);
4922 Register base_reg;
4923 Register data_reg;
4924 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4925 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4926
4927 EmulateInstruction::Context context;
4928 context.type = eContextRegisterLoad;
4929 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
4930
4931 uint64_t data = MemURead (context, address, 1, 0, &success);
4932 if (!success)
4933 return false;
4934
4935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4936 return false;
4937
4938 // if wback then R[n] = offset_addr;
4939 if (wback)
4940 {
4941 context.type = eContextAdjustBaseRegister;
4942 context.SetAddress (offset_addr);
4943 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4944 return false;
4945 }
4946 }
4947 return true;
4948}
Caroline Ticefe479112011-02-18 18:52:37 +00004949
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004950EmulateInstructionARM::ARMOpcode*
4951EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00004952{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004953 static ARMOpcode
4954 g_arm_opcodes[] =
4955 {
4956 //----------------------------------------------------------------------
4957 // Prologue instructions
4958 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00004959
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004960 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00004961 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
4962 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00004963
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004964 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00004965 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004966 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00004967 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00004968 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
4969 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00004970 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00004971
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004972 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00004973 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00004974
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004975 // push one register
4976 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00004977 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00004978
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004979 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00004980 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
4981 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00004982
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004983 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00004984 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00004985 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00004986
Johnny Chen9f687722011-02-18 00:02:28 +00004987 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
4988 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00004989 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00004990 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
4991
4992 //----------------------------------------------------------------------
4993 // Supervisor Call (previously Software Interrupt)
4994 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00004995 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
4996
4997 //----------------------------------------------------------------------
4998 // Branch instructions
4999 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005000 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00005001 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
5002 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5003 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5004 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005005 // for example, "bx lr"
5006 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005007
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005008 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00005009 // Data-processing instructions
5010 //----------------------------------------------------------------------
Johnny Chen8fa20592011-02-18 01:22:22 +00005011 // add (immediate)
5012 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s} <Rd>, <Rn>, #const"},
5013 // add (register)
5014 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s} <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005015 // and (immediate)
5016 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s} <Rd>, <Rn>, #const"},
5017 // and (register)
5018 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s} <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen28070c32011-02-12 01:27:26 +00005019 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005020 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005021 // asr (immediate)
5022 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005023 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00005024 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005025 // lsl (immediate)
5026 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
5027 // lsl (register)
5028 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
5029 // lsr (immediate)
5030 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
5031 // lsr (register)
5032 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005033 // rrx is a special case encoding of ror (immediate)
5034 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
5035 // ror (immediate)
5036 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
5037 // ror (register)
5038 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005039
5040 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005041 // Load instructions
5042 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00005043 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00005044 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00005045 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00005046 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00005047 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00005048 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00005049
5050 //----------------------------------------------------------------------
5051 // Store instructions
5052 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00005053 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005054 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00005055 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00005056 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
5057 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00005058
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005059
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005060 };
5061 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
5062
5063 for (size_t i=0; i<k_num_arm_opcodes; ++i)
5064 {
5065 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
5066 return &g_arm_opcodes[i];
5067 }
5068 return NULL;
5069}
Greg Clayton64c84432011-01-21 22:02:52 +00005070
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005071
5072EmulateInstructionARM::ARMOpcode*
5073EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00005074{
Johnny Chenfdd179e2011-01-31 20:09:28 +00005075
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005076 static ARMOpcode
5077 g_thumb_opcodes[] =
5078 {
5079 //----------------------------------------------------------------------
5080 // Prologue instructions
5081 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00005082
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005083 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005084 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5085 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
5086 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00005087
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005088 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005089 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005090 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00005091 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005092 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00005093 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00005094
Johnny Chen864a8e82011-02-18 00:07:39 +00005095 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00005096 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00005097
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005098 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005099 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
5100 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
5101 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
5102 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005103
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005104 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00005105 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5106 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005107
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005108 //----------------------------------------------------------------------
5109 // Epilogue instructions
5110 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00005111
Johnny Chen864a8e82011-02-18 00:07:39 +00005112 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00005113 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5114 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
5115 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00005116 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
5117 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005118
5119 //----------------------------------------------------------------------
5120 // Supervisor Call (previously Software Interrupt)
5121 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00005122 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
5123
5124 //----------------------------------------------------------------------
5125 // If Then makes up to four following instructions conditional.
5126 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005127 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
5128
5129 //----------------------------------------------------------------------
5130 // Branch instructions
5131 //----------------------------------------------------------------------
5132 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
5133 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
5134 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00005135 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005136 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00005137 // J1 == J2 == 1
5138 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5139 // J1 == J2 == 1
5140 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5141 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005142 // for example, "bx lr"
5143 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00005144 // compare and branch
5145 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00005146 // table branch byte
5147 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
5148 // table branch halfword
5149 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005150
5151 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00005152 // Data-processing instructions
5153 //----------------------------------------------------------------------
Johnny Chen9f687722011-02-18 00:02:28 +00005154 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005155 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chend761dcf2011-02-17 22:03:29 +00005156 // Can update PC!
Johnny Chen9f687722011-02-18 00:02:28 +00005157 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005158 // and (immediate)
5159 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s} <Rd>, <Rn>, #<const>"},
5160 // and (register)
5161 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
5162 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen338bf542011-02-10 19:29:03 +00005163 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00005164 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00005165 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00005166 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00005167 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005168 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
5169 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005170 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005171 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00005172 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005173 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005174 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005175 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005176 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005177 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005178 // asr (immediate)
5179 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00005180 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00005181 // asr (register)
5182 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
5183 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005184 // lsl (immediate)
5185 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
5186 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
5187 // lsl (register)
5188 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
5189 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
5190 // lsr (immediate)
5191 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
5192 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
5193 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00005194 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005195 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005196 // rrx is a special case encoding of ror (immediate)
5197 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
5198 // ror (immediate)
5199 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
5200 // ror (register)
5201 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
5202 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005203
5204 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005205 // Load instructions
5206 //----------------------------------------------------------------------
5207 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00005208 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00005209 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00005210 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
5211 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00005212 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00005213 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
5214 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00005215 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
5216 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
5217 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00005218
5219 //----------------------------------------------------------------------
5220 // Store instructions
5221 //----------------------------------------------------------------------
5222 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005223 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00005224 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00005225 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
5226 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
5227 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
5228 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
5229 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
5230 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
5231 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
5232 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
5233 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005234 };
5235
5236 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
5237 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
5238 {
5239 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
5240 return &g_thumb_opcodes[i];
5241 }
5242 return NULL;
5243}
Greg Clayton64c84432011-01-21 22:02:52 +00005244
Greg Clayton31e2a382011-01-30 20:03:56 +00005245bool
Greg Clayton395fc332011-02-15 21:59:32 +00005246EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00005247{
5248 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00005249 const char *arch_cstr = arch.AsCString ();
5250 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00005251 {
Greg Clayton395fc332011-02-15 21:59:32 +00005252 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
5253 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
5254 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
5255 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
5256 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
5257 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
5258 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
5259 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
5260 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
5261 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00005262 }
5263 return m_arm_isa != 0;
5264}
5265
5266
Greg Clayton64c84432011-01-21 22:02:52 +00005267bool
5268EmulateInstructionARM::ReadInstruction ()
5269{
5270 bool success = false;
5271 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
5272 if (success)
5273 {
5274 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
5275 if (success)
5276 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00005277 Context read_inst_context;
5278 read_inst_context.type = eContextReadOpcode;
5279 read_inst_context.SetNoArgs ();
5280
Greg Clayton64c84432011-01-21 22:02:52 +00005281 if (m_inst_cpsr & MASK_CPSR_T)
5282 {
5283 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005284 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005285
5286 if (success)
5287 {
5288 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
5289 {
5290 m_inst.opcode_type = eOpcode16;
5291 m_inst.opcode.inst16 = thumb_opcode;
5292 }
5293 else
5294 {
5295 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005296 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005297 }
5298 }
5299 }
5300 else
5301 {
5302 m_inst_mode = eModeARM;
5303 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005304 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005305 }
5306 }
5307 }
5308 if (!success)
5309 {
5310 m_inst_mode = eModeInvalid;
5311 m_inst_pc = LLDB_INVALID_ADDRESS;
5312 }
5313 return success;
5314}
5315
Johnny Chenee9b1f72011-02-09 01:00:31 +00005316uint32_t
5317EmulateInstructionARM::ArchVersion ()
5318{
5319 return m_arm_isa;
5320}
5321
Greg Clayton64c84432011-01-21 22:02:52 +00005322bool
5323EmulateInstructionARM::ConditionPassed ()
5324{
5325 if (m_inst_cpsr == 0)
5326 return false;
5327
5328 const uint32_t cond = CurrentCond ();
5329
5330 if (cond == UINT32_MAX)
5331 return false;
5332
5333 bool result = false;
5334 switch (UnsignedBits(cond, 3, 1))
5335 {
5336 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
5337 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
5338 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
5339 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
5340 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
5341 case 5:
5342 {
5343 bool n = (m_inst_cpsr & MASK_CPSR_N);
5344 bool v = (m_inst_cpsr & MASK_CPSR_V);
5345 result = n == v;
5346 }
5347 break;
5348 case 6:
5349 {
5350 bool n = (m_inst_cpsr & MASK_CPSR_N);
5351 bool v = (m_inst_cpsr & MASK_CPSR_V);
5352 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
5353 }
5354 break;
5355 case 7:
5356 result = true;
5357 break;
5358 }
5359
5360 if (cond & 1)
5361 result = !result;
5362 return result;
5363}
5364
Johnny Chen9ee056b2011-02-08 00:06:35 +00005365uint32_t
5366EmulateInstructionARM::CurrentCond ()
5367{
5368 switch (m_inst_mode)
5369 {
5370 default:
5371 case eModeInvalid:
5372 break;
5373
5374 case eModeARM:
5375 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
5376
5377 case eModeThumb:
5378 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
5379 // 'cond' field of the encoding.
5380 if (m_inst.opcode_type == eOpcode16 &&
5381 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
5382 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
5383 {
5384 return Bits32(m_inst.opcode.inst16, 11, 7);
5385 }
5386 else if (m_inst.opcode_type == eOpcode32 &&
5387 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
5388 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
5389 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
5390 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
5391 {
5392 return Bits32(m_inst.opcode.inst32, 25, 22);
5393 }
5394
5395 return m_it_session.GetCond();
5396 }
5397 return UINT32_MAX; // Return invalid value
5398}
5399
Johnny Chen9ee056b2011-02-08 00:06:35 +00005400bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00005401EmulateInstructionARM::InITBlock()
5402{
5403 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
5404}
5405
5406bool
5407EmulateInstructionARM::LastInITBlock()
5408{
5409 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
5410}
5411
5412bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00005413EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
5414{
5415 addr_t target;
5416
Johnny Chenee9b1f72011-02-09 01:00:31 +00005417 // Check the current instruction set.
5418 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005419 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005420 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00005421 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005422
Johnny Chen9ee056b2011-02-08 00:06:35 +00005423 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005424 return false;
5425
5426 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005427}
5428
5429// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
5430bool
Johnny Chen668b4512011-02-15 21:08:58 +00005431EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005432{
5433 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00005434 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
5435 // we want to record it and issue a WriteRegister callback so the clients
5436 // can track the mode changes accordingly.
5437 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005438
5439 if (BitIsSet(addr, 0))
5440 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005441 if (CurrentInstrSet() != eModeThumb)
5442 {
5443 SelectInstrSet(eModeThumb);
5444 cpsr_changed = true;
5445 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005446 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00005447 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005448 }
5449 else if (BitIsClear(addr, 1))
5450 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005451 if (CurrentInstrSet() != eModeARM)
5452 {
5453 SelectInstrSet(eModeARM);
5454 cpsr_changed = true;
5455 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005456 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00005457 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005458 }
5459 else
5460 return false; // address<1:0> == '10' => UNPREDICTABLE
5461
Johnny Chen0f309db2011-02-09 19:11:32 +00005462 if (cpsr_changed)
5463 {
Johnny Chen558133b2011-02-09 23:59:17 +00005464 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00005465 return false;
5466 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005467 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005468 return false;
5469
5470 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005471}
Greg Clayton64c84432011-01-21 22:02:52 +00005472
Johnny Chenee9b1f72011-02-09 01:00:31 +00005473// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
5474bool
Johnny Chen668b4512011-02-15 21:08:58 +00005475EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00005476{
5477 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00005478 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00005479 else
5480 return BranchWritePC((const Context)context, addr);
5481}
5482
Johnny Chen26863dc2011-02-09 23:43:29 +00005483// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
5484bool
Johnny Chen668b4512011-02-15 21:08:58 +00005485EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00005486{
5487 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00005488 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00005489 else
5490 return BranchWritePC((const Context)context, addr);
5491}
5492
Johnny Chenee9b1f72011-02-09 01:00:31 +00005493EmulateInstructionARM::Mode
5494EmulateInstructionARM::CurrentInstrSet ()
5495{
5496 return m_inst_mode;
5497}
5498
5499// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00005500// ReadInstruction() is performed. This function has a side effect of updating
5501// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00005502bool
5503EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
5504{
Johnny Chen558133b2011-02-09 23:59:17 +00005505 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005506 switch (arm_or_thumb)
5507 {
5508 default:
5509 return false;
5510 eModeARM:
5511 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005512 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005513 break;
5514 eModeThumb:
5515 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005516 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005517 break;
5518 }
5519 return true;
5520}
5521
Johnny Chenef21b592011-02-10 01:52:38 +00005522// This function returns TRUE if the processor currently provides support for
5523// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
5524// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
5525bool
5526EmulateInstructionARM::UnalignedSupport()
5527{
5528 return (ArchVersion() >= ARMv7);
5529}
5530
Johnny Chenbf6ad172011-02-11 01:29:53 +00005531// The main addition and subtraction instructions can produce status information
5532// about both unsigned carry and signed overflow conditions. This status
5533// information can be used to synthesize multi-word additions and subtractions.
5534EmulateInstructionARM::AddWithCarryResult
5535EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
5536{
5537 uint32_t result;
5538 uint8_t carry_out;
5539 uint8_t overflow;
5540
5541 uint64_t unsigned_sum = x + y + carry_in;
5542 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
5543
5544 result = UnsignedBits(unsigned_sum, 31, 0);
5545 carry_out = (result == unsigned_sum ? 0 : 1);
5546 overflow = ((int32_t)result == signed_sum ? 0 : 1);
5547
5548 AddWithCarryResult res = { result, carry_out, overflow };
5549 return res;
5550}
5551
Johnny Chenca67d1c2011-02-17 01:35:27 +00005552// Write the result to the ARM core register Rd, and optionally update the
5553// condition flags based on the result.
5554//
5555// This helper method tries to encapsulate the following pseudocode from the
5556// ARM Architecture Reference Manual:
5557//
5558// if d == 15 then // Can only occur for encoding A1
5559// ALUWritePC(result); // setflags is always FALSE here
5560// else
5561// R[d] = result;
5562// if setflags then
5563// APSR.N = result<31>;
5564// APSR.Z = IsZeroBit(result);
5565// APSR.C = carry;
5566// // APSR.V unchanged
5567//
5568// In the above case, the API client does not pass in the overflow arg, which
5569// defaults to ~0u.
5570bool
Johnny Chen10530c22011-02-17 22:37:12 +00005571EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
5572 const uint32_t result,
5573 const uint32_t Rd,
5574 bool setflags,
5575 const uint32_t carry,
5576 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00005577{
5578 if (Rd == 15)
5579 {
5580 if (!ALUWritePC (context, result))
5581 return false;
5582 }
5583 else
5584 {
5585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
5586 return false;
5587 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00005588 return WriteFlags (context, result, carry, overflow);
5589 }
5590 return true;
5591}
5592
5593// This helper method tries to encapsulate the following pseudocode from the
5594// ARM Architecture Reference Manual:
5595//
5596// APSR.N = result<31>;
5597// APSR.Z = IsZeroBit(result);
5598// APSR.C = carry;
5599// APSR.V = overflow
5600//
5601// Default arguments can be specified for carry and overflow parameters, which means
5602// not to update the respective flags.
5603bool
5604EmulateInstructionARM::WriteFlags (Context &context,
5605 const uint32_t result,
5606 const uint32_t carry,
5607 const uint32_t overflow)
5608{
5609 m_new_inst_cpsr = m_inst_cpsr;
5610 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
5611 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
5612 if (carry != ~0u)
5613 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
5614 if (overflow != ~0u)
5615 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
5616 if (m_new_inst_cpsr != m_inst_cpsr)
5617 {
5618 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
5619 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00005620 }
5621 return true;
5622}
5623
Greg Clayton64c84432011-01-21 22:02:52 +00005624bool
5625EmulateInstructionARM::EvaluateInstruction ()
5626{
Johnny Chenc315f862011-02-05 00:46:10 +00005627 // Advance the ITSTATE bits to their values for the next instruction.
5628 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
5629 m_it_session.ITAdvance();
5630
Greg Clayton64c84432011-01-21 22:02:52 +00005631 return false;
5632}