blob: 015a4b5e32a99942838b55eba68db8c938dc8cc7 [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
Johnny Chen8fa20592011-02-18 01:22:22 +00001962 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00001963 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00001964 if (!success)
1965 return false;
1966
1967 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1968
1969 EmulateInstruction::Context context;
1970 context.type = EmulateInstruction::eContextImmediate;
1971 context.SetNoArgs ();
1972
1973 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1974 return false;
1975 }
1976 return true;
1977}
1978
Johnny Chend761dcf2011-02-17 22:03:29 +00001979// This instruction adds a register value and an optionally-shifted register value, and writes the result
1980// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001981bool
Johnny Chen9f687722011-02-18 00:02:28 +00001982EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001983{
1984#if 0
1985 // ARM pseudo code...
1986 if ConditionPassed() then
1987 EncodingSpecificOperations();
1988 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1989 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
1990 if d == 15 then
1991 ALUWritePC(result); // setflags is always FALSE here
1992 else
1993 R[d] = result;
1994 if setflags then
1995 APSR.N = result<31>;
1996 APSR.Z = IsZeroBit(result);
1997 APSR.C = carry;
1998 APSR.V = overflow;
1999#endif
2000
2001 bool success = false;
2002 const uint32_t opcode = OpcodeAsUnsigned (&success);
2003 if (!success)
2004 return false;
2005
2006 if (ConditionPassed())
2007 {
2008 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002009 ARM_ShifterType shift_t;
2010 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002011 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002012 switch (encoding)
2013 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002014 case eEncodingT1:
2015 Rd = Bits32(opcode, 2, 0);
2016 Rn = Bits32(opcode, 5, 3);
2017 Rm = Bits32(opcode, 8, 6);
2018 setflags = !InITBlock();
2019 shift_t = SRType_LSL;
2020 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002021 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002022 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002023 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002024 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002025 shift_t = SRType_LSL;
2026 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002027 if (Rn == 15 && Rm == 15)
2028 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002029 if (Rd == 15 && InITBlock() && !LastInITBlock())
2030 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002031 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002032 case eEncodingA1:
2033 Rd = Bits32(opcode, 15, 12);
2034 Rn = Bits32(opcode, 19, 16);
2035 Rm = Bits32(opcode, 3, 0);
2036 setflags = BitIsSet(opcode, 20);
2037 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2038 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002039 default:
2040 return false;
2041 }
2042
Johnny Chen26863dc2011-02-09 23:43:29 +00002043 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002044 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002045 if (!success)
2046 return false;
2047
2048 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002049 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002050 if (!success)
2051 return false;
2052
Johnny Chene97c0d52011-02-18 19:32:20 +00002053 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002054 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002055
2056 EmulateInstruction::Context context;
2057 context.type = EmulateInstruction::eContextImmediate;
2058 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002059
Johnny Chen10530c22011-02-17 22:37:12 +00002060 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002061 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002062 }
2063 return true;
2064}
2065
Johnny Chene4a4d302011-02-11 21:53:58 +00002066// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002067bool
Johnny Chen9f687722011-02-18 00:02:28 +00002068EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002069{
2070#if 0
2071 // ARM pseudo code...
2072 if ConditionPassed() then
2073 EncodingSpecificOperations();
2074 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2075 APSR.N = result<31>;
2076 APSR.Z = IsZeroBit(result);
2077 APSR.C = carry;
2078 APSR.V = overflow;
2079#endif
2080
2081 bool success = false;
2082 const uint32_t opcode = OpcodeAsUnsigned (&success);
2083 if (!success)
2084 return false;
2085
2086 uint32_t Rn; // the first operand
2087 uint32_t imm32; // the immediate value to be compared with
2088 switch (encoding) {
2089 case eEncodingT1:
2090 Rn = Bits32(opcode, 10, 8);
2091 imm32 = Bits32(opcode, 7, 0);
2092 break;
2093 default:
2094 return false;
2095 }
2096 // Read the register value from the operand register Rn.
2097 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2098 if (!success)
2099 return false;
2100
Johnny Chen10530c22011-02-17 22:37:12 +00002101 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2102
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002103 EmulateInstruction::Context context;
2104 context.type = EmulateInstruction::eContextImmediate;
2105 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002106 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2107 return false;
2108
Johnny Chend4dc4442011-02-11 02:02:56 +00002109 return true;
2110}
2111
Johnny Chene4a4d302011-02-11 21:53:58 +00002112// CMP (register)
2113bool
Johnny Chen9f687722011-02-18 00:02:28 +00002114EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002115{
2116#if 0
2117 // ARM pseudo code...
2118 if ConditionPassed() then
2119 EncodingSpecificOperations();
2120 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2121 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2122 APSR.N = result<31>;
2123 APSR.Z = IsZeroBit(result);
2124 APSR.C = carry;
2125 APSR.V = overflow;
2126#endif
2127
2128 bool success = false;
2129 const uint32_t opcode = OpcodeAsUnsigned (&success);
2130 if (!success)
2131 return false;
2132
2133 uint32_t Rn; // the first operand
2134 uint32_t Rm; // the second operand
2135 switch (encoding) {
2136 case eEncodingT1:
2137 Rn = Bits32(opcode, 2, 0);
2138 Rm = Bits32(opcode, 5, 3);
2139 break;
2140 case eEncodingT2:
2141 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2142 Rm = Bits32(opcode, 6, 3);
2143 if (Rn < 8 && Rm < 8)
2144 return false;
2145 if (Rn == 15 || Rm == 15)
2146 return false;
2147 break;
2148 default:
2149 return false;
2150 }
2151 // Read the register value from register Rn.
2152 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2153 if (!success)
2154 return false;
2155 // Read the register value from register Rm.
2156 // The register value is not being shifted since we don't handle ARM for now.
2157 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2158 if (!success)
2159 return false;
2160
Johnny Chen10530c22011-02-17 22:37:12 +00002161 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2162
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002163 EmulateInstruction::Context context;
2164 context.type = EmulateInstruction::eContextImmediate;
2165 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002166 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2167 return false;
2168
Johnny Chene4a4d302011-02-11 21:53:58 +00002169 return true;
2170}
2171
Johnny Chen82f16aa2011-02-15 20:10:55 +00002172// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2173// shifting in copies of its sign bit, and writes the result to the destination register. It can
2174// optionally update the condition flags based on the result.
2175bool
2176EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2177{
2178#if 0
2179 // ARM pseudo code...
2180 if ConditionPassed() then
2181 EncodingSpecificOperations();
2182 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2183 if d == 15 then // Can only occur for ARM encoding
2184 ALUWritePC(result); // setflags is always FALSE here
2185 else
2186 R[d] = result;
2187 if setflags then
2188 APSR.N = result<31>;
2189 APSR.Z = IsZeroBit(result);
2190 APSR.C = carry;
2191 // APSR.V unchanged
2192#endif
2193
Johnny Chen41a0a152011-02-16 01:27:54 +00002194 return EmulateShiftImm(encoding, SRType_ASR);
2195}
2196
2197// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2198// shifting in copies of its sign bit, and writes the result to the destination register.
2199// The variable number of bits is read from the bottom byte of a register. It can optionally update
2200// the condition flags based on the result.
2201bool
2202EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2203{
2204#if 0
2205 // ARM pseudo code...
2206 if ConditionPassed() then
2207 EncodingSpecificOperations();
2208 shift_n = UInt(R[m]<7:0>);
2209 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2210 R[d] = result;
2211 if setflags then
2212 APSR.N = result<31>;
2213 APSR.Z = IsZeroBit(result);
2214 APSR.C = carry;
2215 // APSR.V unchanged
2216#endif
2217
2218 return EmulateShiftReg(encoding, SRType_ASR);
2219}
2220
2221// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2222// shifting in zeros, and writes the result to the destination register. It can optionally
2223// update the condition flags based on the result.
2224bool
2225EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2226{
2227#if 0
2228 // ARM pseudo code...
2229 if ConditionPassed() then
2230 EncodingSpecificOperations();
2231 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2232 if d == 15 then // Can only occur for ARM encoding
2233 ALUWritePC(result); // setflags is always FALSE here
2234 else
2235 R[d] = result;
2236 if setflags then
2237 APSR.N = result<31>;
2238 APSR.Z = IsZeroBit(result);
2239 APSR.C = carry;
2240 // APSR.V unchanged
2241#endif
2242
2243 return EmulateShiftImm(encoding, SRType_LSL);
2244}
2245
2246// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2247// shifting in zeros, and writes the result to the destination register. The variable number
2248// of bits is read from the bottom byte of a register. It can optionally update the condition
2249// flags based on the result.
2250bool
2251EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2252{
2253#if 0
2254 // ARM pseudo code...
2255 if ConditionPassed() then
2256 EncodingSpecificOperations();
2257 shift_n = UInt(R[m]<7:0>);
2258 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2259 R[d] = result;
2260 if setflags then
2261 APSR.N = result<31>;
2262 APSR.Z = IsZeroBit(result);
2263 APSR.C = carry;
2264 // APSR.V unchanged
2265#endif
2266
2267 return EmulateShiftReg(encoding, SRType_LSL);
2268}
2269
2270// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2271// shifting in zeros, and writes the result to the destination register. It can optionally
2272// update the condition flags based on the result.
2273bool
2274EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2275{
2276#if 0
2277 // ARM pseudo code...
2278 if ConditionPassed() then
2279 EncodingSpecificOperations();
2280 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2281 if d == 15 then // Can only occur for ARM encoding
2282 ALUWritePC(result); // setflags is always FALSE here
2283 else
2284 R[d] = result;
2285 if setflags then
2286 APSR.N = result<31>;
2287 APSR.Z = IsZeroBit(result);
2288 APSR.C = carry;
2289 // APSR.V unchanged
2290#endif
2291
2292 return EmulateShiftImm(encoding, SRType_LSR);
2293}
2294
2295// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2296// shifting in zeros, and writes the result to the destination register. The variable number
2297// of bits is read from the bottom byte of a register. It can optionally update the condition
2298// flags based on the result.
2299bool
2300EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2301{
2302#if 0
2303 // ARM pseudo code...
2304 if ConditionPassed() then
2305 EncodingSpecificOperations();
2306 shift_n = UInt(R[m]<7:0>);
2307 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2308 R[d] = result;
2309 if setflags then
2310 APSR.N = result<31>;
2311 APSR.Z = IsZeroBit(result);
2312 APSR.C = carry;
2313 // APSR.V unchanged
2314#endif
2315
2316 return EmulateShiftReg(encoding, SRType_LSR);
2317}
2318
Johnny Cheneeab4852011-02-16 22:14:44 +00002319// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2320// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2321// It can optionally update the condition flags based on the result.
2322bool
2323EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2324{
2325#if 0
2326 // ARM pseudo code...
2327 if ConditionPassed() then
2328 EncodingSpecificOperations();
2329 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2330 if d == 15 then // Can only occur for ARM encoding
2331 ALUWritePC(result); // setflags is always FALSE here
2332 else
2333 R[d] = result;
2334 if setflags then
2335 APSR.N = result<31>;
2336 APSR.Z = IsZeroBit(result);
2337 APSR.C = carry;
2338 // APSR.V unchanged
2339#endif
2340
2341 return EmulateShiftImm(encoding, SRType_ROR);
2342}
2343
2344// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2345// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2346// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2347// flags based on the result.
2348bool
2349EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2350{
2351#if 0
2352 // ARM pseudo code...
2353 if ConditionPassed() then
2354 EncodingSpecificOperations();
2355 shift_n = UInt(R[m]<7:0>);
2356 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2357 R[d] = result;
2358 if setflags then
2359 APSR.N = result<31>;
2360 APSR.Z = IsZeroBit(result);
2361 APSR.C = carry;
2362 // APSR.V unchanged
2363#endif
2364
2365 return EmulateShiftReg(encoding, SRType_ROR);
2366}
2367
2368// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2369// with the carry flag shifted into bit [31].
2370//
2371// RRX can optionally update the condition flags based on the result.
2372// In that case, bit [0] is shifted into the carry flag.
2373bool
2374EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2375{
2376#if 0
2377 // ARM pseudo code...
2378 if ConditionPassed() then
2379 EncodingSpecificOperations();
2380 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2381 if d == 15 then // Can only occur for ARM encoding
2382 ALUWritePC(result); // setflags is always FALSE here
2383 else
2384 R[d] = result;
2385 if setflags then
2386 APSR.N = result<31>;
2387 APSR.Z = IsZeroBit(result);
2388 APSR.C = carry;
2389 // APSR.V unchanged
2390#endif
2391
2392 return EmulateShiftImm(encoding, SRType_RRX);
2393}
2394
Johnny Chen41a0a152011-02-16 01:27:54 +00002395bool
2396EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2397{
2398 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2399
Johnny Chen82f16aa2011-02-15 20:10:55 +00002400 bool success = false;
2401 const uint32_t opcode = OpcodeAsUnsigned (&success);
2402 if (!success)
2403 return false;
2404
2405 if (ConditionPassed())
2406 {
Johnny Chene7f89532011-02-15 23:22:46 +00002407 uint32_t Rd; // the destination register
2408 uint32_t Rm; // the first operand register
2409 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002410 uint32_t carry; // the carry bit after the shift operation
2411 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002412
2413 // Special case handling!
2414 // A8.6.139 ROR (immediate) -- Encoding T1
2415 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2416 {
2417 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2418 // have the same decoding of bit fields as the other Thumb2 shift operations.
2419 encoding = eEncodingT2;
2420 }
2421
Johnny Chen82f16aa2011-02-15 20:10:55 +00002422 switch (encoding) {
2423 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002424 // Due to the above special case handling!
2425 assert(shift_type != SRType_ROR);
2426
Johnny Chen82f16aa2011-02-15 20:10:55 +00002427 Rd = Bits32(opcode, 2, 0);
2428 Rm = Bits32(opcode, 5, 3);
2429 setflags = !InITBlock();
2430 imm5 = Bits32(opcode, 10, 6);
2431 break;
2432 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002433 // A8.6.141 RRX
2434 assert(shift_type != SRType_RRX);
2435
Johnny Chen82f16aa2011-02-15 20:10:55 +00002436 Rd = Bits32(opcode, 11, 8);
2437 Rm = Bits32(opcode, 3, 0);
2438 setflags = BitIsSet(opcode, 20);
2439 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2440 if (BadReg(Rd) || BadReg(Rm))
2441 return false;
2442 break;
2443 case eEncodingA1:
2444 Rd = Bits32(opcode, 15, 12);
2445 Rm = Bits32(opcode, 3, 0);
2446 setflags = BitIsSet(opcode, 20);
2447 imm5 = Bits32(opcode, 11, 7);
2448 break;
2449 default:
2450 return false;
2451 }
2452
Johnny Cheneeab4852011-02-16 22:14:44 +00002453 // A8.6.139 ROR (immediate)
2454 if (shift_type == SRType_ROR && imm5 == 0)
2455 shift_type = SRType_RRX;
2456
Johnny Chen82f16aa2011-02-15 20:10:55 +00002457 // Get the first operand.
2458 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2459 if (!success)
2460 return false;
2461
Johnny Cheneeab4852011-02-16 22:14:44 +00002462 // Decode the shift amount if not RRX.
2463 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002464
Johnny Chene97c0d52011-02-18 19:32:20 +00002465 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002466
2467 // The context specifies that an immediate is to be moved into Rd.
2468 EmulateInstruction::Context context;
2469 context.type = EmulateInstruction::eContextImmediate;
2470 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002471
Johnny Chen10530c22011-02-17 22:37:12 +00002472 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002473 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002474 }
2475 return true;
2476}
2477
Johnny Chene7f89532011-02-15 23:22:46 +00002478bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002479EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002480{
Johnny Chen41a0a152011-02-16 01:27:54 +00002481 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002482
2483 bool success = false;
2484 const uint32_t opcode = OpcodeAsUnsigned (&success);
2485 if (!success)
2486 return false;
2487
2488 if (ConditionPassed())
2489 {
2490 uint32_t Rd; // the destination register
2491 uint32_t Rn; // the first operand register
2492 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2493 uint32_t carry; // the carry bit after the shift operation
2494 bool setflags;
2495 switch (encoding) {
2496 case eEncodingT1:
2497 Rd = Bits32(opcode, 2, 0);
2498 Rn = Rd;
2499 Rm = Bits32(opcode, 5, 3);
2500 setflags = !InITBlock();
2501 break;
2502 case eEncodingT2:
2503 Rd = Bits32(opcode, 11, 8);
2504 Rn = Bits32(opcode, 19, 16);
2505 Rm = Bits32(opcode, 3, 0);
2506 setflags = BitIsSet(opcode, 20);
2507 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2508 return false;
2509 break;
2510 case eEncodingA1:
2511 Rd = Bits32(opcode, 15, 12);
2512 Rn = Bits32(opcode, 3, 0);
2513 Rm = Bits32(opcode, 11, 8);
2514 setflags = BitIsSet(opcode, 20);
2515 if (Rd == 15 || Rn == 15 || Rm == 15)
2516 return false;
2517 break;
2518 default:
2519 return false;
2520 }
2521
2522 // Get the first operand.
2523 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2524 if (!success)
2525 return false;
2526 // Get the Rm register content.
2527 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2528 if (!success)
2529 return false;
2530
2531 // Get the shift amount.
2532 uint32_t amt = Bits32(val, 7, 0);
2533
Johnny Chene97c0d52011-02-18 19:32:20 +00002534 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002535
2536 // The context specifies that an immediate is to be moved into Rd.
2537 EmulateInstruction::Context context;
2538 context.type = EmulateInstruction::eContextImmediate;
2539 context.SetNoArgs ();
2540
Johnny Chen10530c22011-02-17 22:37:12 +00002541 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002542 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002543 }
2544 return true;
2545}
2546
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002547// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002548// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002549// can be written back to the base register.
2550bool
2551EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2552{
2553#if 0
2554 // ARM pseudo code...
2555 if ConditionPassed()
2556 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2557 address = R[n];
2558
2559 for i = 0 to 14
2560 if registers<i> == '1' then
2561 R[i] = MemA[address, 4]; address = address + 4;
2562 if registers<15> == '1' then
2563 LoadWritePC (MemA[address, 4]);
2564
2565 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2566 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2567
2568#endif
2569
2570 bool success = false;
2571 const uint32_t opcode = OpcodeAsUnsigned (&success);
2572 if (!success)
2573 return false;
2574
2575 if (ConditionPassed())
2576 {
2577 uint32_t n;
2578 uint32_t registers = 0;
2579 bool wback;
2580 const uint32_t addr_byte_size = GetAddressByteSize();
2581 switch (encoding)
2582 {
2583 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002584 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002585 n = Bits32 (opcode, 10, 8);
2586 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002587 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002588 wback = BitIsClear (registers, n);
2589 // if BitCount(registers) < 1 then UNPREDICTABLE;
2590 if (BitCount(registers) < 1)
2591 return false;
2592 break;
2593 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002594 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2595 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002596 n = Bits32 (opcode, 19, 16);
2597 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002598 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002599 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002600
2601 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002602 if ((n == 15)
2603 || (BitCount (registers) < 2)
2604 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2605 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002606
2607 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002608 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002609 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002610
2611 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002612 if (wback
2613 && BitIsSet (registers, n))
2614 return false;
2615 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002616
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002617 case eEncodingA1:
2618 n = Bits32 (opcode, 19, 16);
2619 registers = Bits32 (opcode, 15, 0);
2620 wback = BitIsSet (opcode, 21);
2621 if ((n == 15)
2622 || (BitCount (registers) < 1))
2623 return false;
2624 break;
2625 default:
2626 return false;
2627 }
2628
2629 int32_t offset = 0;
2630 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2631 if (!success)
2632 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002633
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002634 EmulateInstruction::Context context;
2635 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2636 Register dwarf_reg;
2637 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2638 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002639
2640 for (int i = 0; i < 14; ++i)
2641 {
2642 if (BitIsSet (registers, i))
2643 {
Caroline Tice85aab332011-02-08 23:56:10 +00002644 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002645 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002646 if (wback && (n == 13)) // Pop Instruction
2647 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2648
2649 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002650 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002651 if (!success)
2652 return false;
2653
2654 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2655 return false;
2656
2657 offset += addr_byte_size;
2658 }
2659 }
2660
2661 if (BitIsSet (registers, 15))
2662 {
2663 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002664 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002665 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002666 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002667 if (!success)
2668 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002669 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002670 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002671 return false;
2672 }
2673
2674 if (wback && BitIsClear (registers, n))
2675 {
Caroline Ticefa172202011-02-11 22:49:54 +00002676 // R[n] = R[n] + 4 * BitCount (registers)
2677 int32_t offset = addr_byte_size * BitCount (registers);
2678 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002679 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002680
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002681 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2682 return false;
2683 }
2684 if (wback && BitIsSet (registers, n))
2685 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002686 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002687 }
2688 return true;
2689}
Caroline Tice713c2662011-02-11 17:59:55 +00002690
2691// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2692// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2693// can optionally be written back tot he base registers.
2694bool
2695EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2696{
2697#if 0
2698 // ARM pseudo code...
2699 if ConditionPassed() then
2700 EncodingSpecificOperations();
2701 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002702
Caroline Tice713c2662011-02-11 17:59:55 +00002703 for i = 0 to 14
2704 if registers<i> == ’1’ then
2705 R[i] = MemA[address,4]; address = address + 4;
2706
2707 if registers<15> == ’1’ then
2708 LoadWritePC(MemA[address,4]);
2709
2710 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2711 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2712#endif
2713
2714 bool success = false;
2715 const uint32_t opcode = OpcodeAsUnsigned (&success);
2716 if (!success)
2717 return false;
2718
2719 if (ConditionPassed())
2720 {
2721 uint32_t n;
2722 uint32_t registers = 0;
2723 bool wback;
2724 const uint32_t addr_byte_size = GetAddressByteSize();
2725
2726 // EncodingSpecificOperations();
2727 switch (encoding)
2728 {
2729 case eEncodingA1:
2730 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2731 n = Bits32 (opcode, 19, 16);
2732 registers = Bits32 (opcode, 15, 0);
2733 wback = BitIsSet (opcode, 21);
2734
2735 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2736 if ((n == 15) || (BitCount (registers) < 1))
2737 return false;
2738
2739 break;
2740
2741 default:
2742 return false;
2743 }
2744 // address = R[n] - 4*BitCount(registers) + 4;
2745
2746 int32_t offset = 0;
2747 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2748
2749 if (!success)
2750 return false;
2751
2752 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2753
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002754 EmulateInstruction::Context context;
2755 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2756 Register dwarf_reg;
2757 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2758 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002759
2760 // for i = 0 to 14
2761 for (int i = 0; i < 14; ++i)
2762 {
2763 // if registers<i> == ’1’ then
2764 if (BitIsSet (registers, i))
2765 {
2766 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002767 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002768 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002769 if (!success)
2770 return false;
2771 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2772 return false;
2773 offset += addr_byte_size;
2774 }
2775 }
2776
2777 // if registers<15> == ’1’ then
2778 // LoadWritePC(MemA[address,4]);
2779 if (BitIsSet (registers, 15))
2780 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002781 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002782 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002783 if (!success)
2784 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002785 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002786 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002787 return false;
2788 }
2789
2790 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2791 if (wback && BitIsClear (registers, n))
2792 {
Caroline Tice713c2662011-02-11 17:59:55 +00002793 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2794 if (!success)
2795 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002796
2797 offset = (addr_byte_size * BitCount (registers)) * -1;
2798 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002799 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002800 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002801 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2802 return false;
2803 }
2804
2805 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2806 if (wback && BitIsSet (registers, n))
2807 return WriteBits32Unknown (n);
2808 }
2809 return true;
2810}
2811
2812// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2813// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2814// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002815bool
2816EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2817{
2818#if 0
2819 // ARM pseudo code...
2820 if ConditionPassed() then
2821 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2822 address = R[n] - 4*BitCount(registers);
2823
2824 for i = 0 to 14
2825 if registers<i> == ’1’ then
2826 R[i] = MemA[address,4]; address = address + 4;
2827 if registers<15> == ’1’ then
2828 LoadWritePC(MemA[address,4]);
2829
2830 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2831 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2832#endif
2833
2834 bool success = false;
2835 const uint32_t opcode = OpcodeAsUnsigned (&success);
2836 if (!success)
2837 return false;
2838
2839 if (ConditionPassed())
2840 {
2841 uint32_t n;
2842 uint32_t registers = 0;
2843 bool wback;
2844 const uint32_t addr_byte_size = GetAddressByteSize();
2845 switch (encoding)
2846 {
2847 case eEncodingT1:
2848 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2849 n = Bits32 (opcode, 19, 16);
2850 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002851 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002852 wback = BitIsSet (opcode, 21);
2853
2854 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2855 if ((n == 15)
2856 || (BitCount (registers) < 2)
2857 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2858 return false;
2859
2860 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002861 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002862 return false;
2863
2864 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2865 if (wback && BitIsSet (registers, n))
2866 return false;
2867
2868 break;
2869
2870 case eEncodingA1:
2871 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2872 n = Bits32 (opcode, 19, 16);
2873 registers = Bits32 (opcode, 15, 0);
2874 wback = BitIsSet (opcode, 21);
2875
2876 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2877 if ((n == 15) || (BitCount (registers) < 1))
2878 return false;
2879
2880 break;
2881
2882 default:
2883 return false;
2884 }
2885
Caroline Tice713c2662011-02-11 17:59:55 +00002886 // address = R[n] - 4*BitCount(registers);
2887
Caroline Tice0b29e242011-02-08 23:16:02 +00002888 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002889 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2890
2891 if (!success)
2892 return false;
2893
2894 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002895 EmulateInstruction::Context context;
2896 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2897 Register dwarf_reg;
2898 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2899 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002900
2901 for (int i = 0; i < 14; ++i)
2902 {
2903 if (BitIsSet (registers, i))
2904 {
2905 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002906 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002907 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002908 if (!success)
2909 return false;
2910
2911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2912 return false;
2913
2914 offset += addr_byte_size;
2915 }
2916 }
2917
2918 // if registers<15> == ’1’ then
2919 // LoadWritePC(MemA[address,4]);
2920 if (BitIsSet (registers, 15))
2921 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002922 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002923 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002924 if (!success)
2925 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002926 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002927 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002928 return false;
2929 }
2930
2931 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2932 if (wback && BitIsClear (registers, n))
2933 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002934 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2935 if (!success)
2936 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002937
2938 offset = (addr_byte_size * BitCount (registers)) * -1;
2939 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002940 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002941 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002942 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2943 return false;
2944 }
2945
2946 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2947 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002948 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002949 }
2950 return true;
2951}
Caroline Tice85aab332011-02-08 23:56:10 +00002952
Caroline Tice713c2662011-02-11 17:59:55 +00002953// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2954// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2955// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002956bool
2957EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2958{
2959#if 0
2960 if ConditionPassed() then
2961 EncodingSpecificOperations();
2962 address = R[n] + 4;
2963
2964 for i = 0 to 14
2965 if registers<i> == ’1’ then
2966 R[i] = MemA[address,4]; address = address + 4;
2967 if registers<15> == ’1’ then
2968 LoadWritePC(MemA[address,4]);
2969
2970 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2971 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2972#endif
2973
2974 bool success = false;
2975 const uint32_t opcode = OpcodeAsUnsigned (&success);
2976 if (!success)
2977 return false;
2978
2979 if (ConditionPassed())
2980 {
2981 uint32_t n;
2982 uint32_t registers = 0;
2983 bool wback;
2984 const uint32_t addr_byte_size = GetAddressByteSize();
2985 switch (encoding)
2986 {
2987 case eEncodingA1:
2988 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2989 n = Bits32 (opcode, 19, 16);
2990 registers = Bits32 (opcode, 15, 0);
2991 wback = BitIsSet (opcode, 21);
2992
2993 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2994 if ((n == 15) || (BitCount (registers) < 1))
2995 return false;
2996
2997 break;
2998 default:
2999 return false;
3000 }
3001 // address = R[n] + 4;
3002
3003 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003004 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3005
3006 if (!success)
3007 return false;
3008
3009 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003010
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003011 EmulateInstruction::Context context;
3012 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3013 Register dwarf_reg;
3014 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3015 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003016
3017 for (int i = 0; i < 14; ++i)
3018 {
3019 if (BitIsSet (registers, i))
3020 {
3021 // R[i] = MemA[address,4]; address = address + 4;
3022
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003023 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003024 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003025 if (!success)
3026 return false;
3027
3028 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3029 return false;
3030
3031 offset += addr_byte_size;
3032 }
3033 }
3034
3035 // if registers<15> == ’1’ then
3036 // LoadWritePC(MemA[address,4]);
3037 if (BitIsSet (registers, 15))
3038 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003039 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003040 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003041 if (!success)
3042 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003043 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003044 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003045 return false;
3046 }
3047
3048 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3049 if (wback && BitIsClear (registers, n))
3050 {
Caroline Tice85aab332011-02-08 23:56:10 +00003051 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3052 if (!success)
3053 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003054
3055 offset = addr_byte_size * BitCount (registers);
3056 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003057 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003058 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003059 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3060 return false;
3061 }
3062
3063 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3064 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003065 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003066 }
3067 return true;
3068}
Caroline Tice0b29e242011-02-08 23:16:02 +00003069
Johnny Chenef21b592011-02-10 01:52:38 +00003070// Load Register (immediate) calculates an address from a base register value and
3071// an immediate offset, loads a word from memory, and writes to a register.
3072// LDR (immediate, Thumb)
3073bool
3074EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3075{
3076#if 0
3077 // ARM pseudo code...
3078 if (ConditionPassed())
3079 {
3080 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3081 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3082 address = if index then offset_addr else R[n];
3083 data = MemU[address,4];
3084 if wback then R[n] = offset_addr;
3085 if t == 15 then
3086 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3087 elsif UnalignedSupport() || address<1:0> = '00' then
3088 R[t] = data;
3089 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3090 }
3091#endif
3092
3093 bool success = false;
3094 const uint32_t opcode = OpcodeAsUnsigned (&success);
3095 if (!success)
3096 return false;
3097
3098 if (ConditionPassed())
3099 {
3100 uint32_t Rt; // the destination register
3101 uint32_t Rn; // the base register
3102 uint32_t imm32; // the immediate offset used to form the address
3103 addr_t offset_addr; // the offset address
3104 addr_t address; // the calculated address
3105 uint32_t data; // the literal data value from memory load
3106 bool add, index, wback;
3107 switch (encoding) {
3108 case eEncodingT1:
3109 Rt = Bits32(opcode, 5, 3);
3110 Rn = Bits32(opcode, 2, 0);
3111 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3112 // index = TRUE; add = TRUE; wback = FALSE
3113 add = true;
3114 index = true;
3115 wback = false;
3116 break;
3117 default:
3118 return false;
3119 }
3120 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3121 if (!success)
3122 return false;
3123 if (add)
3124 offset_addr = base + imm32;
3125 else
3126 offset_addr = base - imm32;
3127
3128 address = (index ? offset_addr : base);
3129
3130 if (wback)
3131 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003132 EmulateInstruction::Context ctx;
3133 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3134 Register dwarf_reg;
3135 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3136 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3137
Johnny Chenef21b592011-02-10 01:52:38 +00003138 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3139 return false;
3140 }
3141
3142 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003143 EmulateInstruction::Context context;
3144 context.type = EmulateInstruction::eContextImmediate;
3145 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003146
3147 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003148 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003149 if (!success)
3150 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003151
3152 if (Rt == 15)
3153 {
3154 if (Bits32(address, 1, 0) == 0)
3155 {
Johnny Chen668b4512011-02-15 21:08:58 +00003156 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003157 return false;
3158 }
3159 else
3160 return false;
3161 }
3162 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3163 {
3164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3165 return false;
3166 }
3167 else
3168 return false;
3169 }
3170 return true;
3171}
3172
Caroline Ticeaf556562011-02-15 18:42:15 +00003173// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3174// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3175// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003176bool
3177EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3178{
3179#if 0
3180 if ConditionPassed() then
3181 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3182 address = R[n];
3183
3184 for i = 0 to 14
3185 if registers<i> == ’1’ then
3186 if i == n && wback && i != LowestSetBit(registers) then
3187 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3188 else
3189 MemA[address,4] = R[i];
3190 address = address + 4;
3191
3192 if registers<15> == ’1’ then // Only possible for encoding A1
3193 MemA[address,4] = PCStoreValue();
3194 if wback then R[n] = R[n] + 4*BitCount(registers);
3195#endif
3196
3197 bool success = false;
3198 const uint32_t opcode = OpcodeAsUnsigned (&success);
3199 if (!success)
3200 return false;
3201
3202 if (ConditionPassed ())
3203 {
3204 uint32_t n;
3205 uint32_t registers = 0;
3206 bool wback;
3207 const uint32_t addr_byte_size = GetAddressByteSize();
3208
3209 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3210 switch (encoding)
3211 {
3212 case eEncodingT1:
3213 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3214 n = Bits32 (opcode, 10, 8);
3215 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003216 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003217 wback = true;
3218
3219 // if BitCount(registers) < 1 then UNPREDICTABLE;
3220 if (BitCount (registers) < 1)
3221 return false;
3222
3223 break;
3224
3225 case eEncodingT2:
3226 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3227 n = Bits32 (opcode, 19, 16);
3228 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003229 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003230 wback = BitIsSet (opcode, 21);
3231
3232 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3233 if ((n == 15) || (BitCount (registers) < 2))
3234 return false;
3235
3236 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3237 if (wback && BitIsSet (registers, n))
3238 return false;
3239
3240 break;
3241
3242 case eEncodingA1:
3243 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3244 n = Bits32 (opcode, 19, 16);
3245 registers = Bits32 (opcode, 15, 0);
3246 wback = BitIsSet (opcode, 21);
3247
3248 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3249 if ((n == 15) || (BitCount (registers) < 1))
3250 return false;
3251
3252 break;
3253
3254 default:
3255 return false;
3256 }
3257
3258 // address = R[n];
3259 int32_t offset = 0;
3260 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3261 if (!success)
3262 return false;
3263
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003264 EmulateInstruction::Context context;
3265 context.type = EmulateInstruction::eContextRegisterStore;
3266 Register base_reg;
3267 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003268
3269 // for i = 0 to 14
3270 for (int i = 0; i < 14; ++i)
3271 {
3272 int lowest_set_bit = 14;
3273 // if registers<i> == ’1’ then
3274 if (BitIsSet (registers, i))
3275 {
3276 if (i < lowest_set_bit)
3277 lowest_set_bit = i;
3278 // if i == n && wback && i != LowestSetBit(registers) then
3279 if ((i == n) && wback && (i != lowest_set_bit))
3280 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3281 WriteBits32UnknownToMemory (address + offset);
3282 else
3283 {
3284 // MemA[address,4] = R[i];
3285 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3286 if (!success)
3287 return false;
3288
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003289 Register data_reg;
3290 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3291 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003292 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003293 return false;
3294 }
3295
3296 // address = address + 4;
3297 offset += addr_byte_size;
3298 }
3299 }
3300
3301 // if registers<15> == ’1’ then // Only possible for encoding A1
3302 // MemA[address,4] = PCStoreValue();
3303 if (BitIsSet (registers, 15))
3304 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003305 Register pc_reg;
3306 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3307 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003308 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3309 if (!success)
3310 return false;
3311
Caroline Ticecc96eb52011-02-17 19:20:40 +00003312 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003313 return false;
3314 }
3315
3316 // if wback then R[n] = R[n] + 4*BitCount(registers);
3317 if (wback)
3318 {
3319 offset = addr_byte_size * BitCount (registers);
3320 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003321 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003322 addr_t data = address + offset;
3323 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3324 return false;
3325 }
3326 }
3327 return true;
3328}
3329
Caroline Ticeaf556562011-02-15 18:42:15 +00003330// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3331// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3332// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003333bool
3334EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3335{
3336#if 0
3337 if ConditionPassed() then
3338 EncodingSpecificOperations();
3339 address = R[n] - 4*BitCount(registers) + 4;
3340
3341 for i = 0 to 14
3342 if registers<i> == ’1’ then
3343 if i == n && wback && i != LowestSetBit(registers) then
3344 MemA[address,4] = bits(32) UNKNOWN;
3345 else
3346 MemA[address,4] = R[i];
3347 address = address + 4;
3348
3349 if registers<15> == ’1’ then
3350 MemA[address,4] = PCStoreValue();
3351
3352 if wback then R[n] = R[n] - 4*BitCount(registers);
3353#endif
3354
3355 bool success = false;
3356 const uint32_t opcode = OpcodeAsUnsigned (&success);
3357 if (!success)
3358 return false;
3359
3360 if (ConditionPassed ())
3361 {
3362 uint32_t n;
3363 uint32_t registers = 0;
3364 bool wback;
3365 const uint32_t addr_byte_size = GetAddressByteSize();
3366
3367 // EncodingSpecificOperations();
3368 switch (encoding)
3369 {
3370 case eEncodingA1:
3371 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3372 n = Bits32 (opcode, 19, 16);
3373 registers = Bits32 (opcode, 15, 0);
3374 wback = BitIsSet (opcode, 21);
3375
3376 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3377 if ((n == 15) || (BitCount (registers) < 1))
3378 return false;
3379 break;
3380 default:
3381 return false;
3382 }
3383
3384 // address = R[n] - 4*BitCount(registers) + 4;
3385 int32_t offset = 0;
3386 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3387 if (!success)
3388 return false;
3389
3390 address = address - (addr_byte_size * BitCount (registers)) + 4;
3391
3392 EmulateInstruction::Context context;
3393 context.type = EmulateInstruction::eContextRegisterStore;
3394 Register base_reg;
3395 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3396
3397 // for i = 0 to 14
3398 for (int i = 0; i < 14; ++i)
3399 {
3400 int lowest_bit_set = 14;
3401 // if registers<i> == ’1’ then
3402 if (BitIsSet (registers, i))
3403 {
3404 if (i < lowest_bit_set)
3405 lowest_bit_set = i;
3406 //if i == n && wback && i != LowestSetBit(registers) then
3407 if ((i == n) && wback && (i != lowest_bit_set))
3408 // MemA[address,4] = bits(32) UNKNOWN;
3409 WriteBits32UnknownToMemory (address + offset);
3410 else
3411 {
3412 // MemA[address,4] = R[i];
3413 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3414 if (!success)
3415 return false;
3416
3417 Register data_reg;
3418 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3419 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003420 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003421 return false;
3422 }
3423
3424 // address = address + 4;
3425 offset += addr_byte_size;
3426 }
3427 }
3428
3429 // if registers<15> == ’1’ then
3430 // MemA[address,4] = PCStoreValue();
3431 if (BitIsSet (registers, 15))
3432 {
3433 Register pc_reg;
3434 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3435 context.SetRegisterPlusOffset (pc_reg, 8);
3436 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3437 if (!success)
3438 return false;
3439
Caroline Ticecc96eb52011-02-17 19:20:40 +00003440 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003441 return false;
3442 }
3443
3444 // if wback then R[n] = R[n] - 4*BitCount(registers);
3445 if (wback)
3446 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003447 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003448 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3449 context.SetImmediateSigned (offset);
3450 addr_t data = address + offset;
3451 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3452 return false;
3453 }
3454 }
3455 return true;
3456}
3457
Caroline Ticeaf556562011-02-15 18:42:15 +00003458// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3459// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3460// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003461bool
3462EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3463{
3464#if 0
3465 if ConditionPassed() then
3466 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3467 address = R[n] - 4*BitCount(registers);
3468
3469 for i = 0 to 14
3470 if registers<i> == ’1’ then
3471 if i == n && wback && i != LowestSetBit(registers) then
3472 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3473 else
3474 MemA[address,4] = R[i];
3475 address = address + 4;
3476
3477 if registers<15> == ’1’ then // Only possible for encoding A1
3478 MemA[address,4] = PCStoreValue();
3479
3480 if wback then R[n] = R[n] - 4*BitCount(registers);
3481#endif
3482
3483
3484 bool success = false;
3485 const uint32_t opcode = OpcodeAsUnsigned (&success);
3486 if (!success)
3487 return false;
3488
3489 if (ConditionPassed ())
3490 {
3491 uint32_t n;
3492 uint32_t registers = 0;
3493 bool wback;
3494 const uint32_t addr_byte_size = GetAddressByteSize();
3495
3496 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3497 switch (encoding)
3498 {
3499 case eEncodingT1:
3500 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3501 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3502 {
3503 // See PUSH
3504 }
3505 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3506 n = Bits32 (opcode, 19, 16);
3507 registers = Bits32 (opcode, 15, 0);
3508 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3509 wback = BitIsSet (opcode, 21);
3510 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3511 if ((n == 15) || BitCount (registers) < 2)
3512 return false;
3513 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3514 if (wback && BitIsSet (registers, n))
3515 return false;
3516 break;
3517
3518 case eEncodingA1:
3519 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3520 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3521 {
3522 // See Push
3523 }
3524 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3525 n = Bits32 (opcode, 19, 16);
3526 registers = Bits32 (opcode, 15, 0);
3527 wback = BitIsSet (opcode, 21);
3528 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3529 if ((n == 15) || BitCount (registers) < 1)
3530 return false;
3531 break;
3532
3533 default:
3534 return false;
3535 }
3536
3537 // address = R[n] - 4*BitCount(registers);
3538
3539 int32_t offset = 0;
3540 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3541 if (!success)
3542 return false;
3543
3544 address = address - (addr_byte_size * BitCount (registers));
3545
3546 EmulateInstruction::Context context;
3547 context.type = EmulateInstruction::eContextRegisterStore;
3548 Register base_reg;
3549 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3550
3551 // for i = 0 to 14
3552 for (int i = 0; i < 14; ++i)
3553 {
3554 uint32_t lowest_set_bit = 14;
3555 // if registers<i> == ’1’ then
3556 if (BitIsSet (registers, i))
3557 {
3558 if (i < lowest_set_bit)
3559 lowest_set_bit = i;
3560 // if i == n && wback && i != LowestSetBit(registers) then
3561 if ((i == n) && wback && (i != lowest_set_bit))
3562 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3563 WriteBits32UnknownToMemory (address + offset);
3564 else
3565 {
3566 // MemA[address,4] = R[i];
3567 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3568 if (!success)
3569 return false;
3570
3571 Register data_reg;
3572 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3573 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003574 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003575 return false;
3576 }
3577
3578 // address = address + 4;
3579 offset += addr_byte_size;
3580 }
3581 }
3582
3583 // if registers<15> == ’1’ then // Only possible for encoding A1
3584 // MemA[address,4] = PCStoreValue();
3585 if (BitIsSet (registers, 15))
3586 {
3587 Register pc_reg;
3588 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3589 context.SetRegisterPlusOffset (pc_reg, 8);
3590 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3591 if (!success)
3592 return false;
3593
Caroline Ticecc96eb52011-02-17 19:20:40 +00003594 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003595 return false;
3596 }
3597
3598 // if wback then R[n] = R[n] - 4*BitCount(registers);
3599 if (wback)
3600 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003601 offset = (addr_byte_size * BitCount (registers)) * -1;
3602 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3603 context.SetImmediateSigned (offset);
3604 addr_t data = address + offset;
3605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3606 return false;
3607 }
3608 }
3609 return true;
3610}
3611
3612// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3613// from a base register. The consecutive memory locations start just above this address, and the address of the last
3614// of those locations can optionally be written back to the base register.
3615bool
3616EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3617{
3618#if 0
3619 if ConditionPassed() then
3620 EncodingSpecificOperations();
3621 address = R[n] + 4;
3622
3623 for i = 0 to 14
3624 if registers<i> == ’1’ then
3625 if i == n && wback && i != LowestSetBit(registers) then
3626 MemA[address,4] = bits(32) UNKNOWN;
3627 else
3628 MemA[address,4] = R[i];
3629 address = address + 4;
3630
3631 if registers<15> == ’1’ then
3632 MemA[address,4] = PCStoreValue();
3633
3634 if wback then R[n] = R[n] + 4*BitCount(registers);
3635#endif
3636
3637 bool success = false;
3638 const uint32_t opcode = OpcodeAsUnsigned (&success);
3639 if (!success)
3640 return false;
3641
3642 if (ConditionPassed())
3643 {
3644 uint32_t n;
3645 uint32_t registers = 0;
3646 bool wback;
3647 const uint32_t addr_byte_size = GetAddressByteSize();
3648
3649 // EncodingSpecificOperations();
3650 switch (encoding)
3651 {
3652 case eEncodingA1:
3653 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3654 n = Bits32 (opcode, 19, 16);
3655 registers = Bits32 (opcode, 15, 0);
3656 wback = BitIsSet (opcode, 21);
3657
3658 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3659 if ((n == 15) && (BitCount (registers) < 1))
3660 return false;
3661 break;
3662 default:
3663 return false;
3664 }
3665 // address = R[n] + 4;
3666
3667 int32_t offset = 0;
3668 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3669 if (!success)
3670 return false;
3671
3672 address = address + addr_byte_size;
3673
3674 EmulateInstruction::Context context;
3675 context.type = EmulateInstruction::eContextRegisterStore;
3676 Register base_reg;
3677 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3678
3679 uint32_t lowest_set_bit = 14;
3680 // for i = 0 to 14
3681 for (int i = 0; i < 14; ++i)
3682 {
3683 // if registers<i> == ’1’ then
3684 if (BitIsSet (registers, i))
3685 {
3686 if (i < lowest_set_bit)
3687 lowest_set_bit = i;
3688 // if i == n && wback && i != LowestSetBit(registers) then
3689 if ((i == n) && wback && (i != lowest_set_bit))
3690 // MemA[address,4] = bits(32) UNKNOWN;
3691 WriteBits32UnknownToMemory (address + offset);
3692 // else
3693 else
3694 {
3695 // MemA[address,4] = R[i];
3696 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3697 if (!success)
3698 return false;
3699
3700 Register data_reg;
3701 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3702 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003703 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003704 return false;
3705 }
3706
3707 // address = address + 4;
3708 offset += addr_byte_size;
3709 }
3710 }
3711
3712 // if registers<15> == ’1’ then
3713 // MemA[address,4] = PCStoreValue();
3714 if (BitIsSet (registers, 15))
3715 {
3716 Register pc_reg;
3717 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3718 context.SetRegisterPlusOffset (pc_reg, 8);
3719 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3720 if (!success)
3721 return false;
3722
Caroline Ticecc96eb52011-02-17 19:20:40 +00003723 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003724 return false;
3725 }
3726
3727 // if wback then R[n] = R[n] + 4*BitCount(registers);
3728 if (wback)
3729 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003730 offset = addr_byte_size * BitCount (registers);
3731 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3732 context.SetImmediateSigned (offset);
3733 addr_t data = address + offset;
3734 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3735 return false;
3736 }
3737 }
3738 return true;
3739}
Caroline Tice7fac8572011-02-15 22:53:54 +00003740
3741// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3742// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3743bool
3744EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3745{
3746#if 0
3747 if ConditionPassed() then
3748 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3749 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3750 address = if index then offset_addr else R[n];
3751 if UnalignedSupport() || address<1:0> == ’00’ then
3752 MemU[address,4] = R[t];
3753 else // Can only occur before ARMv7
3754 MemU[address,4] = bits(32) UNKNOWN;
3755 if wback then R[n] = offset_addr;
3756#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003757
Caroline Tice7fac8572011-02-15 22:53:54 +00003758 bool success = false;
3759 const uint32_t opcode = OpcodeAsUnsigned (&success);
3760 if (!success)
3761 return false;
3762
3763 if (ConditionPassed())
3764 {
3765 const uint32_t addr_byte_size = GetAddressByteSize();
3766
3767 uint32_t t;
3768 uint32_t n;
3769 uint32_t imm32;
3770 bool index;
3771 bool add;
3772 bool wback;
3773 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3774 switch (encoding)
3775 {
3776 case eEncodingT1:
3777 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3778 t = Bits32 (opcode, 2, 0);
3779 n = Bits32 (opcode, 5, 3);
3780 imm32 = Bits32 (opcode, 10, 6) << 2;
3781
3782 // index = TRUE; add = TRUE; wback = FALSE;
3783 index = true;
3784 add = false;
3785 wback = false;
3786 break;
3787
3788 case eEncodingT2:
3789 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3790 t = Bits32 (opcode, 10, 8);
3791 n = 13;
3792 imm32 = Bits32 (opcode, 7, 0) << 2;
3793
3794 // index = TRUE; add = TRUE; wback = FALSE;
3795 index = true;
3796 add = true;
3797 wback = false;
3798 break;
3799
3800 case eEncodingT3:
3801 // if Rn == ’1111’ then UNDEFINED;
3802 if (Bits32 (opcode, 19, 16) == 15)
3803 return false;
3804
3805 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3806 t = Bits32 (opcode, 15, 12);
3807 n = Bits32 (opcode, 19, 16);
3808 imm32 = Bits32 (opcode, 11, 0);
3809
3810 // index = TRUE; add = TRUE; wback = FALSE;
3811 index = true;
3812 add = true;
3813 wback = false;
3814
3815 // if t == 15 then UNPREDICTABLE;
3816 if (t == 15)
3817 return false;
3818 break;
3819
3820 case eEncodingT4:
3821 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3822 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3823 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3824 if ((Bits32 (opcode, 19, 16) == 15)
3825 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3826 return false;
3827
3828 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3829 t = Bits32 (opcode, 15, 12);
3830 n = Bits32 (opcode, 19, 16);
3831 imm32 = Bits32 (opcode, 7, 0);
3832
3833 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3834 index = BitIsSet (opcode, 10);
3835 add = BitIsSet (opcode, 9);
3836 wback = BitIsSet (opcode, 8);
3837
3838 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3839 if ((t == 15) || (wback && (n == t)))
3840 return false;
3841 break;
3842
3843 default:
3844 return false;
3845 }
3846
3847 addr_t offset_addr;
3848 addr_t address;
3849
3850 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3851 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3852 if (!success)
3853 return false;
3854
3855 if (add)
3856 offset_addr = base_address + imm32;
3857 else
3858 offset_addr = base_address - imm32;
3859
3860 // address = if index then offset_addr else R[n];
3861 if (index)
3862 address = offset_addr;
3863 else
3864 address = base_address;
3865
3866 EmulateInstruction::Context context;
3867 context.type = eContextRegisterStore;
3868 Register base_reg;
3869 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3870
3871 // if UnalignedSupport() || address<1:0> == ’00’ then
3872 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3873 {
3874 // MemU[address,4] = R[t];
3875 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3876 if (!success)
3877 return false;
3878
3879 Register data_reg;
3880 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3881 int32_t offset = address - base_address;
3882 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003883 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003884 return false;
3885 }
3886 else
3887 {
3888 // MemU[address,4] = bits(32) UNKNOWN;
3889 WriteBits32UnknownToMemory (address);
3890 }
3891
3892 // if wback then R[n] = offset_addr;
3893 if (wback)
3894 {
3895 context.type = eContextRegisterLoad;
3896 context.SetAddress (offset_addr);
3897 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3898 return false;
3899 }
3900 }
3901 return true;
3902}
Caroline Ticeaf556562011-02-15 18:42:15 +00003903
Caroline Tice3fd63e92011-02-16 00:33:43 +00003904// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3905// word from a register to memory. The offset register value can optionally be shifted.
3906bool
3907EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3908{
3909#if 0
3910 if ConditionPassed() then
3911 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3912 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3913 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3914 address = if index then offset_addr else R[n];
3915 if t == 15 then // Only possible for encoding A1
3916 data = PCStoreValue();
3917 else
3918 data = R[t];
3919 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3920 MemU[address,4] = data;
3921 else // Can only occur before ARMv7
3922 MemU[address,4] = bits(32) UNKNOWN;
3923 if wback then R[n] = offset_addr;
3924#endif
3925
3926 bool success = false;
3927 const uint32_t opcode = OpcodeAsUnsigned (&success);
3928 if (!success)
3929 return false;
3930
3931 if (ConditionPassed())
3932 {
3933 const uint32_t addr_byte_size = GetAddressByteSize();
3934
3935 uint32_t t;
3936 uint32_t n;
3937 uint32_t m;
3938 ARM_ShifterType shift_t;
3939 uint32_t shift_n;
3940 bool index;
3941 bool add;
3942 bool wback;
3943
3944 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3945 switch (encoding)
3946 {
3947 case eEncodingT1:
3948 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3949 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3950 t = Bits32 (opcode, 2, 0);
3951 n = Bits32 (opcode, 5, 3);
3952 m = Bits32 (opcode, 8, 6);
3953
3954 // index = TRUE; add = TRUE; wback = FALSE;
3955 index = true;
3956 add = true;
3957 wback = false;
3958
3959 // (shift_t, shift_n) = (SRType_LSL, 0);
3960 shift_t = SRType_LSL;
3961 shift_n = 0;
3962 break;
3963
3964 case eEncodingT2:
3965 // if Rn == ’1111’ then UNDEFINED;
3966 if (Bits32 (opcode, 19, 16) == 15)
3967 return false;
3968
3969 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3970 t = Bits32 (opcode, 15, 12);
3971 n = Bits32 (opcode, 19, 16);
3972 m = Bits32 (opcode, 3, 0);
3973
3974 // index = TRUE; add = TRUE; wback = FALSE;
3975 index = true;
3976 add = true;
3977 wback = false;
3978
3979 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3980 shift_t = SRType_LSL;
3981 shift_n = Bits32 (opcode, 5, 4);
3982
3983 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3984 if ((t == 15) || (BadReg (m)))
3985 return false;
3986 break;
3987
3988 case eEncodingA1:
3989 {
3990 // if P == ’0’ && W == ’1’ then SEE STRT;
3991 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3992 t = Bits32 (opcode, 15, 12);
3993 n = Bits32 (opcode, 19, 16);
3994 m = Bits32 (opcode, 3, 0);
3995
3996 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
3997 index = BitIsSet (opcode, 24);
3998 add = BitIsSet (opcode, 23);
3999 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4000
4001 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4002 uint32_t typ = Bits32 (opcode, 6, 5);
4003 uint32_t imm5 = Bits32 (opcode, 11, 7);
4004 shift_n = DecodeImmShift(typ, imm5, shift_t);
4005
4006 // if m == 15 then UNPREDICTABLE;
4007 if (m == 15)
4008 return false;
4009
4010 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4011 if (wback && ((n == 15) || (n == t)))
4012 return false;
4013
4014 break;
4015 }
4016 default:
4017 return false;
4018 }
4019
4020 addr_t offset_addr;
4021 addr_t address;
4022 int32_t offset = 0;
4023
4024 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4025 if (!success)
4026 return false;
4027
4028 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4029 if (!success)
4030 return false;
4031
4032 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004033 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004034
4035 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4036 if (add)
4037 offset_addr = base_address + offset;
4038 else
4039 offset_addr = base_address - offset;
4040
4041 // address = if index then offset_addr else R[n];
4042 if (index)
4043 address = offset_addr;
4044 else
4045 address = base_address;
4046
4047 uint32_t data;
4048 // if t == 15 then // Only possible for encoding A1
4049 if (t == 15)
4050 // data = PCStoreValue();
4051 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4052 else
4053 // data = R[t];
4054 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4055
4056 if (!success)
4057 return false;
4058
4059 EmulateInstruction::Context context;
4060 context.type = eContextRegisterStore;
4061
4062 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4063 if (UnalignedSupport ()
4064 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4065 || CurrentInstrSet() == eModeARM)
4066 {
4067 // MemU[address,4] = data;
4068
4069 Register base_reg;
4070 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4071
4072 Register data_reg;
4073 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4074
4075 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004076 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004077 return false;
4078
4079 }
4080 else
4081 // MemU[address,4] = bits(32) UNKNOWN;
4082 WriteBits32UnknownToMemory (address);
4083
4084 // if wback then R[n] = offset_addr;
4085 if (wback)
4086 {
4087 context.type = eContextRegisterLoad;
4088 context.SetAddress (offset_addr);
4089 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4090 return false;
4091 }
4092
4093 }
4094 return true;
4095}
Caroline Tice73a29de2011-02-16 20:22:22 +00004096
4097bool
4098EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4099{
4100#if 0
4101 if ConditionPassed() then
4102 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4103 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4104 address = if index then offset_addr else R[n];
4105 MemU[address,1] = R[t]<7:0>;
4106 if wback then R[n] = offset_addr;
4107#endif
4108
4109
4110 bool success = false;
4111 const uint32_t opcode = OpcodeAsUnsigned (&success);
4112 if (!success)
4113 return false;
4114
4115 if (ConditionPassed ())
4116 {
4117 uint32_t t;
4118 uint32_t n;
4119 uint32_t imm32;
4120 bool index;
4121 bool add;
4122 bool wback;
4123 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4124 switch (encoding)
4125 {
4126 case eEncodingT1:
4127 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4128 t = Bits32 (opcode, 2, 0);
4129 n = Bits32 (opcode, 5, 3);
4130 imm32 = Bits32 (opcode, 10, 6);
4131
4132 // index = TRUE; add = TRUE; wback = FALSE;
4133 index = true;
4134 add = true;
4135 wback = false;
4136 break;
4137
4138 case eEncodingT2:
4139 // if Rn == ’1111’ then UNDEFINED;
4140 if (Bits32 (opcode, 19, 16) == 15)
4141 return false;
4142
4143 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4144 t = Bits32 (opcode, 15, 12);
4145 n = Bits32 (opcode, 19, 16);
4146 imm32 = Bits32 (opcode, 11, 0);
4147
4148 // index = TRUE; add = TRUE; wback = FALSE;
4149 index = true;
4150 add = true;
4151 wback = false;
4152
4153 // if BadReg(t) then UNPREDICTABLE;
4154 if (BadReg (t))
4155 return false;
4156 break;
4157
4158 case eEncodingT3:
4159 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4160 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4161 if (Bits32 (opcode, 19, 16) == 15)
4162 return false;
4163
4164 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4165 t = Bits32 (opcode, 15, 12);
4166 n = Bits32 (opcode, 19, 16);
4167 imm32 = Bits32 (opcode, 7, 0);
4168
4169 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4170 index = BitIsSet (opcode, 10);
4171 add = BitIsSet (opcode, 9);
4172 wback = BitIsSet (opcode, 8);
4173
4174 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4175 if ((BadReg (t)) || (wback && (n == t)))
4176 return false;
4177 break;
4178
4179 default:
4180 return false;
4181 }
4182
4183 addr_t offset_addr;
4184 addr_t address;
4185 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4186 if (!success)
4187 return false;
4188
4189 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4190 if (add)
4191 offset_addr = base_address + imm32;
4192 else
4193 offset_addr = base_address - imm32;
4194
4195 // address = if index then offset_addr else R[n];
4196 if (index)
4197 address = offset_addr;
4198 else
4199 address = base_address;
4200
Caroline Ticecc96eb52011-02-17 19:20:40 +00004201 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004202 Register base_reg;
4203 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4204
4205 Register data_reg;
4206 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4207
4208 EmulateInstruction::Context context;
4209 context.type = eContextRegisterStore;
4210 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4211
4212 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4213 if (!success)
4214 return false;
4215
4216 data = Bits32 (data, 7, 0);
4217
Caroline Ticecc96eb52011-02-17 19:20:40 +00004218 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004219 return false;
4220
4221 // if wback then R[n] = offset_addr;
4222 if (wback)
4223 {
4224 context.type = eContextRegisterLoad;
4225 context.SetAddress (offset_addr);
4226 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4227 return false;
4228 }
4229
4230 }
4231
4232 return true;
4233}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004234
Johnny Chen157b9592011-02-18 21:13:05 +00004235// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4236// and writes the result to the destination register. It can optionally update the condition flags
4237// based on the result.
4238bool
4239EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4240{
4241#if 0
4242 // ARM pseudo code...
4243 if ConditionPassed() then
4244 EncodingSpecificOperations();
4245 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4246 if d == 15 then // Can only occur for ARM encoding
4247 ALUWritePC(result); // setflags is always FALSE here
4248 else
4249 R[d] = result;
4250 if setflags then
4251 APSR.N = result<31>;
4252 APSR.Z = IsZeroBit(result);
4253 APSR.C = carry;
4254 APSR.V = overflow;
4255#endif
4256
4257 bool success = false;
4258 const uint32_t opcode = OpcodeAsUnsigned (&success);
4259 if (!success)
4260 return false;
4261
4262 if (ConditionPassed())
4263 {
4264 uint32_t Rd, Rn;
4265 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4266 bool setflags;
4267 switch (encoding)
4268 {
4269 case eEncodingT1:
4270 Rd = Bits32(opcode, 11, 8);
4271 Rn = Bits32(opcode, 19, 16);
4272 setflags = BitIsSet(opcode, 20);
4273 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4274 if (BadReg(Rd) || BadReg(Rn))
4275 return false;
4276 break;
4277 case eEncodingA1:
4278 Rd = Bits32(opcode, 15, 12);
4279 Rn = Bits32(opcode, 19, 16);
4280 setflags = BitIsSet(opcode, 20);
4281 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4282 // TODO: Emulate SUBS PC, LR and related instructions.
4283 if (Rd == 15 && setflags)
4284 return false;
4285 break;
4286 default:
4287 return false;
4288 }
4289
4290 // Read the first operand.
4291 int32_t val1 = ReadCoreReg(Rn, &success);
4292 if (!success)
4293 return false;
4294
4295 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4296
4297 EmulateInstruction::Context context;
4298 context.type = EmulateInstruction::eContextImmediate;
4299 context.SetNoArgs ();
4300
4301 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4302 return false;
4303 }
4304 return true;
4305}
4306
4307// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4308// register value, and writes the result to the destination register. It can optionally update the
4309// condition flags based on the result.
4310bool
4311EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4312{
4313#if 0
4314 // ARM pseudo code...
4315 if ConditionPassed() then
4316 EncodingSpecificOperations();
4317 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4318 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4319 if d == 15 then // Can only occur for ARM encoding
4320 ALUWritePC(result); // setflags is always FALSE here
4321 else
4322 R[d] = result;
4323 if setflags then
4324 APSR.N = result<31>;
4325 APSR.Z = IsZeroBit(result);
4326 APSR.C = carry;
4327 APSR.V = overflow;
4328#endif
4329
4330 bool success = false;
4331 const uint32_t opcode = OpcodeAsUnsigned (&success);
4332 if (!success)
4333 return false;
4334
4335 if (ConditionPassed())
4336 {
4337 uint32_t Rd, Rn, Rm;
4338 ARM_ShifterType shift_t;
4339 uint32_t shift_n; // the shift applied to the value read from Rm
4340 bool setflags;
4341 switch (encoding)
4342 {
4343 case eEncodingT1:
4344 Rd = Rn = Bits32(opcode, 2, 0);
4345 Rm = Bits32(opcode, 5, 3);
4346 setflags = !InITBlock();
4347 shift_t = SRType_LSL;
4348 shift_n = 0;
4349 case eEncodingT2:
4350 Rd = Bits32(opcode, 11, 8);
4351 Rn = Bits32(opcode, 19, 16);
4352 Rm = Bits32(opcode, 3, 0);
4353 setflags = BitIsSet(opcode, 20);
4354 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
4355 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4356 return false;
4357 break;
4358 case eEncodingA1:
4359 Rd = Bits32(opcode, 15, 12);
4360 Rn = Bits32(opcode, 19, 16);
4361 Rm = Bits32(opcode, 3, 0);
4362 setflags = BitIsSet(opcode, 20);
4363 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4364 // TODO: Emulate SUBS PC, LR and related instructions.
4365 if (Rd == 15 && setflags)
4366 return false;
4367 break;
4368 default:
4369 return false;
4370 }
4371
4372 // Read the first operand.
4373 int32_t val1 = ReadCoreReg(Rn, &success);
4374 if (!success)
4375 return false;
4376
4377 // Read the second operand.
4378 int32_t val2 = ReadCoreReg(Rm, &success);
4379 if (!success)
4380 return false;
4381
4382 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4383 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4384
4385 EmulateInstruction::Context context;
4386 context.type = EmulateInstruction::eContextImmediate;
4387 context.SetNoArgs ();
4388
4389 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4390 return false;
4391 }
4392 return true;
4393}
4394
Johnny Chene97c0d52011-02-18 19:32:20 +00004395// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4396// to the destination register. It can optionally update the condition flags based on the result.
4397bool
4398EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4399{
4400#if 0
4401 // ARM pseudo code...
4402 if ConditionPassed() then
4403 EncodingSpecificOperations();
4404 result = R[n] AND imm32;
4405 if d == 15 then // Can only occur for ARM encoding
4406 ALUWritePC(result); // setflags is always FALSE here
4407 else
4408 R[d] = result;
4409 if setflags then
4410 APSR.N = result<31>;
4411 APSR.Z = IsZeroBit(result);
4412 APSR.C = carry;
4413 // APSR.V unchanged
4414#endif
4415
4416 bool success = false;
4417 const uint32_t opcode = OpcodeAsUnsigned (&success);
4418 if (!success)
4419 return false;
4420
4421 if (ConditionPassed())
4422 {
4423 uint32_t Rd, Rn;
4424 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4425 bool setflags;
4426 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4427 switch (encoding)
4428 {
4429 case eEncodingT1:
4430 Rd = Bits32(opcode, 11, 8);
4431 Rn = Bits32(opcode, 19, 16);
4432 setflags = BitIsSet(opcode, 20);
4433 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
4434 // TODO: Emulate TST (immediate)
4435 if (Rd == 15 && setflags)
4436 return false;
4437 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4438 return false;
4439 break;
4440 case eEncodingA1:
4441 Rd = Bits32(opcode, 15, 12);
4442 Rn = Bits32(opcode, 19, 16);
4443 setflags = BitIsSet(opcode, 20);
4444 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4445 // TODO: Emulate SUBS PC, LR and related instructions.
4446 if (Rd == 15 && setflags)
4447 return false;
4448 break;
4449 default:
4450 return false;
4451 }
4452
Johnny Chene97c0d52011-02-18 19:32:20 +00004453 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004454 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004455 if (!success)
4456 return false;
4457
4458 uint32_t result = val1 & imm32;
4459
4460 EmulateInstruction::Context context;
4461 context.type = EmulateInstruction::eContextImmediate;
4462 context.SetNoArgs ();
4463
4464 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4465 return false;
4466 }
4467 return true;
4468}
4469
4470// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4471// and writes the result to the destination register. It can optionally update the condition flags
4472// based on the result.
4473bool
4474EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4475{
4476#if 0
4477 // ARM pseudo code...
4478 if ConditionPassed() then
4479 EncodingSpecificOperations();
4480 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4481 result = R[n] AND shifted;
4482 if d == 15 then // Can only occur for ARM encoding
4483 ALUWritePC(result); // setflags is always FALSE here
4484 else
4485 R[d] = result;
4486 if setflags then
4487 APSR.N = result<31>;
4488 APSR.Z = IsZeroBit(result);
4489 APSR.C = carry;
4490 // APSR.V unchanged
4491#endif
4492
4493 bool success = false;
4494 const uint32_t opcode = OpcodeAsUnsigned (&success);
4495 if (!success)
4496 return false;
4497
4498 if (ConditionPassed())
4499 {
4500 uint32_t Rd, Rn, Rm;
4501 ARM_ShifterType shift_t;
4502 uint32_t shift_n; // the shift applied to the value read from Rm
4503 bool setflags;
4504 uint32_t carry;
4505 switch (encoding)
4506 {
4507 case eEncodingT1:
4508 Rd = Rn = Bits32(opcode, 2, 0);
4509 Rm = Bits32(opcode, 5, 3);
4510 setflags = !InITBlock();
4511 shift_t = SRType_LSL;
4512 shift_n = 0;
4513 case eEncodingT2:
4514 Rd = Bits32(opcode, 11, 8);
4515 Rn = Bits32(opcode, 19, 16);
4516 Rm = Bits32(opcode, 3, 0);
4517 setflags = BitIsSet(opcode, 20);
Johnny Chen157b9592011-02-18 21:13:05 +00004518 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004519 // TODO: Emulate TST (register)
4520 if (Rd == 15 && setflags)
4521 return false;
4522 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4523 return false;
4524 break;
4525 case eEncodingA1:
4526 Rd = Bits32(opcode, 15, 12);
4527 Rn = Bits32(opcode, 19, 16);
4528 Rm = Bits32(opcode, 3, 0);
4529 setflags = BitIsSet(opcode, 20);
4530 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4531 // TODO: Emulate SUBS PC, LR and related instructions.
4532 if (Rd == 15 && setflags)
4533 return false;
4534 break;
4535 default:
4536 return false;
4537 }
4538
Johnny Chene97c0d52011-02-18 19:32:20 +00004539 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004540 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004541 if (!success)
4542 return false;
4543
4544 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004545 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004546 if (!success)
4547 return false;
4548
4549 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4550 uint32_t result = val1 & shifted;
4551
4552 EmulateInstruction::Context context;
4553 context.type = EmulateInstruction::eContextImmediate;
4554 context.SetNoArgs ();
4555
4556 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4557 return false;
4558 }
4559 return true;
4560}
4561
Caroline Tice4d729c52011-02-18 00:55:53 +00004562// 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 +00004563// 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 +00004564bool
4565EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4566{
4567#if 0
4568 if ConditionPassed() then
4569 EncodingSpecificOperations();
4570 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4571 address = if index then offset_addr else R[n];
4572 data = MemU[address,4];
4573 if wback then R[n] = offset_addr;
4574 if t == 15 then
4575 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4576 elsif UnalignedSupport() || address<1:0> = ’00’ then
4577 R[t] = data;
4578 else // Can only apply before ARMv7
4579 R[t] = ROR(data, 8*UInt(address<1:0>));
4580#endif
4581
4582 bool success = false;
4583 const uint32_t opcode = OpcodeAsUnsigned (&success);
4584 if (!success)
4585 return false;
4586
4587 if (ConditionPassed ())
4588 {
4589 const uint32_t addr_byte_size = GetAddressByteSize();
4590
4591 uint32_t t;
4592 uint32_t n;
4593 uint32_t imm32;
4594 bool index;
4595 bool add;
4596 bool wback;
4597
4598 switch (encoding)
4599 {
4600 case eEncodingA1:
4601 // if Rn == ’1111’ then SEE LDR (literal);
4602 // if P == ’0’ && W == ’1’ then SEE LDRT;
4603 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4604 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4605 t = Bits32 (opcode, 15, 12);
4606 n = Bits32 (opcode, 19, 16);
4607 imm32 = Bits32 (opcode, 11, 0);
4608
4609 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4610 index = BitIsSet (opcode, 24);
4611 add = BitIsSet (opcode, 23);
4612 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4613
4614 // if wback && n == t then UNPREDICTABLE;
4615 if (wback && (n == t))
4616 return false;
4617
4618 break;
4619
4620 default:
4621 return false;
4622 }
4623
4624 addr_t address;
4625 addr_t offset_addr;
4626 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4627 if (!success)
4628 return false;
4629
4630 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4631 if (add)
4632 offset_addr = base_address + imm32;
4633 else
4634 offset_addr = base_address - imm32;
4635
4636 // address = if index then offset_addr else R[n];
4637 if (index)
4638 address = offset_addr;
4639 else
4640 address = base_address;
4641
4642 // data = MemU[address,4];
4643
4644 Register base_reg;
4645 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4646
4647 EmulateInstruction::Context context;
4648 context.type = eContextRegisterLoad;
4649 context.SetRegisterPlusOffset (base_reg, address - base_address);
4650
4651 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4652 if (!success)
4653 return false;
4654
4655 // if wback then R[n] = offset_addr;
4656 if (wback)
4657 {
4658 context.type = eContextAdjustBaseRegister;
4659 context.SetAddress (offset_addr);
4660 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4661 return false;
4662 }
4663
4664 // if t == 15 then
4665 if (t == 15)
4666 {
4667 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4668 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4669 {
4670 // LoadWritePC (data);
4671 context.type = eContextRegisterLoad;
4672 context.SetRegisterPlusOffset (base_reg, address - base_address);
4673 LoadWritePC (context, data);
4674 }
4675 else
4676 return false;
4677 }
4678 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4679 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4680 {
4681 // R[t] = data;
4682 context.type = eContextRegisterLoad;
4683 context.SetRegisterPlusOffset (base_reg, address - base_address);
4684 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4685 return false;
4686 }
4687 // else // Can only apply before ARMv7
4688 else
4689 {
4690 // R[t] = ROR(data, 8*UInt(address<1:0>));
4691 data = ROR (data, Bits32 (address, 1, 0));
4692 context.type = eContextRegisterLoad;
4693 context.SetImmediate (data);
4694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4695 return false;
4696 }
4697
4698 }
4699 return true;
4700}
4701
Caroline Ticefe479112011-02-18 18:52:37 +00004702// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4703// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4704bool
4705EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4706{
4707#if 0
4708 if ConditionPassed() then
4709 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4710 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4711 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4712 address = if index then offset_addr else R[n];
4713 data = MemU[address,4];
4714 if wback then R[n] = offset_addr;
4715 if t == 15 then
4716 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4717 elsif UnalignedSupport() || address<1:0> = ’00’ then
4718 R[t] = data;
4719 else // Can only apply before ARMv7
4720 if CurrentInstrSet() == InstrSet_ARM then
4721 R[t] = ROR(data, 8*UInt(address<1:0>));
4722 else
4723 R[t] = bits(32) UNKNOWN;
4724#endif
4725
4726 bool success = false;
4727 const uint32_t opcode = OpcodeAsUnsigned (&success);
4728 if (!success)
4729 return false;
4730
4731 if (ConditionPassed ())
4732 {
4733 const uint32_t addr_byte_size = GetAddressByteSize();
4734
4735 uint32_t t;
4736 uint32_t n;
4737 uint32_t m;
4738 bool index;
4739 bool add;
4740 bool wback;
4741 ARM_ShifterType shift_t;
4742 uint32_t shift_n;
4743
4744 switch (encoding)
4745 {
4746 case eEncodingT1:
4747 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4748 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4749 t = Bits32 (opcode, 2, 0);
4750 n = Bits32 (opcode, 5, 3);
4751 m = Bits32 (opcode, 8, 6);
4752
4753 // index = TRUE; add = TRUE; wback = FALSE;
4754 index = true;
4755 add = true;
4756 wback = false;
4757
4758 // (shift_t, shift_n) = (SRType_LSL, 0);
4759 shift_t = SRType_LSL;
4760 shift_n = 0;
4761
4762 break;
4763
4764 case eEncodingT2:
4765 // if Rn == ’1111’ then SEE LDR (literal);
4766 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4767 t = Bits32 (opcode, 15, 12);
4768 n = Bits32 (opcode, 19, 16);
4769 m = Bits32 (opcode, 3, 0);
4770
4771 // index = TRUE; add = TRUE; wback = FALSE;
4772 index = true;
4773 add = true;
4774 wback = false;
4775
4776 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4777 shift_t = SRType_LSL;
4778 shift_n = Bits32 (opcode, 5, 4);
4779
4780 // if BadReg(m) then UNPREDICTABLE;
4781 if (BadReg (m))
4782 return false;
4783
4784 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4785 if ((t == 15) && InITBlock() && !LastInITBlock())
4786 return false;
4787
4788 break;
4789
4790 case eEncodingA1:
4791 {
4792 // if P == ’0’ && W == ’1’ then SEE LDRT;
4793 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4794 t = Bits32 (opcode, 15, 12);
4795 n = Bits32 (opcode, 19, 16);
4796 m = Bits32 (opcode, 3, 0);
4797
4798 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4799 index = BitIsSet (opcode, 24);
4800 add = BitIsSet (opcode, 23);
4801 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4802
4803 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4804 uint32_t type = Bits32 (opcode, 6, 5);
4805 uint32_t imm5 = Bits32 (opcode, 11, 7);
4806 shift_n = DecodeImmShift (type, imm5, shift_t);
4807
4808 // if m == 15 then UNPREDICTABLE;
4809 if (m == 15)
4810 return false;
4811
4812 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4813 if (wback && ((n == 15) || (n == t)))
4814 return false;
4815 }
4816 break;
4817
4818
4819 default:
4820 return false;
4821 }
4822
4823 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4824 if (!success)
4825 return false;
4826
4827 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4828 if (!success)
4829 return false;
4830
4831 addr_t offset_addr;
4832 addr_t address;
4833
4834 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
4835 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
4836
4837 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4838 if (add)
4839 offset_addr = Rn + offset;
4840 else
4841 offset_addr = Rn - offset;
4842
4843 // address = if index then offset_addr else R[n];
4844 if (index)
4845 address = offset_addr;
4846 else
4847 address = Rn;
4848
4849 // data = MemU[address,4];
4850 Register base_reg;
4851 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4852
4853 EmulateInstruction::Context context;
4854 context.type = eContextRegisterLoad;
4855 context.SetRegisterPlusOffset (base_reg, address - Rn);
4856
4857 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4858 if (!success)
4859 return false;
4860
4861 // if wback then R[n] = offset_addr;
4862 if (wback)
4863 {
4864 context.type = eContextAdjustBaseRegister;
4865 context.SetAddress (offset_addr);
4866 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4867 return false;
4868 }
4869
4870 // if t == 15 then
4871 if (t == 15)
4872 {
4873 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4874 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4875 {
4876 context.type = eContextRegisterLoad;
4877 context.SetRegisterPlusOffset (base_reg, address - Rn);
4878 LoadWritePC (context, data);
4879 }
4880 else
4881 return false;
4882 }
4883 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4884 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4885 {
4886 // R[t] = data;
4887 context.type = eContextRegisterLoad;
4888 context.SetRegisterPlusOffset (base_reg, address - Rn);
4889 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4890 return false;
4891 }
4892 else // Can only apply before ARMv7
4893 {
4894 // if CurrentInstrSet() == InstrSet_ARM then
4895 if (CurrentInstrSet () == eModeARM)
4896 {
4897 // R[t] = ROR(data, 8*UInt(address<1:0>));
4898 data = ROR (data, Bits32 (address, 1, 0));
4899 context.type = eContextRegisterLoad;
4900 context.SetImmediate (data);
4901 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4902 return false;
4903 }
4904 else
4905 {
4906 // R[t] = bits(32) UNKNOWN;
4907 WriteBits32Unknown (t);
4908 }
4909 }
4910 }
4911 return true;
4912}
Caroline Tice21b604b2011-02-18 21:06:04 +00004913
4914// LDRB (immediate, Thumb)
4915bool
4916EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
4917{
4918#if 0
4919 if ConditionPassed() then
4920 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4921 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4922 address = if index then offset_addr else R[n];
4923 R[t] = ZeroExtend(MemU[address,1], 32);
4924 if wback then R[n] = offset_addr;
4925#endif
4926
4927 bool success = false;
4928 const uint32_t opcode = OpcodeAsUnsigned (&success);
4929 if (!success)
4930 return false;
4931
4932 if (ConditionPassed ())
4933 {
4934 uint32_t t;
4935 uint32_t n;
4936 uint32_t imm32;
4937 bool index;
4938 bool add;
4939 bool wback;
4940
4941 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4942 switch (encoding)
4943 {
4944 case eEncodingT1:
4945 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4946 t = Bits32 (opcode, 2, 0);
4947 n = Bits32 (opcode, 5, 3);
4948 imm32 = Bits32 (opcode, 10, 6);
4949
4950 // index = TRUE; add = TRUE; wback = FALSE;
4951 index = true;
4952 add = true;
4953 wback= false;
4954
4955 break;
4956
4957 case eEncodingT2:
4958 // if Rt == ’1111’ then SEE PLD;
4959 // if Rn == ’1111’ then SEE LDRB (literal);
4960 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4961 t = Bits32 (opcode, 15, 12);
4962 n = Bits32 (opcode, 19, 16);
4963 imm32 = Bits32 (opcode, 11, 0);
4964
4965 // index = TRUE; add = TRUE; wback = FALSE;
4966 index = true;
4967 add = true;
4968 wback = false;
4969
4970 // if t == 13 then UNPREDICTABLE;
4971 if (t == 13)
4972 return false;
4973
4974 break;
4975
4976 case eEncodingT3:
4977 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
4978 // if Rn == ’1111’ then SEE LDRB (literal);
4979 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
4980 // if P == ’0’ && W == ’0’ then UNDEFINED;
4981 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
4982 return false;
4983
4984 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4985 t = Bits32 (opcode, 15, 12);
4986 n = Bits32 (opcode, 19, 16);
4987 imm32 = Bits32 (opcode, 7, 0);
4988
4989 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4990 index = BitIsSet (opcode, 10);
4991 add = BitIsSet (opcode, 9);
4992 wback = BitIsSet (opcode, 8);
4993
4994 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
4995 if (BadReg (t) || (wback && (n == t)))
4996 return false;
4997
4998 break;
4999
5000 default:
5001 return false;
5002 }
5003
5004 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5005 if (!success)
5006 return false;
5007
5008 addr_t address;
5009 addr_t offset_addr;
5010
5011 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5012 if (add)
5013 offset_addr = Rn + imm32;
5014 else
5015 offset_addr = Rn - imm32;
5016
5017 // address = if index then offset_addr else R[n];
5018 if (index)
5019 address = offset_addr;
5020 else
5021 address = Rn;
5022
5023 // R[t] = ZeroExtend(MemU[address,1], 32);
5024 Register base_reg;
5025 Register data_reg;
5026 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5027 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5028
5029 EmulateInstruction::Context context;
5030 context.type = eContextRegisterLoad;
5031 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5032
5033 uint64_t data = MemURead (context, address, 1, 0, &success);
5034 if (!success)
5035 return false;
5036
5037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5038 return false;
5039
5040 // if wback then R[n] = offset_addr;
5041 if (wback)
5042 {
5043 context.type = eContextAdjustBaseRegister;
5044 context.SetAddress (offset_addr);
5045 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5046 return false;
5047 }
5048 }
5049 return true;
5050}
Caroline Ticefe479112011-02-18 18:52:37 +00005051
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005052EmulateInstructionARM::ARMOpcode*
5053EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00005054{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005055 static ARMOpcode
5056 g_arm_opcodes[] =
5057 {
5058 //----------------------------------------------------------------------
5059 // Prologue instructions
5060 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00005061
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005062 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005063 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5064 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00005065
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005066 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005067 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005068 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00005069 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00005070 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
5071 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005072 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00005073
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005074 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005075 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00005076
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005077 // push one register
5078 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00005079 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00005080
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005081 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00005082 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5083 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00005084
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005085 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00005086 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005087 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00005088
Johnny Chen9f687722011-02-18 00:02:28 +00005089 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5090 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00005091 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005092 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
5093
5094 //----------------------------------------------------------------------
5095 // Supervisor Call (previously Software Interrupt)
5096 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005097 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
5098
5099 //----------------------------------------------------------------------
5100 // Branch instructions
5101 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005102 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00005103 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
5104 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5105 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5106 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005107 // for example, "bx lr"
5108 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005109
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005110 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00005111 // Data-processing instructions
5112 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005113 // adc (immediate)
5114 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
5115 // adc (register)
5116 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005117 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005118 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005119 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005120 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005121 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005122 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005123 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005124 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen28070c32011-02-12 01:27:26 +00005125 // move bitwise not
Johnny Chen157b9592011-02-18 21:13:05 +00005126 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005127 // asr (immediate)
5128 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005129 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00005130 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005131 // lsl (immediate)
5132 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
5133 // lsl (register)
5134 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
5135 // lsr (immediate)
5136 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
5137 // lsr (register)
5138 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005139 // rrx is a special case encoding of ror (immediate)
5140 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
5141 // ror (immediate)
5142 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
5143 // ror (register)
5144 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005145
5146 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005147 // Load instructions
5148 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00005149 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00005150 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00005151 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00005152 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00005153 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00005154 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00005155
5156 //----------------------------------------------------------------------
5157 // Store instructions
5158 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00005159 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005160 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00005161 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00005162 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
5163 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00005164
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005165
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005166 };
5167 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
5168
5169 for (size_t i=0; i<k_num_arm_opcodes; ++i)
5170 {
5171 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
5172 return &g_arm_opcodes[i];
5173 }
5174 return NULL;
5175}
Greg Clayton64c84432011-01-21 22:02:52 +00005176
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005177
5178EmulateInstructionARM::ARMOpcode*
5179EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00005180{
Johnny Chenfdd179e2011-01-31 20:09:28 +00005181
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005182 static ARMOpcode
5183 g_thumb_opcodes[] =
5184 {
5185 //----------------------------------------------------------------------
5186 // Prologue instructions
5187 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00005188
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005189 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005190 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5191 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
5192 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00005193
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005194 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005195 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005196 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00005197 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005198 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00005199 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00005200
Johnny Chen864a8e82011-02-18 00:07:39 +00005201 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00005202 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00005203
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005204 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005205 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
5206 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
5207 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
5208 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005209
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005210 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00005211 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5212 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005213
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005214 //----------------------------------------------------------------------
5215 // Epilogue instructions
5216 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00005217
Johnny Chen864a8e82011-02-18 00:07:39 +00005218 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00005219 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5220 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
5221 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00005222 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
5223 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005224
5225 //----------------------------------------------------------------------
5226 // Supervisor Call (previously Software Interrupt)
5227 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00005228 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
5229
5230 //----------------------------------------------------------------------
5231 // If Then makes up to four following instructions conditional.
5232 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005233 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
5234
5235 //----------------------------------------------------------------------
5236 // Branch instructions
5237 //----------------------------------------------------------------------
5238 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
5239 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
5240 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00005241 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005242 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00005243 // J1 == J2 == 1
5244 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5245 // J1 == J2 == 1
5246 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5247 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005248 // for example, "bx lr"
5249 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00005250 // compare and branch
5251 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00005252 // table branch byte
5253 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
5254 // table branch halfword
5255 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005256
5257 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00005258 // Data-processing instructions
5259 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005260 // adc (immediate)
5261 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
5262 // adc (register)
5263 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
5264 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
5265 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00005266 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005267 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00005268 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005269 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005270 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005271 // and (register)
5272 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
5273 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen338bf542011-02-10 19:29:03 +00005274 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00005275 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00005276 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00005277 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00005278 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005279 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
5280 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005281 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005282 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00005283 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005284 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005285 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005286 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005287 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005288 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005289 // asr (immediate)
5290 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00005291 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00005292 // asr (register)
5293 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
5294 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005295 // lsl (immediate)
5296 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
5297 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
5298 // lsl (register)
5299 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
5300 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
5301 // lsr (immediate)
5302 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
5303 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
5304 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00005305 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005306 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005307 // rrx is a special case encoding of ror (immediate)
5308 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
5309 // ror (immediate)
5310 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
5311 // ror (register)
5312 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
5313 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005314
5315 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005316 // Load instructions
5317 //----------------------------------------------------------------------
5318 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00005319 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00005320 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00005321 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
5322 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00005323 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00005324 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
5325 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00005326 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
5327 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
5328 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00005329
5330 //----------------------------------------------------------------------
5331 // Store instructions
5332 //----------------------------------------------------------------------
5333 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005334 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00005335 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00005336 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
5337 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
5338 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
5339 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
5340 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
5341 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
5342 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
5343 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
5344 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005345 };
5346
5347 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
5348 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
5349 {
5350 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
5351 return &g_thumb_opcodes[i];
5352 }
5353 return NULL;
5354}
Greg Clayton64c84432011-01-21 22:02:52 +00005355
Greg Clayton31e2a382011-01-30 20:03:56 +00005356bool
Greg Clayton395fc332011-02-15 21:59:32 +00005357EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00005358{
5359 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00005360 const char *arch_cstr = arch.AsCString ();
5361 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00005362 {
Greg Clayton395fc332011-02-15 21:59:32 +00005363 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
5364 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
5365 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
5366 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
5367 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
5368 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
5369 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
5370 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
5371 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
5372 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00005373 }
5374 return m_arm_isa != 0;
5375}
5376
5377
Greg Clayton64c84432011-01-21 22:02:52 +00005378bool
5379EmulateInstructionARM::ReadInstruction ()
5380{
5381 bool success = false;
5382 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
5383 if (success)
5384 {
5385 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
5386 if (success)
5387 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00005388 Context read_inst_context;
5389 read_inst_context.type = eContextReadOpcode;
5390 read_inst_context.SetNoArgs ();
5391
Greg Clayton64c84432011-01-21 22:02:52 +00005392 if (m_inst_cpsr & MASK_CPSR_T)
5393 {
5394 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005395 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005396
5397 if (success)
5398 {
5399 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
5400 {
5401 m_inst.opcode_type = eOpcode16;
5402 m_inst.opcode.inst16 = thumb_opcode;
5403 }
5404 else
5405 {
5406 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005407 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005408 }
5409 }
5410 }
5411 else
5412 {
5413 m_inst_mode = eModeARM;
5414 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005415 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005416 }
5417 }
5418 }
5419 if (!success)
5420 {
5421 m_inst_mode = eModeInvalid;
5422 m_inst_pc = LLDB_INVALID_ADDRESS;
5423 }
5424 return success;
5425}
5426
Johnny Chenee9b1f72011-02-09 01:00:31 +00005427uint32_t
5428EmulateInstructionARM::ArchVersion ()
5429{
5430 return m_arm_isa;
5431}
5432
Greg Clayton64c84432011-01-21 22:02:52 +00005433bool
5434EmulateInstructionARM::ConditionPassed ()
5435{
5436 if (m_inst_cpsr == 0)
5437 return false;
5438
5439 const uint32_t cond = CurrentCond ();
5440
5441 if (cond == UINT32_MAX)
5442 return false;
5443
5444 bool result = false;
5445 switch (UnsignedBits(cond, 3, 1))
5446 {
5447 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
5448 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
5449 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
5450 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
5451 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
5452 case 5:
5453 {
5454 bool n = (m_inst_cpsr & MASK_CPSR_N);
5455 bool v = (m_inst_cpsr & MASK_CPSR_V);
5456 result = n == v;
5457 }
5458 break;
5459 case 6:
5460 {
5461 bool n = (m_inst_cpsr & MASK_CPSR_N);
5462 bool v = (m_inst_cpsr & MASK_CPSR_V);
5463 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
5464 }
5465 break;
5466 case 7:
5467 result = true;
5468 break;
5469 }
5470
5471 if (cond & 1)
5472 result = !result;
5473 return result;
5474}
5475
Johnny Chen9ee056b2011-02-08 00:06:35 +00005476uint32_t
5477EmulateInstructionARM::CurrentCond ()
5478{
5479 switch (m_inst_mode)
5480 {
5481 default:
5482 case eModeInvalid:
5483 break;
5484
5485 case eModeARM:
5486 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
5487
5488 case eModeThumb:
5489 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
5490 // 'cond' field of the encoding.
5491 if (m_inst.opcode_type == eOpcode16 &&
5492 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
5493 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
5494 {
5495 return Bits32(m_inst.opcode.inst16, 11, 7);
5496 }
5497 else if (m_inst.opcode_type == eOpcode32 &&
5498 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
5499 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
5500 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
5501 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
5502 {
5503 return Bits32(m_inst.opcode.inst32, 25, 22);
5504 }
5505
5506 return m_it_session.GetCond();
5507 }
5508 return UINT32_MAX; // Return invalid value
5509}
5510
Johnny Chen9ee056b2011-02-08 00:06:35 +00005511bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00005512EmulateInstructionARM::InITBlock()
5513{
5514 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
5515}
5516
5517bool
5518EmulateInstructionARM::LastInITBlock()
5519{
5520 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
5521}
5522
5523bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00005524EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
5525{
5526 addr_t target;
5527
Johnny Chenee9b1f72011-02-09 01:00:31 +00005528 // Check the current instruction set.
5529 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005530 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005531 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00005532 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005533
Johnny Chen9ee056b2011-02-08 00:06:35 +00005534 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005535 return false;
5536
5537 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005538}
5539
5540// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
5541bool
Johnny Chen668b4512011-02-15 21:08:58 +00005542EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005543{
5544 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00005545 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
5546 // we want to record it and issue a WriteRegister callback so the clients
5547 // can track the mode changes accordingly.
5548 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005549
5550 if (BitIsSet(addr, 0))
5551 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005552 if (CurrentInstrSet() != eModeThumb)
5553 {
5554 SelectInstrSet(eModeThumb);
5555 cpsr_changed = true;
5556 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005557 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00005558 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005559 }
5560 else if (BitIsClear(addr, 1))
5561 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005562 if (CurrentInstrSet() != eModeARM)
5563 {
5564 SelectInstrSet(eModeARM);
5565 cpsr_changed = true;
5566 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005567 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00005568 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005569 }
5570 else
5571 return false; // address<1:0> == '10' => UNPREDICTABLE
5572
Johnny Chen0f309db2011-02-09 19:11:32 +00005573 if (cpsr_changed)
5574 {
Johnny Chen558133b2011-02-09 23:59:17 +00005575 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00005576 return false;
5577 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005578 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005579 return false;
5580
5581 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005582}
Greg Clayton64c84432011-01-21 22:02:52 +00005583
Johnny Chenee9b1f72011-02-09 01:00:31 +00005584// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
5585bool
Johnny Chen668b4512011-02-15 21:08:58 +00005586EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00005587{
5588 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00005589 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00005590 else
5591 return BranchWritePC((const Context)context, addr);
5592}
5593
Johnny Chen26863dc2011-02-09 23:43:29 +00005594// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
5595bool
Johnny Chen668b4512011-02-15 21:08:58 +00005596EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00005597{
5598 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00005599 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00005600 else
5601 return BranchWritePC((const Context)context, addr);
5602}
5603
Johnny Chenee9b1f72011-02-09 01:00:31 +00005604EmulateInstructionARM::Mode
5605EmulateInstructionARM::CurrentInstrSet ()
5606{
5607 return m_inst_mode;
5608}
5609
5610// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00005611// ReadInstruction() is performed. This function has a side effect of updating
5612// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00005613bool
5614EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
5615{
Johnny Chen558133b2011-02-09 23:59:17 +00005616 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005617 switch (arm_or_thumb)
5618 {
5619 default:
5620 return false;
5621 eModeARM:
5622 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005623 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005624 break;
5625 eModeThumb:
5626 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005627 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005628 break;
5629 }
5630 return true;
5631}
5632
Johnny Chenef21b592011-02-10 01:52:38 +00005633// This function returns TRUE if the processor currently provides support for
5634// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
5635// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
5636bool
5637EmulateInstructionARM::UnalignedSupport()
5638{
5639 return (ArchVersion() >= ARMv7);
5640}
5641
Johnny Chenbf6ad172011-02-11 01:29:53 +00005642// The main addition and subtraction instructions can produce status information
5643// about both unsigned carry and signed overflow conditions. This status
5644// information can be used to synthesize multi-word additions and subtractions.
5645EmulateInstructionARM::AddWithCarryResult
5646EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
5647{
5648 uint32_t result;
5649 uint8_t carry_out;
5650 uint8_t overflow;
5651
5652 uint64_t unsigned_sum = x + y + carry_in;
5653 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
5654
5655 result = UnsignedBits(unsigned_sum, 31, 0);
5656 carry_out = (result == unsigned_sum ? 0 : 1);
5657 overflow = ((int32_t)result == signed_sum ? 0 : 1);
5658
5659 AddWithCarryResult res = { result, carry_out, overflow };
5660 return res;
5661}
5662
Johnny Chen157b9592011-02-18 21:13:05 +00005663uint32_t
5664EmulateInstructionARM::ReadCoreReg(uint32_t regnum, bool *success)
5665{
5666 uint32_t val;
5667 if (regnum == 15)
5668 {
5669 val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, success);
5670 if (CurrentInstrSet() == eModeThumb)
5671 val += 4;
5672 else
5673 val += 8;
5674 }
5675 else
5676 val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + regnum, 0, success);
5677
5678 return val;
5679}
5680
Johnny Chenca67d1c2011-02-17 01:35:27 +00005681// Write the result to the ARM core register Rd, and optionally update the
5682// condition flags based on the result.
5683//
5684// This helper method tries to encapsulate the following pseudocode from the
5685// ARM Architecture Reference Manual:
5686//
5687// if d == 15 then // Can only occur for encoding A1
5688// ALUWritePC(result); // setflags is always FALSE here
5689// else
5690// R[d] = result;
5691// if setflags then
5692// APSR.N = result<31>;
5693// APSR.Z = IsZeroBit(result);
5694// APSR.C = carry;
5695// // APSR.V unchanged
5696//
5697// In the above case, the API client does not pass in the overflow arg, which
5698// defaults to ~0u.
5699bool
Johnny Chen10530c22011-02-17 22:37:12 +00005700EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
5701 const uint32_t result,
5702 const uint32_t Rd,
5703 bool setflags,
5704 const uint32_t carry,
5705 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00005706{
5707 if (Rd == 15)
5708 {
5709 if (!ALUWritePC (context, result))
5710 return false;
5711 }
5712 else
5713 {
5714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
5715 return false;
5716 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00005717 return WriteFlags (context, result, carry, overflow);
5718 }
5719 return true;
5720}
5721
5722// This helper method tries to encapsulate the following pseudocode from the
5723// ARM Architecture Reference Manual:
5724//
5725// APSR.N = result<31>;
5726// APSR.Z = IsZeroBit(result);
5727// APSR.C = carry;
5728// APSR.V = overflow
5729//
5730// Default arguments can be specified for carry and overflow parameters, which means
5731// not to update the respective flags.
5732bool
5733EmulateInstructionARM::WriteFlags (Context &context,
5734 const uint32_t result,
5735 const uint32_t carry,
5736 const uint32_t overflow)
5737{
5738 m_new_inst_cpsr = m_inst_cpsr;
5739 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
5740 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
5741 if (carry != ~0u)
5742 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
5743 if (overflow != ~0u)
5744 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
5745 if (m_new_inst_cpsr != m_inst_cpsr)
5746 {
5747 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
5748 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00005749 }
5750 return true;
5751}
5752
Greg Clayton64c84432011-01-21 22:02:52 +00005753bool
5754EmulateInstructionARM::EvaluateInstruction ()
5755{
Johnny Chenc315f862011-02-05 00:46:10 +00005756 // Advance the ITSTATE bits to their values for the next instruction.
5757 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
5758 m_it_session.ITAdvance();
5759
Greg Clayton64c84432011-01-21 22:02:52 +00005760 return false;
5761}