blob: 1cd8440c19173de4d624b0cb97a7f344002dea61 [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"
Caroline Tice080bf612011-04-05 18:46:00 +000014#include "lldb/Core/Address.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000015#include "lldb/Core/ConstString.h"
Caroline Tice080bf612011-04-05 18:46:00 +000016#include "lldb/Core/PluginManager.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000017
Greg Claytonf29a08f2011-02-09 17:41:27 +000018#include "Plugins/Process/Utility/ARMDefines.h"
19#include "Plugins/Process/Utility/ARMUtils.h"
20#include "Utility/ARM_DWARF_Registers.h"
21
Johnny Chen9b8d7832011-02-02 01:13:56 +000022#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000023 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000024
25using namespace lldb;
26using namespace lldb_private;
27
Johnny Chene97c0d52011-02-18 19:32:20 +000028// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000029#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
30#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000031
Caroline Ticef55261f2011-02-18 22:24:22 +000032#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
33
Johnny Chen0e00af22011-02-10 19:40:42 +000034//----------------------------------------------------------------------
35//
36// ITSession implementation
37//
38//----------------------------------------------------------------------
39
Johnny Chen93070472011-02-04 23:02:47 +000040// A8.6.50
41// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
42static unsigned short CountITSize(unsigned ITMask) {
43 // First count the trailing zeros of the IT mask.
44 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
45 if (TZ > 3)
46 {
47 printf("Encoding error: IT Mask '0000'\n");
48 return 0;
49 }
50 return (4 - TZ);
51}
52
53// Init ITState. Note that at least one bit is always 1 in mask.
54bool ITSession::InitIT(unsigned short bits7_0)
55{
56 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
57 if (ITCounter == 0)
58 return false;
59
60 // A8.6.50 IT
61 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
62 if (FirstCond == 0xF)
63 {
64 printf("Encoding error: IT FirstCond '1111'\n");
65 return false;
66 }
67 if (FirstCond == 0xE && ITCounter != 1)
68 {
69 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
70 return false;
71 }
72
73 ITState = bits7_0;
74 return true;
75}
76
77// Update ITState if necessary.
78void ITSession::ITAdvance()
79{
80 assert(ITCounter);
81 --ITCounter;
82 if (ITCounter == 0)
83 ITState = 0;
84 else
85 {
86 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
87 SetBits32(ITState, 4, 0, NewITState4_0);
88 }
89}
90
91// Return true if we're inside an IT Block.
92bool ITSession::InITBlock()
93{
94 return ITCounter != 0;
95}
96
Johnny Chenc315f862011-02-05 00:46:10 +000097// Return true if we're the last instruction inside an IT Block.
98bool ITSession::LastInITBlock()
99{
100 return ITCounter == 1;
101}
102
Johnny Chen93070472011-02-04 23:02:47 +0000103// Get condition bits for the current thumb instruction.
104uint32_t ITSession::GetCond()
105{
Johnny Chenc315f862011-02-05 00:46:10 +0000106 if (InITBlock())
107 return Bits32(ITState, 7, 4);
108 else
109 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000110}
111
Greg Clayton64c84432011-01-21 22:02:52 +0000112// ARM constants used during decoding
113#define REG_RD 0
114#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000115#define SP_REG 13
116#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000117#define PC_REG 15
118#define PC_REGLIST_BIT 0x8000
119
Johnny Chen251af6a2011-01-21 22:47:25 +0000120#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000121#define ARMv4T (1u << 1)
122#define ARMv5T (1u << 2)
123#define ARMv5TE (1u << 3)
124#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000125#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000126#define ARMv6K (1u << 6)
127#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000128#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000129#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000130#define ARMvAll (0xffffffffu)
131
Johnny Chen9b8d7832011-02-02 01:13:56 +0000132#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
133#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000134#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000135#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000136#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000137#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000138
Caroline Tice4f605582011-03-31 00:02:51 +0000139#define No_VFP 0
140#define VFPv1 (1u << 1)
141#define VFPv2 (1u << 2)
142#define VFPv3 (1u << 3)
143#define AdvancedSIMD (1u << 4)
144
145#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
146#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
147#define VFPv2v3 (VFPv2 | VFPv3)
148
Johnny Chen0e00af22011-02-10 19:40:42 +0000149//----------------------------------------------------------------------
150//
151// EmulateInstructionARM implementation
152//
153//----------------------------------------------------------------------
154
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000155void
156EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000157{
Caroline Tice080bf612011-04-05 18:46:00 +0000158 PluginManager::RegisterPlugin (GetPluginNameStatic (),
159 GetPluginDescriptionStatic (),
160 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000161}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000162
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000163void
164EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000165{
Caroline Tice080bf612011-04-05 18:46:00 +0000166 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000167}
168
Caroline Tice080bf612011-04-05 18:46:00 +0000169const char *
170EmulateInstructionARM::GetPluginNameStatic ()
171{
172 return "lldb.emulate-instruction.arm";
173}
174
175const char *
176EmulateInstructionARM::GetPluginDescriptionStatic ()
177{
178 return "Emulate instructions for the ARM architecture.";
179}
180
181EmulateInstruction *
182EmulateInstructionARM::CreateInstance (const ArchSpec &arch)
183{
184 if (arch.GetTriple().getArch() == llvm::Triple::arm)
185 {
186 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
187
188 if (emulate_insn_ap.get())
189 return emulate_insn_ap.release();
190 }
191 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
192 {
193 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
194
195 if (emulate_insn_ap.get())
196 return emulate_insn_ap.release();
197 }
198
199 return NULL;
200}
201
202bool
203EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
204{
205 if (arch.GetTriple().getArch () == llvm::Triple::arm)
206 return true;
207 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
208 return true;
209
210 return false;
211}
212
Caroline Ticefa172202011-02-11 22:49:54 +0000213// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
214bool
215EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
216{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000217 EmulateInstruction::Context context;
218 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
219 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000220
221 uint32_t random_data = rand ();
222 const uint32_t addr_byte_size = GetAddressByteSize();
223
Caroline Ticecc96eb52011-02-17 19:20:40 +0000224 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000225 return false;
226
227 return true;
228}
229
Caroline Tice713c2662011-02-11 17:59:55 +0000230// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
231bool
232EmulateInstructionARM::WriteBits32Unknown (int n)
233{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000234 EmulateInstruction::Context context;
235 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
236 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000237
Johnny Chen62ff6f52011-02-11 18:11:22 +0000238 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000239 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
240
241 if (!success)
242 return false;
243
244 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
245 return false;
246
247 return true;
248}
249
Johnny Chen08c25e82011-01-31 18:02:28 +0000250// Push Multiple Registers stores multiple registers to the stack, storing to
251// consecutive memory locations ending just below the address in SP, and updates
252// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000253bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000254EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000255{
256#if 0
257 // ARM pseudo code...
258 if (ConditionPassed())
259 {
260 EncodingSpecificOperations();
261 NullCheckIfThumbEE(13);
262 address = SP - 4*BitCount(registers);
263
264 for (i = 0 to 14)
265 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000266 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000267 {
268 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
269 MemA[address,4] = bits(32) UNKNOWN;
270 else
271 MemA[address,4] = R[i];
272 address = address + 4;
273 }
274 }
275
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000276 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000277 MemA[address,4] = PCStoreValue();
278
279 SP = SP - 4*BitCount(registers);
280 }
281#endif
282
283 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000284 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000285 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000286 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000290 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000291 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000292 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000293 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000294 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000295 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000296 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000297 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000298 // if BitCount(registers) < 1 then UNPREDICTABLE;
299 if (BitCount(registers) < 1)
300 return false;
301 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000302 case eEncodingT2:
303 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000304 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000305 // if BitCount(registers) < 2 then UNPREDICTABLE;
306 if (BitCount(registers) < 2)
307 return false;
308 break;
309 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000310 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000311 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000312 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000313 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000314 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000315 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000316 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000317 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000318 // Instead of return false, let's handle the following case as well,
319 // which amounts to pushing one reg onto the full descending stacks.
320 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000321 break;
322 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000323 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000324 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000325 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000326 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000327 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000328 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000329 default:
330 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000331 }
Johnny Chence1ca772011-01-25 01:13:00 +0000332 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000333 addr_t addr = sp - sp_offset;
334 uint32_t i;
335
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000336 EmulateInstruction::Context context;
337 context.type = EmulateInstruction::eContextPushRegisterOnStack;
338 Register dwarf_reg;
339 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000340 Register sp_reg;
341 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000342 for (i=0; i<15; ++i)
343 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000344 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000345 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000346 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000347 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000348 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000349 if (!success)
350 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000351 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000352 return false;
353 addr += addr_byte_size;
354 }
355 }
356
Johnny Chen7c1bf922011-02-08 23:49:37 +0000357 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000358 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000359 dwarf_reg.num = dwarf_pc;
360 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000361 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000362 if (!success)
363 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000364 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000365 return false;
366 }
367
368 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000369 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000370
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000371 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000372 return false;
373 }
374 return true;
375}
376
Johnny Chenef85e912011-01-31 23:07:40 +0000377// Pop Multiple Registers loads multiple registers from the stack, loading from
378// consecutive memory locations staring at the address in SP, and updates
379// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000380bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000381EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000382{
383#if 0
384 // ARM pseudo code...
385 if (ConditionPassed())
386 {
387 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
388 address = SP;
389 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000390 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000391 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000392 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000393 if UnalignedAllowed then
394 LoadWritePC(MemU[address,4]);
395 else
396 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000397 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
398 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000399 }
400#endif
401
402 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000403
Greg Clayton7bc39082011-03-24 23:53:38 +0000404 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000405 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000406 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000407 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000408 if (!success)
409 return false;
410 uint32_t registers = 0;
411 uint32_t Rt; // the destination register
412 switch (encoding) {
413 case eEncodingT1:
414 registers = Bits32(opcode, 7, 0);
415 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000416 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000417 registers |= (1u << 15);
418 // if BitCount(registers) < 1 then UNPREDICTABLE;
419 if (BitCount(registers) < 1)
420 return false;
421 break;
422 case eEncodingT2:
423 // Ignore bit 13.
424 registers = Bits32(opcode, 15, 0) & ~0x2000;
425 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000426 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000428 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
429 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
430 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000431 break;
432 case eEncodingT3:
433 Rt = Bits32(opcode, 15, 12);
434 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000435 if (Rt == 13)
436 return false;
437 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000438 return false;
439 registers = (1u << Rt);
440 break;
441 case eEncodingA1:
442 registers = Bits32(opcode, 15, 0);
443 // Instead of return false, let's handle the following case as well,
444 // which amounts to popping one reg from the full descending stacks.
445 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
446
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000447 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000448 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000449 return false;
450 break;
451 case eEncodingA2:
452 Rt = Bits32(opcode, 15, 12);
453 // if t == 13 then UNPREDICTABLE;
454 if (Rt == dwarf_sp)
455 return false;
456 registers = (1u << Rt);
457 break;
458 default:
459 return false;
460 }
461 addr_t sp_offset = addr_byte_size * BitCount (registers);
462 addr_t addr = sp;
463 uint32_t i, data;
464
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000465 EmulateInstruction::Context context;
466 context.type = EmulateInstruction::eContextPopRegisterOffStack;
467 Register dwarf_reg;
468 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000469 Register sp_reg;
470 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000471 for (i=0; i<15; ++i)
472 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000473 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000474 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000475 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000476 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000477 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000478 if (!success)
479 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000480 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000481 return false;
482 addr += addr_byte_size;
483 }
484 }
485
Johnny Chen7c1bf922011-02-08 23:49:37 +0000486 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000487 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000488 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000489 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000490 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000491 if (!success)
492 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000493 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000494 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000495 return false;
496 addr += addr_byte_size;
497 }
498
499 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000500 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000501
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000503 return false;
504 }
505 return true;
506}
507
Johnny Chen5b442b72011-01-27 19:34:30 +0000508// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000509// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000511EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000512{
513#if 0
514 // ARM pseudo code...
515 if (ConditionPassed())
516 {
517 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000518 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000519 if d == 15 then
520 ALUWritePC(result); // setflags is always FALSE here
521 else
522 R[d] = result;
523 if setflags then
524 APSR.N = result<31>;
525 APSR.Z = IsZeroBit(result);
526 APSR.C = carry;
527 APSR.V = overflow;
528 }
529#endif
530
531 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000532
Greg Clayton7bc39082011-03-24 23:53:38 +0000533 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000534 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000535 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000536 if (!success)
537 return false;
538 uint32_t Rd; // the destination register
539 uint32_t imm32;
540 switch (encoding) {
541 case eEncodingT1:
542 Rd = 7;
543 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
544 break;
545 case eEncodingA1:
546 Rd = Bits32(opcode, 15, 12);
547 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
548 break;
549 default:
550 return false;
551 }
552 addr_t sp_offset = imm32;
553 addr_t addr = sp + sp_offset; // a pointer to the stack area
554
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000555 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +0000556 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000557 Register sp_reg;
558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
559 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000560
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000562 return false;
563 }
564 return true;
565}
566
Johnny Chen2ccad832011-01-28 19:57:25 +0000567// Set r7 or ip to the current stack pointer.
568// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000570EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000571{
572#if 0
573 // ARM pseudo code...
574 if (ConditionPassed())
575 {
576 EncodingSpecificOperations();
577 result = R[m];
578 if d == 15 then
579 ALUWritePC(result); // setflags is always FALSE here
580 else
581 R[d] = result;
582 if setflags then
583 APSR.N = result<31>;
584 APSR.Z = IsZeroBit(result);
585 // APSR.C unchanged
586 // APSR.V unchanged
587 }
588#endif
589
590 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000591
Greg Clayton7bc39082011-03-24 23:53:38 +0000592 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000593 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000594 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000595 if (!success)
596 return false;
597 uint32_t Rd; // the destination register
598 switch (encoding) {
599 case eEncodingT1:
600 Rd = 7;
601 break;
602 case eEncodingA1:
603 Rd = 12;
604 break;
605 default:
606 return false;
607 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000608
609 EmulateInstruction::Context context;
610 context.type = EmulateInstruction::eContextRegisterPlusOffset;
611 Register sp_reg;
612 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
613 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000614
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000616 return false;
617 }
618 return true;
619}
620
Johnny Chen1c13b622011-01-29 00:11:15 +0000621// Move from high register (r8-r15) to low register (r0-r7).
622// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000623bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000624EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000625{
Greg Clayton7bc39082011-03-24 23:53:38 +0000626 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000627}
628
629// Move from register to register.
630// MOV (register)
631bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000632EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000633{
Johnny Chen1c13b622011-01-29 00:11:15 +0000634#if 0
635 // ARM pseudo code...
636 if (ConditionPassed())
637 {
638 EncodingSpecificOperations();
639 result = R[m];
640 if d == 15 then
641 ALUWritePC(result); // setflags is always FALSE here
642 else
643 R[d] = result;
644 if setflags then
645 APSR.N = result<31>;
646 APSR.Z = IsZeroBit(result);
647 // APSR.C unchanged
648 // APSR.V unchanged
649 }
650#endif
651
652 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000653
Greg Clayton7bc39082011-03-24 23:53:38 +0000654 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000655 {
656 uint32_t Rm; // the source register
657 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000658 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000659 switch (encoding) {
660 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000661 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000662 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000663 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000664 if (Rd == 15 && InITBlock() && !LastInITBlock())
665 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000666 break;
667 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000668 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000669 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000670 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000671 if (InITBlock())
672 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000673 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000674 case eEncodingT3:
675 Rd = Bits32(opcode, 11, 8);
676 Rm = Bits32(opcode, 3, 0);
677 setflags = BitIsSet(opcode, 20);
678 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
679 if (setflags && (BadReg(Rd) || BadReg(Rm)))
680 return false;
681 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
682 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
683 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000684 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000685 case eEncodingA1:
686 Rd = Bits32(opcode, 15, 12);
687 Rm = Bits32(opcode, 3, 0);
688 setflags = BitIsSet(opcode, 20);
689 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
690 // TODO: Emulate SUBS PC, LR and related instructions.
691 if (Rd == 15 && setflags)
692 return false;
693 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000694 default:
695 return false;
696 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000697 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000698 if (!success)
699 return false;
700
701 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000702 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000703 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000704 Register dwarf_reg;
705 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000706 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000707
Johnny Chen10530c22011-02-17 22:37:12 +0000708 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000709 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000710 }
711 return true;
712}
713
Johnny Chen357c30f2011-02-14 22:04:25 +0000714// Move (immediate) writes an immediate value to the destination register. It
715// can optionally update the condition flags based on the value.
716// MOV (immediate)
717bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000718EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000719{
720#if 0
721 // ARM pseudo code...
722 if (ConditionPassed())
723 {
724 EncodingSpecificOperations();
725 result = imm32;
726 if d == 15 then // Can only occur for ARM encoding
727 ALUWritePC(result); // setflags is always FALSE here
728 else
729 R[d] = result;
730 if setflags then
731 APSR.N = result<31>;
732 APSR.Z = IsZeroBit(result);
733 APSR.C = carry;
734 // APSR.V unchanged
735 }
736#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000737
Greg Clayton7bc39082011-03-24 23:53:38 +0000738 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000739 {
740 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000741 uint32_t imm32; // the immediate value to be written to Rd
742 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
743 bool setflags;
744 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000745 case eEncodingT1:
746 Rd = Bits32(opcode, 10, 8);
747 setflags = !InITBlock();
748 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
749 carry = APSR_C;
750
751 break;
752
753 case eEncodingT2:
754 Rd = Bits32(opcode, 11, 8);
755 setflags = BitIsSet(opcode, 20);
756 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
757 if (BadReg(Rd))
758 return false;
759
760 break;
761
762 case eEncodingT3:
763 {
764 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
765 Rd = Bits32 (opcode, 11, 8);
766 setflags = false;
767 uint32_t imm4 = Bits32 (opcode, 19, 16);
768 uint32_t imm3 = Bits32 (opcode, 14, 12);
769 uint32_t i = Bit32 (opcode, 26);
770 uint32_t imm8 = Bits32 (opcode, 7, 0);
771 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
772
773 // if BadReg(d) then UNPREDICTABLE;
774 if (BadReg (Rd))
775 return false;
776 }
777 break;
778
779 case eEncodingA1:
780 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
781 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
782 Rd = Bits32 (opcode, 15, 12);
783 setflags = BitIsSet (opcode, 20);
784 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
785
786 break;
787
788 case eEncodingA2:
789 {
790 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
791 Rd = Bits32 (opcode, 15, 12);
792 setflags = false;
793 uint32_t imm4 = Bits32 (opcode, 19, 16);
794 uint32_t imm12 = Bits32 (opcode, 11, 0);
795 imm32 = (imm4 << 12) | imm12;
796
797 // if d == 15 then UNPREDICTABLE;
798 if (Rd == 15)
799 return false;
800 }
801 break;
802
803 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000804 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000805 }
806 uint32_t result = imm32;
807
808 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000809 EmulateInstruction::Context context;
810 context.type = EmulateInstruction::eContextImmediate;
811 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000812
Johnny Chen10530c22011-02-17 22:37:12 +0000813 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000814 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000815 }
816 return true;
817}
818
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000819// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
820// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
821// unsigned values.
822//
823// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
824// limited to only a few forms of the instruction.
825bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000826EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000827{
828#if 0
829 if ConditionPassed() then
830 EncodingSpecificOperations();
831 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
832 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
833 result = operand1 * operand2;
834 R[d] = result<31:0>;
835 if setflags then
836 APSR.N = result<31>;
837 APSR.Z = IsZeroBit(result);
838 if ArchVersion() == 4 then
839 APSR.C = bit UNKNOWN;
840 // else APSR.C unchanged
841 // APSR.V always unchanged
842#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000843
Greg Clayton7bc39082011-03-24 23:53:38 +0000844 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000845 {
846 uint32_t d;
847 uint32_t n;
848 uint32_t m;
849 bool setflags;
850
851 // EncodingSpecificOperations();
852 switch (encoding)
853 {
854 case eEncodingT1:
855 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
856 d = Bits32 (opcode, 2, 0);
857 n = Bits32 (opcode, 5, 3);
858 m = Bits32 (opcode, 2, 0);
859 setflags = !InITBlock();
860
861 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
862 if ((ArchVersion() < ARMv6) && (d == n))
863 return false;
864
865 break;
866
867 case eEncodingT2:
868 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
869 d = Bits32 (opcode, 11, 8);
870 n = Bits32 (opcode, 19, 16);
871 m = Bits32 (opcode, 3, 0);
872 setflags = false;
873
874 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
875 if (BadReg (d) || BadReg (n) || BadReg (m))
876 return false;
877
878 break;
879
880 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000881 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000882 d = Bits32 (opcode, 19, 16);
883 n = Bits32 (opcode, 3, 0);
884 m = Bits32 (opcode, 11, 8);
885 setflags = BitIsSet (opcode, 20);
886
887 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
888 if ((d == 15) || (n == 15) || (m == 15))
889 return false;
890
891 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
892 if ((ArchVersion() < ARMv6) && (d == n))
893 return false;
894
895 break;
896
897 default:
898 return false;
899 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000900
901 bool success = false;
902
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000903 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
904 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
905 if (!success)
906 return false;
907
908 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
909 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
910 if (!success)
911 return false;
912
913 // result = operand1 * operand2;
914 uint64_t result = operand1 * operand2;
915
916 // R[d] = result<31:0>;
917 Register op1_reg;
918 Register op2_reg;
919 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
920 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
921
922 EmulateInstruction::Context context;
923 context.type = eContextMultiplication;
924 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
925
926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
927 return false;
928
929 // if setflags then
930 if (setflags)
931 {
932 // APSR.N = result<31>;
933 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000934 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000935 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
936 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000937 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000938 {
939 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
940 return false;
941 }
942
943 // if ArchVersion() == 4 then
944 // APSR.C = bit UNKNOWN;
945 }
946 }
947 return true;
948}
949
Johnny Chend642a6a2011-02-22 01:01:03 +0000950// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
951// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000952bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000953EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000954{
955#if 0
956 // ARM pseudo code...
957 if (ConditionPassed())
958 {
959 EncodingSpecificOperations();
960 result = NOT(imm32);
961 if d == 15 then // Can only occur for ARM encoding
962 ALUWritePC(result); // setflags is always FALSE here
963 else
964 R[d] = result;
965 if setflags then
966 APSR.N = result<31>;
967 APSR.Z = IsZeroBit(result);
968 APSR.C = carry;
969 // APSR.V unchanged
970 }
971#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000972
Greg Clayton7bc39082011-03-24 23:53:38 +0000973 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000974 {
975 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000976 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
977 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000978 bool setflags;
979 switch (encoding) {
980 case eEncodingT1:
981 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000982 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000984 break;
985 case eEncodingA1:
986 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000987 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000988 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
989 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
990 // TODO: Emulate SUBS PC, LR and related instructions.
991 if (Rd == 15 && setflags)
992 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000993 break;
994 default:
995 return false;
996 }
997 uint32_t result = ~imm32;
998
999 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001000 EmulateInstruction::Context context;
1001 context.type = EmulateInstruction::eContextImmediate;
1002 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001003
Johnny Chen10530c22011-02-17 22:37:12 +00001004 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001005 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001006 }
1007 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001008}
1009
Johnny Chend642a6a2011-02-22 01:01:03 +00001010// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1011// It can optionally update the condition flags based on the result.
1012bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001013EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001014{
1015#if 0
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1018 {
1019 EncodingSpecificOperations();
1020 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1021 result = NOT(shifted);
1022 if d == 15 then // Can only occur for ARM encoding
1023 ALUWritePC(result); // setflags is always FALSE here
1024 else
1025 R[d] = result;
1026 if setflags then
1027 APSR.N = result<31>;
1028 APSR.Z = IsZeroBit(result);
1029 APSR.C = carry;
1030 // APSR.V unchanged
1031 }
1032#endif
1033
Greg Clayton7bc39082011-03-24 23:53:38 +00001034 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001035 {
1036 uint32_t Rm; // the source register
1037 uint32_t Rd; // the destination register
1038 ARM_ShifterType shift_t;
1039 uint32_t shift_n; // the shift applied to the value read from Rm
1040 bool setflags;
1041 uint32_t carry; // the carry bit after the shift operation
1042 switch (encoding) {
1043 case eEncodingT1:
1044 Rd = Bits32(opcode, 2, 0);
1045 Rm = Bits32(opcode, 5, 3);
1046 setflags = !InITBlock();
1047 shift_t = SRType_LSL;
1048 shift_n = 0;
1049 if (InITBlock())
1050 return false;
1051 break;
1052 case eEncodingT2:
1053 Rd = Bits32(opcode, 11, 8);
1054 Rm = Bits32(opcode, 3, 0);
1055 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001056 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001057 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001058 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001059 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001060 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001061 case eEncodingA1:
1062 Rd = Bits32(opcode, 15, 12);
1063 Rm = Bits32(opcode, 3, 0);
1064 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001065 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001066 break;
1067 default:
1068 return false;
1069 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001070 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001071 uint32_t value = ReadCoreReg(Rm, &success);
1072 if (!success)
1073 return false;
1074
1075 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1076 uint32_t result = ~shifted;
1077
1078 // The context specifies that an immediate is to be moved into Rd.
1079 EmulateInstruction::Context context;
1080 context.type = EmulateInstruction::eContextImmediate;
1081 context.SetNoArgs ();
1082
1083 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1084 return false;
1085 }
1086 return true;
1087}
1088
Johnny Chen788e0552011-01-27 22:52:23 +00001089// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1090// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001091bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001092EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001093{
1094#if 0
1095 // ARM pseudo code...
1096 if (ConditionPassed())
1097 {
1098 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1099 base = Align(PC,4);
1100 address = if add then (base + imm32) else (base - imm32);
1101 data = MemU[address,4];
1102 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001103 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1104 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001105 R[t] = data;
1106 else // Can only apply before ARMv7
1107 if CurrentInstrSet() == InstrSet_ARM then
1108 R[t] = ROR(data, 8*UInt(address<1:0>));
1109 else
1110 R[t] = bits(32) UNKNOWN;
1111 }
1112#endif
1113
Greg Clayton7bc39082011-03-24 23:53:38 +00001114 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001115 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001116 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001117 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001118 if (!success)
1119 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001120
1121 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001122 EmulateInstruction::Context context;
1123 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1124 Register pc_reg;
1125 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1126 context.SetRegisterPlusOffset (pc_reg, 0);
1127
Johnny Chenc9de9102011-02-11 19:12:30 +00001128 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001129 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001130 bool add; // +imm32 or -imm32?
1131 addr_t base; // the base address
1132 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001133 uint32_t data; // the literal data value from the PC relative load
1134 switch (encoding) {
1135 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001136 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001137 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001138 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001139 break;
1140 case eEncodingT2:
1141 Rt = Bits32(opcode, 15, 12);
1142 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1143 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001144 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001145 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001146 break;
1147 default:
1148 return false;
1149 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001150
Johnny Chene39f22d2011-02-19 01:36:13 +00001151 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001152 if (add)
1153 address = base + imm32;
1154 else
1155 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001156
1157 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001158 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001159 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001160 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001161
1162 if (Rt == 15)
1163 {
1164 if (Bits32(address, 1, 0) == 0)
1165 {
1166 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001167 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001168 return false;
1169 }
1170 else
1171 return false;
1172 }
1173 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1174 {
1175 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1176 return false;
1177 }
1178 else // We don't handle ARM for now.
1179 return false;
1180
Johnny Chen788e0552011-01-27 22:52:23 +00001181 }
1182 return true;
1183}
1184
Johnny Chen5b442b72011-01-27 19:34:30 +00001185// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001186// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001187bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001188EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001189{
1190#if 0
1191 // ARM pseudo code...
1192 if (ConditionPassed())
1193 {
1194 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001195 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001196 if d == 15 then // Can only occur for ARM encoding
1197 ALUWritePC(result); // setflags is always FALSE here
1198 else
1199 R[d] = result;
1200 if setflags then
1201 APSR.N = result<31>;
1202 APSR.Z = IsZeroBit(result);
1203 APSR.C = carry;
1204 APSR.V = overflow;
1205 }
1206#endif
1207
1208 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001209
Greg Clayton7bc39082011-03-24 23:53:38 +00001210 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001211 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001212 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001213 if (!success)
1214 return false;
1215 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001216 uint32_t d;
1217 bool setflags;
1218 switch (encoding)
1219 {
1220 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001221 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001222 d = Bits32 (opcode, 10, 8);
1223 setflags = false;
1224 imm32 = (Bits32 (opcode, 7, 0) << 2);
1225
1226 break;
1227
1228 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001229 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001230 d = 13;
1231 setflags = false;
1232 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1233
1234 break;
1235
1236 default:
1237 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001238 }
1239 addr_t sp_offset = imm32;
1240 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1241
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001242 EmulateInstruction::Context context;
1243 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice080bf612011-04-05 18:46:00 +00001244 Register sp_reg;
1245 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1246 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001247
Caroline Ticee2212882011-03-22 22:38:28 +00001248 if (d == 15)
1249 {
1250 if (!ALUWritePC (context, addr))
1251 return false;
1252 }
1253 else
1254 {
1255 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1256 return false;
1257 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001258 }
1259 return true;
1260}
1261
1262// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001263// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001265EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001266{
1267#if 0
1268 // ARM pseudo code...
1269 if (ConditionPassed())
1270 {
1271 EncodingSpecificOperations();
1272 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001273 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001274 if d == 15 then
1275 ALUWritePC(result); // setflags is always FALSE here
1276 else
1277 R[d] = result;
1278 if setflags then
1279 APSR.N = result<31>;
1280 APSR.Z = IsZeroBit(result);
1281 APSR.C = carry;
1282 APSR.V = overflow;
1283 }
1284#endif
1285
1286 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001287
Greg Clayton7bc39082011-03-24 23:53:38 +00001288 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001289 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001290 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001291 if (!success)
1292 return false;
1293 uint32_t Rm; // the second operand
1294 switch (encoding) {
1295 case eEncodingT2:
1296 Rm = Bits32(opcode, 6, 3);
1297 break;
1298 default:
1299 return false;
1300 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001301 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001302 if (!success)
1303 return false;
1304
1305 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1306
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001307 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00001308 context.type = EmulateInstruction::eContextAddition;
1309 Register sp_reg;
1310 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1311 Register other_reg;
1312 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1313 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001314
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001315 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001316 return false;
1317 }
1318 return true;
1319}
1320
Johnny Chen9b8d7832011-02-02 01:13:56 +00001321// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1322// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1323// from Thumb to ARM.
1324// BLX (immediate)
1325bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001326EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001327{
1328#if 0
1329 // ARM pseudo code...
1330 if (ConditionPassed())
1331 {
1332 EncodingSpecificOperations();
1333 if CurrentInstrSet() == InstrSet_ARM then
1334 LR = PC - 4;
1335 else
1336 LR = PC<31:1> : '1';
1337 if targetInstrSet == InstrSet_ARM then
1338 targetAddress = Align(PC,4) + imm32;
1339 else
1340 targetAddress = PC + imm32;
1341 SelectInstrSet(targetInstrSet);
1342 BranchWritePC(targetAddress);
1343 }
1344#endif
1345
Greg Clayton7bc39082011-03-24 23:53:38 +00001346 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001347
Greg Clayton7bc39082011-03-24 23:53:38 +00001348 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001349 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001350 EmulateInstruction::Context context;
1351 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001352 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001353 if (!success)
1354 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001355 addr_t lr; // next instruction address
1356 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001357 int32_t imm32; // PC-relative offset
1358 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001359 case eEncodingT1:
1360 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001361 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001362 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001363 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001364 uint32_t J1 = Bit32(opcode, 13);
1365 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001366 uint32_t imm11 = Bits32(opcode, 10, 0);
1367 uint32_t I1 = !(J1 ^ S);
1368 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001369 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001370 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001371 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001372 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001373 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001374 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001375 break;
1376 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001377 case eEncodingT2:
1378 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001380 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001382 uint32_t J1 = Bit32(opcode, 13);
1383 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001384 uint32_t imm10L = Bits32(opcode, 10, 1);
1385 uint32_t I1 = !(J1 ^ S);
1386 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001387 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001389 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001390 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001391 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001392 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001393 break;
1394 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001395 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001396 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001397 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001398 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001399 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001400 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001401 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001402 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001403 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001404 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001405 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001406 break;
1407 default:
1408 return false;
1409 }
1410 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1411 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001412 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001413 return false;
1414 }
1415 return true;
1416}
1417
1418// Branch with Link and Exchange (register) calls a subroutine at an address and
1419// instruction set specified by a register.
1420// BLX (register)
1421bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001422EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001423{
1424#if 0
1425 // ARM pseudo code...
1426 if (ConditionPassed())
1427 {
1428 EncodingSpecificOperations();
1429 target = R[m];
1430 if CurrentInstrSet() == InstrSet_ARM then
1431 next_instr_addr = PC - 4;
1432 LR = next_instr_addr;
1433 else
1434 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001435 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001436 BXWritePC(target);
1437 }
1438#endif
1439
1440 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001441
Greg Clayton7bc39082011-03-24 23:53:38 +00001442 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001443 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001444 EmulateInstruction::Context context;
1445 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001446 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001447 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001448 if (!success)
1449 return false;
1450 uint32_t Rm; // the register with the target address
1451 switch (encoding) {
1452 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001453 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001454 Rm = Bits32(opcode, 6, 3);
1455 // if m == 15 then UNPREDICTABLE;
1456 if (Rm == 15)
1457 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001458 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001459 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001460 break;
1461 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001462 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 Rm = Bits32(opcode, 3, 0);
1464 // if m == 15 then UNPREDICTABLE;
1465 if (Rm == 15)
1466 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001467 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001468 default:
1469 return false;
1470 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001471 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001472 if (!success)
1473 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001474 Register dwarf_reg;
1475 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1476 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001477 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1478 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001479 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001480 return false;
1481 }
1482 return true;
1483}
1484
Johnny Chenab3b3512011-02-12 00:10:51 +00001485// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001486bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001487EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001488{
1489#if 0
1490 // ARM pseudo code...
1491 if (ConditionPassed())
1492 {
1493 EncodingSpecificOperations();
1494 BXWritePC(R[m]);
1495 }
1496#endif
1497
Greg Clayton7bc39082011-03-24 23:53:38 +00001498 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001499 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001500 EmulateInstruction::Context context;
1501 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001502 uint32_t Rm; // the register with the target address
1503 switch (encoding) {
1504 case eEncodingT1:
1505 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001506 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001507 return false;
1508 break;
1509 case eEncodingA1:
1510 Rm = Bits32(opcode, 3, 0);
1511 break;
1512 default:
1513 return false;
1514 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001515 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001516 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001517 if (!success)
1518 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001519
1520 Register dwarf_reg;
1521 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001522 context.SetRegister (dwarf_reg);
1523 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001524 return false;
1525 }
1526 return true;
1527}
1528
Johnny Chen59e6ab72011-02-24 21:01:20 +00001529// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1530// address and instruction set specified by a register as though it were a BX instruction.
1531//
1532// TODO: Emulate Jazelle architecture?
1533// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1534bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001535EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001536{
1537#if 0
1538 // ARM pseudo code...
1539 if (ConditionPassed())
1540 {
1541 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001542 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001543 BXWritePC(R[m]);
1544 else
1545 if JazelleAcceptsExecution() then
1546 SwitchToJazelleExecution();
1547 else
1548 SUBARCHITECTURE_DEFINED handler call;
1549 }
1550#endif
1551
Greg Clayton7bc39082011-03-24 23:53:38 +00001552 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001553 {
1554 EmulateInstruction::Context context;
1555 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1556 uint32_t Rm; // the register with the target address
1557 switch (encoding) {
1558 case eEncodingT1:
1559 Rm = Bits32(opcode, 19, 16);
1560 if (BadReg(Rm))
1561 return false;
1562 if (InITBlock() && !LastInITBlock())
1563 return false;
1564 break;
1565 case eEncodingA1:
1566 Rm = Bits32(opcode, 3, 0);
1567 if (Rm == 15)
1568 return false;
1569 break;
1570 default:
1571 return false;
1572 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001573 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001574 addr_t target = ReadCoreReg (Rm, &success);
1575 if (!success)
1576 return false;
1577
1578 Register dwarf_reg;
1579 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1580 context.SetRegister (dwarf_reg);
1581 if (!BXWritePC(context, target))
1582 return false;
1583 }
1584 return true;
1585}
1586
Johnny Chen0d0148e2011-01-28 02:26:08 +00001587// Set r7 to point to some ip offset.
1588// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001589bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001590EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001591{
1592#if 0
1593 // ARM pseudo code...
1594 if (ConditionPassed())
1595 {
1596 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001597 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001598 if d == 15 then // Can only occur for ARM encoding
1599 ALUWritePC(result); // setflags is always FALSE here
1600 else
1601 R[d] = result;
1602 if setflags then
1603 APSR.N = result<31>;
1604 APSR.Z = IsZeroBit(result);
1605 APSR.C = carry;
1606 APSR.V = overflow;
1607 }
1608#endif
1609
Greg Clayton7bc39082011-03-24 23:53:38 +00001610 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001611 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001612 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001613 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001614 if (!success)
1615 return false;
1616 uint32_t imm32;
1617 switch (encoding) {
1618 case eEncodingA1:
1619 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1620 break;
1621 default:
1622 return false;
1623 }
1624 addr_t ip_offset = imm32;
1625 addr_t addr = ip - ip_offset; // the adjusted ip value
1626
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001627 EmulateInstruction::Context context;
1628 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1629 Register dwarf_reg;
1630 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1631 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001632
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001633 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001634 return false;
1635 }
1636 return true;
1637}
1638
1639// Set ip to point to some stack offset.
1640// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001642EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001649 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001650 if d == 15 then // Can only occur for ARM encoding
1651 ALUWritePC(result); // setflags is always FALSE here
1652 else
1653 R[d] = result;
1654 if setflags then
1655 APSR.N = result<31>;
1656 APSR.Z = IsZeroBit(result);
1657 APSR.C = carry;
1658 APSR.V = overflow;
1659 }
1660#endif
1661
Greg Clayton7bc39082011-03-24 23:53:38 +00001662 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001663 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001664 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001665 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001666 if (!success)
1667 return false;
1668 uint32_t imm32;
1669 switch (encoding) {
1670 case eEncodingA1:
1671 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1672 break;
1673 default:
1674 return false;
1675 }
1676 addr_t sp_offset = imm32;
1677 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1678
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679 EmulateInstruction::Context context;
1680 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1681 Register dwarf_reg;
1682 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1683 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001684
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001685 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001686 return false;
1687 }
1688 return true;
1689}
1690
Johnny Chenc9e747f2011-02-23 01:55:07 +00001691// This instruction subtracts an immediate value from the SP value, and writes
1692// the result to the destination register.
1693//
1694// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001695bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001696EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001697{
1698#if 0
1699 // ARM pseudo code...
1700 if (ConditionPassed())
1701 {
1702 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001703 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001704 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001705 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001706 else
1707 R[d] = result;
1708 if setflags then
1709 APSR.N = result<31>;
1710 APSR.Z = IsZeroBit(result);
1711 APSR.C = carry;
1712 APSR.V = overflow;
1713 }
1714#endif
1715
1716 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001717 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001718 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001719 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001720 if (!success)
1721 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001722
1723 uint32_t Rd;
1724 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001725 uint32_t imm32;
1726 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001727 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001728 Rd = 13;
1729 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001730 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001731 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001732 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001733 Rd = Bits32(opcode, 11, 8);
1734 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001735 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001736 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001737 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001738 if (Rd == 15 && !setflags)
1739 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001740 break;
1741 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001742 Rd = Bits32(opcode, 11, 8);
1743 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001744 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001745 if (Rd == 15)
1746 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001747 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001748 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001749 Rd = Bits32(opcode, 15, 12);
1750 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001751 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001752 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1753 // TODO: Emulate SUBS PC, LR and related instructions.
1754 if (Rd == 15 && setflags)
1755 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001756 break;
1757 default:
1758 return false;
1759 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001760 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1761
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001762 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001763 if (Rd == 13)
1764 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001765 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1766 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001767 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001768 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001769 }
1770 else
1771 {
1772 context.type = EmulateInstruction::eContextImmediate;
1773 context.SetNoArgs ();
1774 }
1775
1776 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001777 return false;
1778 }
1779 return true;
1780}
1781
Johnny Chen08c25e82011-01-31 18:02:28 +00001782// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001783bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001784EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001785{
1786#if 0
1787 // ARM pseudo code...
1788 if (ConditionPassed())
1789 {
1790 EncodingSpecificOperations();
1791 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1792 address = if index then offset_addr else R[n];
1793 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1794 if wback then R[n] = offset_addr;
1795 }
1796#endif
1797
1798 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001799
Greg Clayton7bc39082011-03-24 23:53:38 +00001800 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001801 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001802 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001803 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001804 if (!success)
1805 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001806 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001807 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001808 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1809
1810 bool index;
1811 bool add;
1812 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001813 switch (encoding) {
1814 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001815 Rt = Bits32(opcode, 15, 12);
1816 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001817 Rn = Bits32 (opcode, 19, 16);
1818
1819 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1820 return false;
1821
1822 index = BitIsSet (opcode, 24);
1823 add = BitIsSet (opcode, 23);
1824 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1825
1826 if (wback && ((Rn == 15) || (Rn == Rt)))
1827 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001828 break;
1829 default:
1830 return false;
1831 }
Caroline Tice3e407972011-03-18 19:41:00 +00001832 addr_t offset_addr;
1833 if (add)
1834 offset_addr = sp + imm12;
1835 else
1836 offset_addr = sp - imm12;
1837
1838 addr_t addr;
1839 if (index)
1840 addr = offset_addr;
1841 else
1842 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001843
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001844 EmulateInstruction::Context context;
1845 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001846 Register sp_reg;
1847 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1848 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001849 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001850 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001851 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001852 if (!success)
1853 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001854 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001855 return false;
1856 }
1857 else
1858 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001859 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001860 if (!success)
1861 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001862 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001863 return false;
1864 }
1865
Caroline Tice3e407972011-03-18 19:41:00 +00001866
1867 if (wback)
1868 {
1869 context.type = EmulateInstruction::eContextAdjustStackPointer;
1870 context.SetImmediateSigned (addr - sp);
1871 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1872 return false;
1873 }
Johnny Chence1ca772011-01-25 01:13:00 +00001874 }
1875 return true;
1876}
1877
Johnny Chen08c25e82011-01-31 18:02:28 +00001878// Vector Push stores multiple extension registers to the stack.
1879// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001880bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001881EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001882{
1883#if 0
1884 // ARM pseudo code...
1885 if (ConditionPassed())
1886 {
1887 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1888 address = SP - imm32;
1889 SP = SP - imm32;
1890 if single_regs then
1891 for r = 0 to regs-1
1892 MemA[address,4] = S[d+r]; address = address+4;
1893 else
1894 for r = 0 to regs-1
1895 // Store as two word-aligned words in the correct order for current endianness.
1896 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1897 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1898 address = address+8;
1899 }
1900#endif
1901
1902 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001903
Greg Clayton7bc39082011-03-24 23:53:38 +00001904 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001905 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001906 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001907 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001908 if (!success)
1909 return false;
1910 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001911 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001912 uint32_t imm32; // stack offset
1913 uint32_t regs; // number of registers
1914 switch (encoding) {
1915 case eEncodingT1:
1916 case eEncodingA1:
1917 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001918 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001919 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1920 // If UInt(imm8) is odd, see "FSTMX".
1921 regs = Bits32(opcode, 7, 0) / 2;
1922 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1923 if (regs == 0 || regs > 16 || (d + regs) > 32)
1924 return false;
1925 break;
1926 case eEncodingT2:
1927 case eEncodingA2:
1928 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001929 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001930 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1931 regs = Bits32(opcode, 7, 0);
1932 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1933 if (regs == 0 || regs > 16 || (d + regs) > 32)
1934 return false;
1935 break;
1936 default:
1937 return false;
1938 }
1939 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1940 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1941 addr_t sp_offset = imm32;
1942 addr_t addr = sp - sp_offset;
1943 uint32_t i;
1944
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001945 EmulateInstruction::Context context;
1946 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1947 Register dwarf_reg;
1948 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001949 Register sp_reg;
1950 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1951 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001952 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001953 dwarf_reg.num = start_reg + d + i;
1954 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001955 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001956 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001957 if (!success)
1958 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001959 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 return false;
1961 addr += reg_byte_size;
1962 }
1963
1964 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001965 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001966
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001967 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001968 return false;
1969 }
1970 return true;
1971}
1972
Johnny Chen587a0a42011-02-01 18:35:28 +00001973// Vector Pop loads multiple extension registers from the stack.
1974// It also updates SP to point just above the loaded data.
1975bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001976EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001977{
1978#if 0
1979 // ARM pseudo code...
1980 if (ConditionPassed())
1981 {
1982 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1983 address = SP;
1984 SP = SP + imm32;
1985 if single_regs then
1986 for r = 0 to regs-1
1987 S[d+r] = MemA[address,4]; address = address+4;
1988 else
1989 for r = 0 to regs-1
1990 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1991 // Combine the word-aligned words in the correct order for current endianness.
1992 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1993 }
1994#endif
1995
1996 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001997
Greg Clayton7bc39082011-03-24 23:53:38 +00001998 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001999 {
2000 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002001 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002002 if (!success)
2003 return false;
2004 bool single_regs;
2005 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2006 uint32_t imm32; // stack offset
2007 uint32_t regs; // number of registers
2008 switch (encoding) {
2009 case eEncodingT1:
2010 case eEncodingA1:
2011 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002012 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002013 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2014 // If UInt(imm8) is odd, see "FLDMX".
2015 regs = Bits32(opcode, 7, 0) / 2;
2016 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2017 if (regs == 0 || regs > 16 || (d + regs) > 32)
2018 return false;
2019 break;
2020 case eEncodingT2:
2021 case eEncodingA2:
2022 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002023 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002024 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2025 regs = Bits32(opcode, 7, 0);
2026 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2027 if (regs == 0 || regs > 16 || (d + regs) > 32)
2028 return false;
2029 break;
2030 default:
2031 return false;
2032 }
2033 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2034 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2035 addr_t sp_offset = imm32;
2036 addr_t addr = sp;
2037 uint32_t i;
2038 uint64_t data; // uint64_t to accomodate 64-bit registers.
2039
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002040 EmulateInstruction::Context context;
2041 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2042 Register dwarf_reg;
2043 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002044 Register sp_reg;
2045 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
2046 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002047 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002048 dwarf_reg.num = start_reg + d + i;
2049 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002050 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002051 if (!success)
2052 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002053 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002054 return false;
2055 addr += reg_byte_size;
2056 }
2057
2058 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002059 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002060
2061 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2062 return false;
2063 }
2064 return true;
2065}
2066
Johnny Chenb77be412011-02-04 00:40:18 +00002067// SVC (previously SWI)
2068bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002069EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002070{
2071#if 0
2072 // ARM pseudo code...
2073 if (ConditionPassed())
2074 {
2075 EncodingSpecificOperations();
2076 CallSupervisor();
2077 }
2078#endif
2079
2080 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002081
Greg Clayton7bc39082011-03-24 23:53:38 +00002082 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002083 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002084 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002085 addr_t lr; // next instruction address
2086 if (!success)
2087 return false;
2088 uint32_t imm32; // the immediate constant
2089 uint32_t mode; // ARM or Thumb mode
2090 switch (encoding) {
2091 case eEncodingT1:
2092 lr = (pc + 2) | 1u; // return address
2093 imm32 = Bits32(opcode, 7, 0);
2094 mode = eModeThumb;
2095 break;
2096 case eEncodingA1:
2097 lr = pc + 4; // return address
2098 imm32 = Bits32(opcode, 23, 0);
2099 mode = eModeARM;
2100 break;
2101 default:
2102 return false;
2103 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002104
2105 EmulateInstruction::Context context;
2106 context.type = EmulateInstruction::eContextSupervisorCall;
2107 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002108 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2109 return false;
2110 }
2111 return true;
2112}
2113
Johnny Chenc315f862011-02-05 00:46:10 +00002114// If Then makes up to four following instructions (the IT block) conditional.
2115bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002116EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002117{
2118#if 0
2119 // ARM pseudo code...
2120 EncodingSpecificOperations();
2121 ITSTATE.IT<7:0> = firstcond:mask;
2122#endif
2123
Johnny Chenc315f862011-02-05 00:46:10 +00002124 m_it_session.InitIT(Bits32(opcode, 7, 0));
2125 return true;
2126}
2127
Johnny Chen3b620b32011-02-07 20:11:47 +00002128// Branch causes a branch to a target address.
2129bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002130EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002131{
2132#if 0
2133 // ARM pseudo code...
2134 if (ConditionPassed())
2135 {
2136 EncodingSpecificOperations();
2137 BranchWritePC(PC + imm32);
2138 }
2139#endif
2140
2141 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002142
Greg Clayton7bc39082011-03-24 23:53:38 +00002143 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002144 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002145 EmulateInstruction::Context context;
2146 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002147 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002148 if (!success)
2149 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002150 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002151 int32_t imm32; // PC-relative offset
2152 switch (encoding) {
2153 case eEncodingT1:
2154 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2155 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002156 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002157 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002158 break;
2159 case eEncodingT2:
2160 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002161 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002162 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002163 break;
2164 case eEncodingT3:
2165 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2166 {
Johnny Chenbd599902011-02-10 21:39:01 +00002167 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002168 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002169 uint32_t J1 = Bit32(opcode, 13);
2170 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002171 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002172 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002173 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002174 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002175 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 break;
2177 }
2178 case eEncodingT4:
2179 {
Johnny Chenbd599902011-02-10 21:39:01 +00002180 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002181 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002182 uint32_t J1 = Bit32(opcode, 13);
2183 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002184 uint32_t imm11 = Bits32(opcode, 10, 0);
2185 uint32_t I1 = !(J1 ^ S);
2186 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002187 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002188 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002189 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002190 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002191 break;
2192 }
2193 case eEncodingA1:
2194 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002195 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002196 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002197 break;
2198 default:
2199 return false;
2200 }
2201 if (!BranchWritePC(context, target))
2202 return false;
2203 }
2204 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002205}
2206
Johnny Chen53ebab72011-02-08 23:21:57 +00002207// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2208// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2209// CBNZ, CBZ
2210bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002211EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002212{
2213#if 0
2214 // ARM pseudo code...
2215 EncodingSpecificOperations();
2216 if nonzero ^ IsZero(R[n]) then
2217 BranchWritePC(PC + imm32);
2218#endif
2219
2220 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002221
2222 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002223 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002224 if (!success)
2225 return false;
2226
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002227 EmulateInstruction::Context context;
2228 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002229 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002230 if (!success)
2231 return false;
2232
2233 addr_t target; // target address
2234 uint32_t imm32; // PC-relative offset to branch forward
2235 bool nonzero;
2236 switch (encoding) {
2237 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002238 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002239 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002240 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002241 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002242 break;
2243 default:
2244 return false;
2245 }
2246 if (nonzero ^ (reg_val == 0))
2247 if (!BranchWritePC(context, target))
2248 return false;
2249
2250 return true;
2251}
2252
Johnny Chen60299ec2011-02-17 19:34:27 +00002253// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2254// A base register provides a pointer to the table, and a second register supplies an index into the table.
2255// The branch length is twice the value of the byte returned from the table.
2256//
2257// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2258// A base register provides a pointer to the table, and a second register supplies an index into the table.
2259// The branch length is twice the value of the halfword returned from the table.
2260// TBB, TBH
2261bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002262EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002263{
2264#if 0
2265 // ARM pseudo code...
2266 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2267 if is_tbh then
2268 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2269 else
2270 halfwords = UInt(MemU[R[n]+R[m], 1]);
2271 BranchWritePC(PC + 2*halfwords);
2272#endif
2273
2274 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002275
2276 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2277 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2278 bool is_tbh; // true if table branch halfword
2279 switch (encoding) {
2280 case eEncodingT1:
2281 Rn = Bits32(opcode, 19, 16);
2282 Rm = Bits32(opcode, 3, 0);
2283 is_tbh = BitIsSet(opcode, 4);
2284 if (Rn == 13 || BadReg(Rm))
2285 return false;
2286 if (InITBlock() && !LastInITBlock())
2287 return false;
2288 break;
2289 default:
2290 return false;
2291 }
2292
2293 // Read the address of the table from the operand register Rn.
2294 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002295 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002296 if (!success)
2297 return false;
2298
2299 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002300 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002301 if (!success)
2302 return false;
2303
2304 // the offsetted table address
2305 addr_t addr = base + (is_tbh ? index*2 : index);
2306
2307 // PC-relative offset to branch forward
2308 EmulateInstruction::Context context;
2309 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002310 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002311 if (!success)
2312 return false;
2313
Johnny Chene39f22d2011-02-19 01:36:13 +00002314 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002315 if (!success)
2316 return false;
2317
2318 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002319 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002320 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2321 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2322
2323 if (!BranchWritePC(context, target))
2324 return false;
2325
2326 return true;
2327}
2328
Caroline Ticedcc11b32011-03-02 23:57:02 +00002329// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2330// It can optionally update the condition flags based on the result.
2331bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002332EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002333{
2334#if 0
2335 if ConditionPassed() then
2336 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002337 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002338 R[d] = result;
2339 if setflags then
2340 APSR.N = result<31>;
2341 APSR.Z = IsZeroBit(result);
2342 APSR.C = carry;
2343 APSR.V = overflow;
2344#endif
2345
2346 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002347
Greg Clayton7bc39082011-03-24 23:53:38 +00002348 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002349 {
2350 uint32_t d;
2351 uint32_t n;
2352 bool setflags;
2353 uint32_t imm32;
2354 uint32_t carry_out;
2355
2356 //EncodingSpecificOperations();
2357 switch (encoding)
2358 {
2359 case eEncodingT1:
2360 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2361 d = Bits32 (opcode, 2, 0);
2362 n = Bits32 (opcode, 5, 3);
2363 setflags = !InITBlock();
2364 imm32 = Bits32 (opcode, 8,6);
2365
2366 break;
2367
2368 case eEncodingT2:
2369 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2370 d = Bits32 (opcode, 10, 8);
2371 n = Bits32 (opcode, 10, 8);
2372 setflags = !InITBlock();
2373 imm32 = Bits32 (opcode, 7, 0);
2374
2375 break;
2376
2377 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002378 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2379 // if Rn == '1101' then SEE ADD (SP plus immediate);
2380 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002381 d = Bits32 (opcode, 11, 8);
2382 n = Bits32 (opcode, 19, 16);
2383 setflags = BitIsSet (opcode, 20);
2384 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2385
2386 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2387 if (BadReg (d) || (n == 15))
2388 return false;
2389
2390 break;
2391
2392 case eEncodingT4:
2393 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002394 // if Rn == '1111' then SEE ADR;
2395 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002396 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2397 d = Bits32 (opcode, 11, 8);
2398 n = Bits32 (opcode, 19, 16);
2399 setflags = false;
2400 uint32_t i = Bit32 (opcode, 26);
2401 uint32_t imm3 = Bits32 (opcode, 14, 12);
2402 uint32_t imm8 = Bits32 (opcode, 7, 0);
2403 imm32 = (i << 11) | (imm3 << 8) | imm8;
2404
2405 // if BadReg(d) then UNPREDICTABLE;
2406 if (BadReg (d))
2407 return false;
2408
2409 break;
2410 }
2411 default:
2412 return false;
2413 }
2414
2415 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2416 if (!success)
2417 return false;
2418
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002419 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002420 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2421
2422 Register reg_n;
2423 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2424
2425 EmulateInstruction::Context context;
2426 context.type = eContextAddition;
2427 context.SetRegisterPlusOffset (reg_n, imm32);
2428
2429 //R[d] = result;
2430 //if setflags then
2431 //APSR.N = result<31>;
2432 //APSR.Z = IsZeroBit(result);
2433 //APSR.C = carry;
2434 //APSR.V = overflow;
2435 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2436 return false;
2437
2438 }
2439 return true;
2440}
2441
Johnny Chen8fa20592011-02-18 01:22:22 +00002442// This instruction adds an immediate value to a register value, and writes the result to the destination
2443// register. It can optionally update the condition flags based on the result.
2444bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002445EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002446{
2447#if 0
2448 // ARM pseudo code...
2449 if ConditionPassed() then
2450 EncodingSpecificOperations();
2451 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2452 if d == 15 then
2453 ALUWritePC(result); // setflags is always FALSE here
2454 else
2455 R[d] = result;
2456 if setflags then
2457 APSR.N = result<31>;
2458 APSR.Z = IsZeroBit(result);
2459 APSR.C = carry;
2460 APSR.V = overflow;
2461#endif
2462
2463 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002464
Greg Clayton7bc39082011-03-24 23:53:38 +00002465 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002466 {
2467 uint32_t Rd, Rn;
2468 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2469 bool setflags;
2470 switch (encoding)
2471 {
2472 case eEncodingA1:
2473 Rd = Bits32(opcode, 15, 12);
2474 Rn = Bits32(opcode, 19, 16);
2475 setflags = BitIsSet(opcode, 20);
2476 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2477 break;
2478 default:
2479 return false;
2480 }
2481
Johnny Chen8fa20592011-02-18 01:22:22 +00002482 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002483 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002484 if (!success)
2485 return false;
2486
2487 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2488
2489 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00002490 context.type = EmulateInstruction::eContextAddition;
2491 Register dwarf_reg;
2492 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn);
2493 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002494
2495 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2496 return false;
2497 }
2498 return true;
2499}
2500
Johnny Chend761dcf2011-02-17 22:03:29 +00002501// This instruction adds a register value and an optionally-shifted register value, and writes the result
2502// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002503bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002504EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002505{
2506#if 0
2507 // ARM pseudo code...
2508 if ConditionPassed() then
2509 EncodingSpecificOperations();
2510 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2511 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2512 if d == 15 then
2513 ALUWritePC(result); // setflags is always FALSE here
2514 else
2515 R[d] = result;
2516 if setflags then
2517 APSR.N = result<31>;
2518 APSR.Z = IsZeroBit(result);
2519 APSR.C = carry;
2520 APSR.V = overflow;
2521#endif
2522
2523 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002524
Greg Clayton7bc39082011-03-24 23:53:38 +00002525 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002526 {
2527 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002528 ARM_ShifterType shift_t;
2529 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002530 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002531 switch (encoding)
2532 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002533 case eEncodingT1:
2534 Rd = Bits32(opcode, 2, 0);
2535 Rn = Bits32(opcode, 5, 3);
2536 Rm = Bits32(opcode, 8, 6);
2537 setflags = !InITBlock();
2538 shift_t = SRType_LSL;
2539 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002540 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002541 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002542 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002543 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002544 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002545 shift_t = SRType_LSL;
2546 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002547 if (Rn == 15 && Rm == 15)
2548 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002549 if (Rd == 15 && InITBlock() && !LastInITBlock())
2550 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002551 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002552 case eEncodingA1:
2553 Rd = Bits32(opcode, 15, 12);
2554 Rn = Bits32(opcode, 19, 16);
2555 Rm = Bits32(opcode, 3, 0);
2556 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002557 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002558 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002559 default:
2560 return false;
2561 }
2562
Johnny Chen26863dc2011-02-09 23:43:29 +00002563 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002564 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002565 if (!success)
2566 return false;
2567
2568 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002569 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002570 if (!success)
2571 return false;
2572
Johnny Chene97c0d52011-02-18 19:32:20 +00002573 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002574 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002575
2576 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002577 context.type = EmulateInstruction::eContextAddition;
2578 Register op1_reg;
2579 Register op2_reg;
2580 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2581 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2582 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002583
Johnny Chen10530c22011-02-17 22:37:12 +00002584 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002585 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002586 }
2587 return true;
2588}
2589
Johnny Chen34075cb2011-02-22 01:56:31 +00002590// Compare Negative (immediate) adds a register value and an immediate value.
2591// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002592bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002593EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002594{
2595#if 0
2596 // ARM pseudo code...
2597 if ConditionPassed() then
2598 EncodingSpecificOperations();
2599 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2600 APSR.N = result<31>;
2601 APSR.Z = IsZeroBit(result);
2602 APSR.C = carry;
2603 APSR.V = overflow;
2604#endif
2605
2606 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002607
2608 uint32_t Rn; // the first operand
2609 uint32_t imm32; // the immediate value to be compared with
2610 switch (encoding) {
2611 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002612 Rn = Bits32(opcode, 19, 16);
2613 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2614 if (Rn == 15)
2615 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002616 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002617 case eEncodingA1:
2618 Rn = Bits32(opcode, 19, 16);
2619 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2620 break;
2621 default:
2622 return false;
2623 }
2624 // Read the register value from the operand register Rn.
2625 uint32_t reg_val = ReadCoreReg(Rn, &success);
2626 if (!success)
2627 return false;
2628
Johnny Chen078fbc62011-02-22 19:48:22 +00002629 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002630
2631 EmulateInstruction::Context context;
2632 context.type = EmulateInstruction::eContextImmediate;
2633 context.SetNoArgs ();
2634 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2635 return false;
2636
2637 return true;
2638}
2639
2640// Compare Negative (register) adds a register value and an optionally-shifted register value.
2641// It updates the condition flags based on the result, and discards the result.
2642bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002643EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002644{
2645#if 0
2646 // ARM pseudo code...
2647 if ConditionPassed() then
2648 EncodingSpecificOperations();
2649 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2650 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2651 APSR.N = result<31>;
2652 APSR.Z = IsZeroBit(result);
2653 APSR.C = carry;
2654 APSR.V = overflow;
2655#endif
2656
2657 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002658
2659 uint32_t Rn; // the first operand
2660 uint32_t Rm; // the second operand
2661 ARM_ShifterType shift_t;
2662 uint32_t shift_n; // the shift applied to the value read from Rm
2663 switch (encoding) {
2664 case eEncodingT1:
2665 Rn = Bits32(opcode, 2, 0);
2666 Rm = Bits32(opcode, 5, 3);
2667 shift_t = SRType_LSL;
2668 shift_n = 0;
2669 break;
2670 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002671 Rn = Bits32(opcode, 19, 16);
2672 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002673 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002674 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2675 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002676 return false;
2677 break;
2678 case eEncodingA1:
2679 Rn = Bits32(opcode, 19, 16);
2680 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002681 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002682 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002683 default:
2684 return false;
2685 }
2686 // Read the register value from register Rn.
2687 uint32_t val1 = ReadCoreReg(Rn, &success);
2688 if (!success)
2689 return false;
2690
2691 // Read the register value from register Rm.
2692 uint32_t val2 = ReadCoreReg(Rm, &success);
2693 if (!success)
2694 return false;
2695
2696 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002697 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002698
2699 EmulateInstruction::Context context;
2700 context.type = EmulateInstruction::eContextImmediate;
2701 context.SetNoArgs();
2702 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2703 return false;
2704
2705 return true;
2706}
2707
2708// Compare (immediate) subtracts an immediate value from a register value.
2709// It updates the condition flags based on the result, and discards the result.
2710bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002711EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002712{
2713#if 0
2714 // ARM pseudo code...
2715 if ConditionPassed() then
2716 EncodingSpecificOperations();
2717 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2718 APSR.N = result<31>;
2719 APSR.Z = IsZeroBit(result);
2720 APSR.C = carry;
2721 APSR.V = overflow;
2722#endif
2723
2724 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002725
2726 uint32_t Rn; // the first operand
2727 uint32_t imm32; // the immediate value to be compared with
2728 switch (encoding) {
2729 case eEncodingT1:
2730 Rn = Bits32(opcode, 10, 8);
2731 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002732 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002733 case eEncodingT2:
2734 Rn = Bits32(opcode, 19, 16);
2735 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2736 if (Rn == 15)
2737 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002738 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002739 case eEncodingA1:
2740 Rn = Bits32(opcode, 19, 16);
2741 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002742 break;
2743 default:
2744 return false;
2745 }
2746 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002747 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002748 if (!success)
2749 return false;
2750
Johnny Chen10530c22011-02-17 22:37:12 +00002751 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2752
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002753 EmulateInstruction::Context context;
2754 context.type = EmulateInstruction::eContextImmediate;
2755 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002756 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2757 return false;
2758
Johnny Chend4dc4442011-02-11 02:02:56 +00002759 return true;
2760}
2761
Johnny Chen34075cb2011-02-22 01:56:31 +00002762// Compare (register) subtracts an optionally-shifted register value from a register value.
2763// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002764bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002765EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002766{
2767#if 0
2768 // ARM pseudo code...
2769 if ConditionPassed() then
2770 EncodingSpecificOperations();
2771 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2772 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2773 APSR.N = result<31>;
2774 APSR.Z = IsZeroBit(result);
2775 APSR.C = carry;
2776 APSR.V = overflow;
2777#endif
2778
2779 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002780
2781 uint32_t Rn; // the first operand
2782 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002783 ARM_ShifterType shift_t;
2784 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002785 switch (encoding) {
2786 case eEncodingT1:
2787 Rn = Bits32(opcode, 2, 0);
2788 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002789 shift_t = SRType_LSL;
2790 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002791 break;
2792 case eEncodingT2:
2793 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2794 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002795 shift_t = SRType_LSL;
2796 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002797 if (Rn < 8 && Rm < 8)
2798 return false;
2799 if (Rn == 15 || Rm == 15)
2800 return false;
2801 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002802 case eEncodingA1:
2803 Rn = Bits32(opcode, 19, 16);
2804 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002805 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002806 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002807 default:
2808 return false;
2809 }
2810 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002811 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002812 if (!success)
2813 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002814
Johnny Chene4a4d302011-02-11 21:53:58 +00002815 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002816 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002817 if (!success)
2818 return false;
2819
Johnny Chen34075cb2011-02-22 01:56:31 +00002820 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2821 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002822
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002823 EmulateInstruction::Context context;
2824 context.type = EmulateInstruction::eContextImmediate;
2825 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002826 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2827 return false;
2828
Johnny Chene4a4d302011-02-11 21:53:58 +00002829 return true;
2830}
2831
Johnny Chen82f16aa2011-02-15 20:10:55 +00002832// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2833// shifting in copies of its sign bit, and writes the result to the destination register. It can
2834// optionally update the condition flags based on the result.
2835bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002836EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002837{
2838#if 0
2839 // ARM pseudo code...
2840 if ConditionPassed() then
2841 EncodingSpecificOperations();
2842 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2843 if d == 15 then // Can only occur for ARM encoding
2844 ALUWritePC(result); // setflags is always FALSE here
2845 else
2846 R[d] = result;
2847 if setflags then
2848 APSR.N = result<31>;
2849 APSR.Z = IsZeroBit(result);
2850 APSR.C = carry;
2851 // APSR.V unchanged
2852#endif
2853
Greg Clayton7bc39082011-03-24 23:53:38 +00002854 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002855}
2856
2857// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2858// shifting in copies of its sign bit, and writes the result to the destination register.
2859// The variable number of bits is read from the bottom byte of a register. It can optionally update
2860// the condition flags based on the result.
2861bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002862EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002863{
2864#if 0
2865 // ARM pseudo code...
2866 if ConditionPassed() then
2867 EncodingSpecificOperations();
2868 shift_n = UInt(R[m]<7:0>);
2869 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2870 R[d] = result;
2871 if setflags then
2872 APSR.N = result<31>;
2873 APSR.Z = IsZeroBit(result);
2874 APSR.C = carry;
2875 // APSR.V unchanged
2876#endif
2877
Greg Clayton7bc39082011-03-24 23:53:38 +00002878 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002879}
2880
2881// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2882// shifting in zeros, and writes the result to the destination register. It can optionally
2883// update the condition flags based on the result.
2884bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002885EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002886{
2887#if 0
2888 // ARM pseudo code...
2889 if ConditionPassed() then
2890 EncodingSpecificOperations();
2891 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2892 if d == 15 then // Can only occur for ARM encoding
2893 ALUWritePC(result); // setflags is always FALSE here
2894 else
2895 R[d] = result;
2896 if setflags then
2897 APSR.N = result<31>;
2898 APSR.Z = IsZeroBit(result);
2899 APSR.C = carry;
2900 // APSR.V unchanged
2901#endif
2902
Greg Clayton7bc39082011-03-24 23:53:38 +00002903 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002904}
2905
2906// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2907// shifting in zeros, and writes the result to the destination register. The variable number
2908// of bits is read from the bottom byte of a register. It can optionally update the condition
2909// flags based on the result.
2910bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002911EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002912{
2913#if 0
2914 // ARM pseudo code...
2915 if ConditionPassed() then
2916 EncodingSpecificOperations();
2917 shift_n = UInt(R[m]<7:0>);
2918 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2919 R[d] = result;
2920 if setflags then
2921 APSR.N = result<31>;
2922 APSR.Z = IsZeroBit(result);
2923 APSR.C = carry;
2924 // APSR.V unchanged
2925#endif
2926
Greg Clayton7bc39082011-03-24 23:53:38 +00002927 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002928}
2929
2930// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2931// shifting in zeros, and writes the result to the destination register. It can optionally
2932// update the condition flags based on the result.
2933bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002934EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002935{
2936#if 0
2937 // ARM pseudo code...
2938 if ConditionPassed() then
2939 EncodingSpecificOperations();
2940 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2941 if d == 15 then // Can only occur for ARM encoding
2942 ALUWritePC(result); // setflags is always FALSE here
2943 else
2944 R[d] = result;
2945 if setflags then
2946 APSR.N = result<31>;
2947 APSR.Z = IsZeroBit(result);
2948 APSR.C = carry;
2949 // APSR.V unchanged
2950#endif
2951
Greg Clayton7bc39082011-03-24 23:53:38 +00002952 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002953}
2954
2955// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2956// shifting in zeros, and writes the result to the destination register. The variable number
2957// of bits is read from the bottom byte of a register. It can optionally update the condition
2958// flags based on the result.
2959bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002960EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002961{
2962#if 0
2963 // ARM pseudo code...
2964 if ConditionPassed() then
2965 EncodingSpecificOperations();
2966 shift_n = UInt(R[m]<7:0>);
2967 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2968 R[d] = result;
2969 if setflags then
2970 APSR.N = result<31>;
2971 APSR.Z = IsZeroBit(result);
2972 APSR.C = carry;
2973 // APSR.V unchanged
2974#endif
2975
Greg Clayton7bc39082011-03-24 23:53:38 +00002976 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002977}
2978
Johnny Cheneeab4852011-02-16 22:14:44 +00002979// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2980// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2981// It can optionally update the condition flags based on the result.
2982bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002983EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002984{
2985#if 0
2986 // ARM pseudo code...
2987 if ConditionPassed() then
2988 EncodingSpecificOperations();
2989 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2990 if d == 15 then // Can only occur for ARM encoding
2991 ALUWritePC(result); // setflags is always FALSE here
2992 else
2993 R[d] = result;
2994 if setflags then
2995 APSR.N = result<31>;
2996 APSR.Z = IsZeroBit(result);
2997 APSR.C = carry;
2998 // APSR.V unchanged
2999#endif
3000
Greg Clayton7bc39082011-03-24 23:53:38 +00003001 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003002}
3003
3004// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3005// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3006// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3007// flags based on the result.
3008bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003009EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003010{
3011#if 0
3012 // ARM pseudo code...
3013 if ConditionPassed() then
3014 EncodingSpecificOperations();
3015 shift_n = UInt(R[m]<7:0>);
3016 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3017 R[d] = result;
3018 if setflags then
3019 APSR.N = result<31>;
3020 APSR.Z = IsZeroBit(result);
3021 APSR.C = carry;
3022 // APSR.V unchanged
3023#endif
3024
Greg Clayton7bc39082011-03-24 23:53:38 +00003025 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003026}
3027
3028// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3029// with the carry flag shifted into bit [31].
3030//
3031// RRX can optionally update the condition flags based on the result.
3032// In that case, bit [0] is shifted into the carry flag.
3033bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003034EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003035{
3036#if 0
3037 // ARM pseudo code...
3038 if ConditionPassed() then
3039 EncodingSpecificOperations();
3040 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3041 if d == 15 then // Can only occur for ARM encoding
3042 ALUWritePC(result); // setflags is always FALSE here
3043 else
3044 R[d] = result;
3045 if setflags then
3046 APSR.N = result<31>;
3047 APSR.Z = IsZeroBit(result);
3048 APSR.C = carry;
3049 // APSR.V unchanged
3050#endif
3051
Greg Clayton7bc39082011-03-24 23:53:38 +00003052 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003053}
3054
Johnny Chen41a0a152011-02-16 01:27:54 +00003055bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003056EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003057{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003058 assert(shift_type == SRType_ASR
3059 || shift_type == SRType_LSL
3060 || shift_type == SRType_LSR
3061 || shift_type == SRType_ROR
3062 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003063
Johnny Chen82f16aa2011-02-15 20:10:55 +00003064 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003065
Greg Clayton7bc39082011-03-24 23:53:38 +00003066 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003067 {
Johnny Chene7f89532011-02-15 23:22:46 +00003068 uint32_t Rd; // the destination register
3069 uint32_t Rm; // the first operand register
3070 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003071 uint32_t carry; // the carry bit after the shift operation
3072 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003073
3074 // Special case handling!
3075 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003076 ARMEncoding use_encoding = encoding;
3077 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003078 {
3079 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3080 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003081 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003082 }
3083
Greg Clayton7bc39082011-03-24 23:53:38 +00003084 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003085 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003086 // Due to the above special case handling!
3087 assert(shift_type != SRType_ROR);
3088
Johnny Chen82f16aa2011-02-15 20:10:55 +00003089 Rd = Bits32(opcode, 2, 0);
3090 Rm = Bits32(opcode, 5, 3);
3091 setflags = !InITBlock();
3092 imm5 = Bits32(opcode, 10, 6);
3093 break;
3094 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003095 // A8.6.141 RRX
3096 assert(shift_type != SRType_RRX);
3097
Johnny Chen82f16aa2011-02-15 20:10:55 +00003098 Rd = Bits32(opcode, 11, 8);
3099 Rm = Bits32(opcode, 3, 0);
3100 setflags = BitIsSet(opcode, 20);
3101 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3102 if (BadReg(Rd) || BadReg(Rm))
3103 return false;
3104 break;
3105 case eEncodingA1:
3106 Rd = Bits32(opcode, 15, 12);
3107 Rm = Bits32(opcode, 3, 0);
3108 setflags = BitIsSet(opcode, 20);
3109 imm5 = Bits32(opcode, 11, 7);
3110 break;
3111 default:
3112 return false;
3113 }
3114
Johnny Cheneeab4852011-02-16 22:14:44 +00003115 // A8.6.139 ROR (immediate)
3116 if (shift_type == SRType_ROR && imm5 == 0)
3117 shift_type = SRType_RRX;
3118
Johnny Chen82f16aa2011-02-15 20:10:55 +00003119 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003120 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003121 if (!success)
3122 return false;
3123
Johnny Cheneeab4852011-02-16 22:14:44 +00003124 // Decode the shift amount if not RRX.
3125 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003126
Johnny Chene97c0d52011-02-18 19:32:20 +00003127 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003128
3129 // The context specifies that an immediate is to be moved into Rd.
3130 EmulateInstruction::Context context;
3131 context.type = EmulateInstruction::eContextImmediate;
3132 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003133
Johnny Chen10530c22011-02-17 22:37:12 +00003134 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003135 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003136 }
3137 return true;
3138}
3139
Johnny Chene7f89532011-02-15 23:22:46 +00003140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003141EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003142{
Johnny Chen41a0a152011-02-16 01:27:54 +00003143 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003144
3145 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003146
Greg Clayton7bc39082011-03-24 23:53:38 +00003147 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003148 {
3149 uint32_t Rd; // the destination register
3150 uint32_t Rn; // the first operand register
3151 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3152 uint32_t carry; // the carry bit after the shift operation
3153 bool setflags;
3154 switch (encoding) {
3155 case eEncodingT1:
3156 Rd = Bits32(opcode, 2, 0);
3157 Rn = Rd;
3158 Rm = Bits32(opcode, 5, 3);
3159 setflags = !InITBlock();
3160 break;
3161 case eEncodingT2:
3162 Rd = Bits32(opcode, 11, 8);
3163 Rn = Bits32(opcode, 19, 16);
3164 Rm = Bits32(opcode, 3, 0);
3165 setflags = BitIsSet(opcode, 20);
3166 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3167 return false;
3168 break;
3169 case eEncodingA1:
3170 Rd = Bits32(opcode, 15, 12);
3171 Rn = Bits32(opcode, 3, 0);
3172 Rm = Bits32(opcode, 11, 8);
3173 setflags = BitIsSet(opcode, 20);
3174 if (Rd == 15 || Rn == 15 || Rm == 15)
3175 return false;
3176 break;
3177 default:
3178 return false;
3179 }
3180
3181 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003182 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003183 if (!success)
3184 return false;
3185 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003186 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003187 if (!success)
3188 return false;
3189
3190 // Get the shift amount.
3191 uint32_t amt = Bits32(val, 7, 0);
3192
Johnny Chene97c0d52011-02-18 19:32:20 +00003193 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003194
3195 // The context specifies that an immediate is to be moved into Rd.
3196 EmulateInstruction::Context context;
3197 context.type = EmulateInstruction::eContextImmediate;
3198 context.SetNoArgs ();
3199
Johnny Chen10530c22011-02-17 22:37:12 +00003200 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003201 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003202 }
3203 return true;
3204}
3205
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003206// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003207// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003208// can be written back to the base register.
3209bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003210EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003211{
3212#if 0
3213 // ARM pseudo code...
3214 if ConditionPassed()
3215 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3216 address = R[n];
3217
3218 for i = 0 to 14
3219 if registers<i> == '1' then
3220 R[i] = MemA[address, 4]; address = address + 4;
3221 if registers<15> == '1' then
3222 LoadWritePC (MemA[address, 4]);
3223
3224 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3225 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3226
3227#endif
3228
3229 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003230
Greg Clayton7bc39082011-03-24 23:53:38 +00003231 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003232 {
3233 uint32_t n;
3234 uint32_t registers = 0;
3235 bool wback;
3236 const uint32_t addr_byte_size = GetAddressByteSize();
3237 switch (encoding)
3238 {
3239 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003240 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003241 n = Bits32 (opcode, 10, 8);
3242 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003243 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244 wback = BitIsClear (registers, n);
3245 // if BitCount(registers) < 1 then UNPREDICTABLE;
3246 if (BitCount(registers) < 1)
3247 return false;
3248 break;
3249 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003250 // if W == '1' && Rn == '1101' then SEE POP;
3251 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003252 n = Bits32 (opcode, 19, 16);
3253 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003254 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003256
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003257 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003258 if ((n == 15)
3259 || (BitCount (registers) < 2)
3260 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3261 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003262
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003263 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003264 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003265 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003266
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003267 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268 if (wback
3269 && BitIsSet (registers, n))
3270 return false;
3271 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003272
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003273 case eEncodingA1:
3274 n = Bits32 (opcode, 19, 16);
3275 registers = Bits32 (opcode, 15, 0);
3276 wback = BitIsSet (opcode, 21);
3277 if ((n == 15)
3278 || (BitCount (registers) < 1))
3279 return false;
3280 break;
3281 default:
3282 return false;
3283 }
3284
3285 int32_t offset = 0;
3286 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3287 if (!success)
3288 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003289
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003290 EmulateInstruction::Context context;
3291 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3292 Register dwarf_reg;
3293 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3294 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003295
3296 for (int i = 0; i < 14; ++i)
3297 {
3298 if (BitIsSet (registers, i))
3299 {
Caroline Tice85aab332011-02-08 23:56:10 +00003300 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003301 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302 if (wback && (n == 13)) // Pop Instruction
3303 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3304
3305 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003306 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003307 if (!success)
3308 return false;
3309
3310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3311 return false;
3312
3313 offset += addr_byte_size;
3314 }
3315 }
3316
3317 if (BitIsSet (registers, 15))
3318 {
3319 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003320 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003321 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003322 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003323 if (!success)
3324 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003325 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003326 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003327 return false;
3328 }
3329
3330 if (wback && BitIsClear (registers, n))
3331 {
Caroline Ticefa172202011-02-11 22:49:54 +00003332 // R[n] = R[n] + 4 * BitCount (registers)
3333 int32_t offset = addr_byte_size * BitCount (registers);
3334 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003335 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003336
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3338 return false;
3339 }
3340 if (wback && BitIsSet (registers, n))
3341 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003342 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003343 }
3344 return true;
3345}
Caroline Tice713c2662011-02-11 17:59:55 +00003346
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003347// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3348// The consecutive memory locations end at this address and the address just below the lowest of those locations
3349// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003350bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003351EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003352{
3353#if 0
3354 // ARM pseudo code...
3355 if ConditionPassed() then
3356 EncodingSpecificOperations();
3357 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003358
Caroline Tice713c2662011-02-11 17:59:55 +00003359 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003360 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003361 R[i] = MemA[address,4]; address = address + 4;
3362
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003363 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003364 LoadWritePC(MemA[address,4]);
3365
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003366 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3367 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003368#endif
3369
3370 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003371
Greg Clayton7bc39082011-03-24 23:53:38 +00003372 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003373 {
3374 uint32_t n;
3375 uint32_t registers = 0;
3376 bool wback;
3377 const uint32_t addr_byte_size = GetAddressByteSize();
3378
3379 // EncodingSpecificOperations();
3380 switch (encoding)
3381 {
3382 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003383 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003384 n = Bits32 (opcode, 19, 16);
3385 registers = Bits32 (opcode, 15, 0);
3386 wback = BitIsSet (opcode, 21);
3387
3388 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3389 if ((n == 15) || (BitCount (registers) < 1))
3390 return false;
3391
3392 break;
3393
3394 default:
3395 return false;
3396 }
3397 // address = R[n] - 4*BitCount(registers) + 4;
3398
3399 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003400 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003401
3402 if (!success)
3403 return false;
3404
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003405 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003406
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003407 EmulateInstruction::Context context;
3408 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3409 Register dwarf_reg;
3410 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3411 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003412
3413 // for i = 0 to 14
3414 for (int i = 0; i < 14; ++i)
3415 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003416 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003417 if (BitIsSet (registers, i))
3418 {
3419 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003420 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003421 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003422 if (!success)
3423 return false;
3424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3425 return false;
3426 offset += addr_byte_size;
3427 }
3428 }
3429
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003430 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003431 // LoadWritePC(MemA[address,4]);
3432 if (BitIsSet (registers, 15))
3433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003434 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003435 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003436 if (!success)
3437 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003438 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003439 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003440 return false;
3441 }
3442
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003443 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003444 if (wback && BitIsClear (registers, n))
3445 {
Caroline Tice713c2662011-02-11 17:59:55 +00003446 if (!success)
3447 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003448
3449 offset = (addr_byte_size * BitCount (registers)) * -1;
3450 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003451 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003452 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003453 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3454 return false;
3455 }
3456
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003457 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003458 if (wback && BitIsSet (registers, n))
3459 return WriteBits32Unknown (n);
3460 }
3461 return true;
3462}
3463
3464// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3465// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3466// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003467bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003468EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003469{
3470#if 0
3471 // ARM pseudo code...
3472 if ConditionPassed() then
3473 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3474 address = R[n] - 4*BitCount(registers);
3475
3476 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003477 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003478 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003479 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003480 LoadWritePC(MemA[address,4]);
3481
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003482 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3483 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003484#endif
3485
3486 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003487
Greg Clayton7bc39082011-03-24 23:53:38 +00003488 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003489 {
3490 uint32_t n;
3491 uint32_t registers = 0;
3492 bool wback;
3493 const uint32_t addr_byte_size = GetAddressByteSize();
3494 switch (encoding)
3495 {
3496 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003497 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003498 n = Bits32 (opcode, 19, 16);
3499 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003500 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003501 wback = BitIsSet (opcode, 21);
3502
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003503 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003504 if ((n == 15)
3505 || (BitCount (registers) < 2)
3506 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3507 return false;
3508
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003509 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003510 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003511 return false;
3512
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003513 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003514 if (wback && BitIsSet (registers, n))
3515 return false;
3516
3517 break;
3518
3519 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003520 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003521 n = Bits32 (opcode, 19, 16);
3522 registers = Bits32 (opcode, 15, 0);
3523 wback = BitIsSet (opcode, 21);
3524
3525 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3526 if ((n == 15) || (BitCount (registers) < 1))
3527 return false;
3528
3529 break;
3530
3531 default:
3532 return false;
3533 }
3534
Caroline Tice713c2662011-02-11 17:59:55 +00003535 // address = R[n] - 4*BitCount(registers);
3536
Caroline Tice0b29e242011-02-08 23:16:02 +00003537 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003538 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003539
3540 if (!success)
3541 return false;
3542
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003543 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003544 EmulateInstruction::Context context;
3545 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3546 Register dwarf_reg;
3547 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003548 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003549
3550 for (int i = 0; i < 14; ++i)
3551 {
3552 if (BitIsSet (registers, i))
3553 {
3554 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003555 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003556 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003557 if (!success)
3558 return false;
3559
3560 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3561 return false;
3562
3563 offset += addr_byte_size;
3564 }
3565 }
3566
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003567 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003568 // LoadWritePC(MemA[address,4]);
3569 if (BitIsSet (registers, 15))
3570 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003571 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003572 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003573 if (!success)
3574 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003575 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003576 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003577 return false;
3578 }
3579
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003580 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003581 if (wback && BitIsClear (registers, n))
3582 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003583 if (!success)
3584 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003585
3586 offset = (addr_byte_size * BitCount (registers)) * -1;
3587 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003588 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003589 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003590 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3591 return false;
3592 }
3593
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003594 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003595 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003596 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003597 }
3598 return true;
3599}
Caroline Tice85aab332011-02-08 23:56:10 +00003600
Caroline Tice713c2662011-02-11 17:59:55 +00003601// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3602// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3603// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003604bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003605EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003606{
3607#if 0
3608 if ConditionPassed() then
3609 EncodingSpecificOperations();
3610 address = R[n] + 4;
3611
3612 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003613 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003614 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003615 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003616 LoadWritePC(MemA[address,4]);
3617
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003618 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3619 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003620#endif
3621
3622 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003623
Greg Clayton7bc39082011-03-24 23:53:38 +00003624 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003625 {
3626 uint32_t n;
3627 uint32_t registers = 0;
3628 bool wback;
3629 const uint32_t addr_byte_size = GetAddressByteSize();
3630 switch (encoding)
3631 {
3632 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003633 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003634 n = Bits32 (opcode, 19, 16);
3635 registers = Bits32 (opcode, 15, 0);
3636 wback = BitIsSet (opcode, 21);
3637
3638 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3639 if ((n == 15) || (BitCount (registers) < 1))
3640 return false;
3641
3642 break;
3643 default:
3644 return false;
3645 }
3646 // address = R[n] + 4;
3647
3648 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003649 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003650
3651 if (!success)
3652 return false;
3653
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003654 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003655
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003656 EmulateInstruction::Context context;
3657 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3658 Register dwarf_reg;
3659 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3660 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003661
3662 for (int i = 0; i < 14; ++i)
3663 {
3664 if (BitIsSet (registers, i))
3665 {
3666 // R[i] = MemA[address,4]; address = address + 4;
3667
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003668 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003669 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003670 if (!success)
3671 return false;
3672
3673 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3674 return false;
3675
3676 offset += addr_byte_size;
3677 }
3678 }
3679
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003680 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003681 // LoadWritePC(MemA[address,4]);
3682 if (BitIsSet (registers, 15))
3683 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003684 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003685 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003686 if (!success)
3687 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003688 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003689 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003690 return false;
3691 }
3692
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003693 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003694 if (wback && BitIsClear (registers, n))
3695 {
Caroline Tice85aab332011-02-08 23:56:10 +00003696 if (!success)
3697 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003698
3699 offset = addr_byte_size * BitCount (registers);
3700 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003701 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003702 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003703 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3704 return false;
3705 }
3706
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003707 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003708 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003709 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003710 }
3711 return true;
3712}
Caroline Tice0b29e242011-02-08 23:16:02 +00003713
Johnny Chenef21b592011-02-10 01:52:38 +00003714// Load Register (immediate) calculates an address from a base register value and
3715// an immediate offset, loads a word from memory, and writes to a register.
3716// LDR (immediate, Thumb)
3717bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003718EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003719{
3720#if 0
3721 // ARM pseudo code...
3722 if (ConditionPassed())
3723 {
3724 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3726 address = if index then offset_addr else R[n];
3727 data = MemU[address,4];
3728 if wback then R[n] = offset_addr;
3729 if t == 15 then
3730 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3731 elsif UnalignedSupport() || address<1:0> = '00' then
3732 R[t] = data;
3733 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3734 }
3735#endif
3736
3737 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003738
Greg Clayton7bc39082011-03-24 23:53:38 +00003739 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003740 {
3741 uint32_t Rt; // the destination register
3742 uint32_t Rn; // the base register
3743 uint32_t imm32; // the immediate offset used to form the address
3744 addr_t offset_addr; // the offset address
3745 addr_t address; // the calculated address
3746 uint32_t data; // the literal data value from memory load
3747 bool add, index, wback;
3748 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003749 case eEncodingT1:
3750 Rt = Bits32(opcode, 5, 3);
3751 Rn = Bits32(opcode, 2, 0);
3752 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3753 // index = TRUE; add = TRUE; wback = FALSE
3754 add = true;
3755 index = true;
3756 wback = false;
3757
3758 break;
3759
3760 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003761 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003762 Rt = Bits32 (opcode, 10, 8);
3763 Rn = 13;
3764 imm32 = Bits32 (opcode, 7, 0) << 2;
3765
3766 // index = TRUE; add = TRUE; wback = FALSE;
3767 index = true;
3768 add = true;
3769 wback = false;
3770
3771 break;
3772
3773 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003774 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003775 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3776 Rt = Bits32 (opcode, 15, 12);
3777 Rn = Bits32 (opcode, 19, 16);
3778 imm32 = Bits32 (opcode, 11, 0);
3779
3780 // index = TRUE; add = TRUE; wback = FALSE;
3781 index = true;
3782 add = true;
3783 wback = false;
3784
3785 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3786 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3787 return false;
3788
3789 break;
3790
3791 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003792 // if Rn == '1111' then SEE LDR (literal);
3793 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3794 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3795 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003796 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3797 return false;
3798
3799 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3800 Rt = Bits32 (opcode, 15, 12);
3801 Rn = Bits32 (opcode, 19, 16);
3802 imm32 = Bits32 (opcode, 7, 0);
3803
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003804 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003805 index = BitIsSet (opcode, 10);
3806 add = BitIsSet (opcode, 9);
3807 wback = BitIsSet (opcode, 8);
3808
3809 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3810 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3811 return false;
3812
3813 break;
3814
3815 default:
3816 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003817 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003818 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003819 if (!success)
3820 return false;
3821 if (add)
3822 offset_addr = base + imm32;
3823 else
3824 offset_addr = base - imm32;
3825
3826 address = (index ? offset_addr : base);
3827
Caroline Ticebaf1f642011-03-24 19:23:45 +00003828 Register base_reg;
3829 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003830 if (wback)
3831 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003832 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003833 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3834 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003835
Johnny Chenef21b592011-02-10 01:52:38 +00003836 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3837 return false;
3838 }
3839
3840 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003841 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003842 context.type = EmulateInstruction::eContextRegisterLoad;
3843 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003844
3845 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003846 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003847 if (!success)
3848 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003849
3850 if (Rt == 15)
3851 {
3852 if (Bits32(address, 1, 0) == 0)
3853 {
Johnny Chen668b4512011-02-15 21:08:58 +00003854 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003855 return false;
3856 }
3857 else
3858 return false;
3859 }
3860 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3861 {
3862 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3863 return false;
3864 }
3865 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003866 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003867 }
3868 return true;
3869}
3870
Caroline Ticeaf556562011-02-15 18:42:15 +00003871// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3872// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3873// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003874bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003875EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003876{
3877#if 0
3878 if ConditionPassed() then
3879 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3880 address = R[n];
3881
3882 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003883 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003884 if i == n && wback && i != LowestSetBit(registers) then
3885 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3886 else
3887 MemA[address,4] = R[i];
3888 address = address + 4;
3889
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003890 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003891 MemA[address,4] = PCStoreValue();
3892 if wback then R[n] = R[n] + 4*BitCount(registers);
3893#endif
3894
3895 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003896
Greg Clayton7bc39082011-03-24 23:53:38 +00003897 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003898 {
3899 uint32_t n;
3900 uint32_t registers = 0;
3901 bool wback;
3902 const uint32_t addr_byte_size = GetAddressByteSize();
3903
3904 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3905 switch (encoding)
3906 {
3907 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003908 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003909 n = Bits32 (opcode, 10, 8);
3910 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003911 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003912 wback = true;
3913
3914 // if BitCount(registers) < 1 then UNPREDICTABLE;
3915 if (BitCount (registers) < 1)
3916 return false;
3917
3918 break;
3919
3920 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003921 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003922 n = Bits32 (opcode, 19, 16);
3923 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003924 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003925 wback = BitIsSet (opcode, 21);
3926
3927 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3928 if ((n == 15) || (BitCount (registers) < 2))
3929 return false;
3930
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003931 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003932 if (wback && BitIsSet (registers, n))
3933 return false;
3934
3935 break;
3936
3937 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003938 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003939 n = Bits32 (opcode, 19, 16);
3940 registers = Bits32 (opcode, 15, 0);
3941 wback = BitIsSet (opcode, 21);
3942
3943 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3944 if ((n == 15) || (BitCount (registers) < 1))
3945 return false;
3946
3947 break;
3948
3949 default:
3950 return false;
3951 }
3952
3953 // address = R[n];
3954 int32_t offset = 0;
3955 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3956 if (!success)
3957 return false;
3958
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003959 EmulateInstruction::Context context;
3960 context.type = EmulateInstruction::eContextRegisterStore;
3961 Register base_reg;
3962 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003963
3964 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003965 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003966 for (int i = 0; i < 14; ++i)
3967 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003968 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003969 if (BitIsSet (registers, i))
3970 {
3971 if (i < lowest_set_bit)
3972 lowest_set_bit = i;
3973 // if i == n && wback && i != LowestSetBit(registers) then
3974 if ((i == n) && wback && (i != lowest_set_bit))
3975 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3976 WriteBits32UnknownToMemory (address + offset);
3977 else
3978 {
3979 // MemA[address,4] = R[i];
3980 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3981 if (!success)
3982 return false;
3983
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003984 Register data_reg;
3985 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3986 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003987 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003988 return false;
3989 }
3990
3991 // address = address + 4;
3992 offset += addr_byte_size;
3993 }
3994 }
3995
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003996 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003997 // MemA[address,4] = PCStoreValue();
3998 if (BitIsSet (registers, 15))
3999 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004000 Register pc_reg;
4001 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4002 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004003 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004004 if (!success)
4005 return false;
4006
Caroline Tice8d681f52011-03-17 23:50:16 +00004007 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004008 return false;
4009 }
4010
4011 // if wback then R[n] = R[n] + 4*BitCount(registers);
4012 if (wback)
4013 {
4014 offset = addr_byte_size * BitCount (registers);
4015 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004016 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004017 addr_t data = address + offset;
4018 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4019 return false;
4020 }
4021 }
4022 return true;
4023}
4024
Caroline Ticeaf556562011-02-15 18:42:15 +00004025// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4026// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4027// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004028bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004029EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004030{
4031#if 0
4032 if ConditionPassed() then
4033 EncodingSpecificOperations();
4034 address = R[n] - 4*BitCount(registers) + 4;
4035
4036 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004037 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004038 if i == n && wback && i != LowestSetBit(registers) then
4039 MemA[address,4] = bits(32) UNKNOWN;
4040 else
4041 MemA[address,4] = R[i];
4042 address = address + 4;
4043
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004044 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004045 MemA[address,4] = PCStoreValue();
4046
4047 if wback then R[n] = R[n] - 4*BitCount(registers);
4048#endif
4049
4050 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004051
Greg Clayton7bc39082011-03-24 23:53:38 +00004052 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004053 {
4054 uint32_t n;
4055 uint32_t registers = 0;
4056 bool wback;
4057 const uint32_t addr_byte_size = GetAddressByteSize();
4058
4059 // EncodingSpecificOperations();
4060 switch (encoding)
4061 {
4062 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004063 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004064 n = Bits32 (opcode, 19, 16);
4065 registers = Bits32 (opcode, 15, 0);
4066 wback = BitIsSet (opcode, 21);
4067
4068 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4069 if ((n == 15) || (BitCount (registers) < 1))
4070 return false;
4071 break;
4072 default:
4073 return false;
4074 }
4075
4076 // address = R[n] - 4*BitCount(registers) + 4;
4077 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004078 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004079 if (!success)
4080 return false;
4081
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004082 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004083
4084 EmulateInstruction::Context context;
4085 context.type = EmulateInstruction::eContextRegisterStore;
4086 Register base_reg;
4087 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4088
4089 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004090 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004091 for (int i = 0; i < 14; ++i)
4092 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004093 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004094 if (BitIsSet (registers, i))
4095 {
4096 if (i < lowest_bit_set)
4097 lowest_bit_set = i;
4098 //if i == n && wback && i != LowestSetBit(registers) then
4099 if ((i == n) && wback && (i != lowest_bit_set))
4100 // MemA[address,4] = bits(32) UNKNOWN;
4101 WriteBits32UnknownToMemory (address + offset);
4102 else
4103 {
4104 // MemA[address,4] = R[i];
4105 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4106 if (!success)
4107 return false;
4108
4109 Register data_reg;
4110 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004111 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004112 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004113 return false;
4114 }
4115
4116 // address = address + 4;
4117 offset += addr_byte_size;
4118 }
4119 }
4120
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004121 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004122 // MemA[address,4] = PCStoreValue();
4123 if (BitIsSet (registers, 15))
4124 {
4125 Register pc_reg;
4126 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4127 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004128 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004129 if (!success)
4130 return false;
4131
Caroline Tice8d681f52011-03-17 23:50:16 +00004132 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004133 return false;
4134 }
4135
4136 // if wback then R[n] = R[n] - 4*BitCount(registers);
4137 if (wback)
4138 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004139 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004140 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4141 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004142 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4144 return false;
4145 }
4146 }
4147 return true;
4148}
4149
Caroline Ticeaf556562011-02-15 18:42:15 +00004150// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4151// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4152// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004153bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004154EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004155{
4156#if 0
4157 if ConditionPassed() then
4158 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4159 address = R[n] - 4*BitCount(registers);
4160
4161 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004162 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004163 if i == n && wback && i != LowestSetBit(registers) then
4164 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4165 else
4166 MemA[address,4] = R[i];
4167 address = address + 4;
4168
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004169 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004170 MemA[address,4] = PCStoreValue();
4171
4172 if wback then R[n] = R[n] - 4*BitCount(registers);
4173#endif
4174
4175
4176 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004177
Greg Clayton7bc39082011-03-24 23:53:38 +00004178 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004179 {
4180 uint32_t n;
4181 uint32_t registers = 0;
4182 bool wback;
4183 const uint32_t addr_byte_size = GetAddressByteSize();
4184
4185 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4186 switch (encoding)
4187 {
4188 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004189 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004190 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4191 {
4192 // See PUSH
4193 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004195 n = Bits32 (opcode, 19, 16);
4196 registers = Bits32 (opcode, 15, 0);
4197 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4198 wback = BitIsSet (opcode, 21);
4199 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4200 if ((n == 15) || BitCount (registers) < 2)
4201 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004202 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004203 if (wback && BitIsSet (registers, n))
4204 return false;
4205 break;
4206
4207 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004208 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004209 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4210 {
4211 // See Push
4212 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004213 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004214 n = Bits32 (opcode, 19, 16);
4215 registers = Bits32 (opcode, 15, 0);
4216 wback = BitIsSet (opcode, 21);
4217 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4218 if ((n == 15) || BitCount (registers) < 1)
4219 return false;
4220 break;
4221
4222 default:
4223 return false;
4224 }
4225
4226 // address = R[n] - 4*BitCount(registers);
4227
4228 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004229 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004230 if (!success)
4231 return false;
4232
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004233 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004234
4235 EmulateInstruction::Context context;
4236 context.type = EmulateInstruction::eContextRegisterStore;
4237 Register base_reg;
4238 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4239
4240 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004241 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004242 for (int i = 0; i < 14; ++i)
4243 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004244 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004245 if (BitIsSet (registers, i))
4246 {
4247 if (i < lowest_set_bit)
4248 lowest_set_bit = i;
4249 // if i == n && wback && i != LowestSetBit(registers) then
4250 if ((i == n) && wback && (i != lowest_set_bit))
4251 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4252 WriteBits32UnknownToMemory (address + offset);
4253 else
4254 {
4255 // MemA[address,4] = R[i];
4256 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4257 if (!success)
4258 return false;
4259
4260 Register data_reg;
4261 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004262 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004263 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004264 return false;
4265 }
4266
4267 // address = address + 4;
4268 offset += addr_byte_size;
4269 }
4270 }
4271
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004272 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004273 // MemA[address,4] = PCStoreValue();
4274 if (BitIsSet (registers, 15))
4275 {
4276 Register pc_reg;
4277 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4278 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004279 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004280 if (!success)
4281 return false;
4282
Caroline Tice8d681f52011-03-17 23:50:16 +00004283 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004284 return false;
4285 }
4286
4287 // if wback then R[n] = R[n] - 4*BitCount(registers);
4288 if (wback)
4289 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004290 offset = (addr_byte_size * BitCount (registers)) * -1;
4291 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4292 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004293 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004294 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4295 return false;
4296 }
4297 }
4298 return true;
4299}
4300
4301// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4302// from a base register. The consecutive memory locations start just above this address, and the address of the last
4303// of those locations can optionally be written back to the base register.
4304bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004305EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004306{
4307#if 0
4308 if ConditionPassed() then
4309 EncodingSpecificOperations();
4310 address = R[n] + 4;
4311
4312 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004313 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004314 if i == n && wback && i != LowestSetBit(registers) then
4315 MemA[address,4] = bits(32) UNKNOWN;
4316 else
4317 MemA[address,4] = R[i];
4318 address = address + 4;
4319
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004320 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004321 MemA[address,4] = PCStoreValue();
4322
4323 if wback then R[n] = R[n] + 4*BitCount(registers);
4324#endif
4325
4326 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004327
Greg Clayton7bc39082011-03-24 23:53:38 +00004328 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004329 {
4330 uint32_t n;
4331 uint32_t registers = 0;
4332 bool wback;
4333 const uint32_t addr_byte_size = GetAddressByteSize();
4334
4335 // EncodingSpecificOperations();
4336 switch (encoding)
4337 {
4338 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004339 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004340 n = Bits32 (opcode, 19, 16);
4341 registers = Bits32 (opcode, 15, 0);
4342 wback = BitIsSet (opcode, 21);
4343
4344 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4345 if ((n == 15) && (BitCount (registers) < 1))
4346 return false;
4347 break;
4348 default:
4349 return false;
4350 }
4351 // address = R[n] + 4;
4352
4353 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004354 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004355 if (!success)
4356 return false;
4357
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004358 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004359
4360 EmulateInstruction::Context context;
4361 context.type = EmulateInstruction::eContextRegisterStore;
4362 Register base_reg;
4363 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4364
4365 uint32_t lowest_set_bit = 14;
4366 // for i = 0 to 14
4367 for (int i = 0; i < 14; ++i)
4368 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004369 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004370 if (BitIsSet (registers, i))
4371 {
4372 if (i < lowest_set_bit)
4373 lowest_set_bit = i;
4374 // if i == n && wback && i != LowestSetBit(registers) then
4375 if ((i == n) && wback && (i != lowest_set_bit))
4376 // MemA[address,4] = bits(32) UNKNOWN;
4377 WriteBits32UnknownToMemory (address + offset);
4378 // else
4379 else
4380 {
4381 // MemA[address,4] = R[i];
4382 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4383 if (!success)
4384 return false;
4385
4386 Register data_reg;
4387 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004388 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004389 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004390 return false;
4391 }
4392
4393 // address = address + 4;
4394 offset += addr_byte_size;
4395 }
4396 }
4397
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004398 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004399 // MemA[address,4] = PCStoreValue();
4400 if (BitIsSet (registers, 15))
4401 {
4402 Register pc_reg;
4403 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4404 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004405 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004406 if (!success)
4407 return false;
4408
Caroline Tice8d681f52011-03-17 23:50:16 +00004409 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004410 return false;
4411 }
4412
4413 // if wback then R[n] = R[n] + 4*BitCount(registers);
4414 if (wback)
4415 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004416 offset = addr_byte_size * BitCount (registers);
4417 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4418 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004419 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004420 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4421 return false;
4422 }
4423 }
4424 return true;
4425}
Caroline Tice7fac8572011-02-15 22:53:54 +00004426
4427// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4428// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4429bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004430EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004431{
4432#if 0
4433 if ConditionPassed() then
4434 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4435 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4436 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004437 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004438 MemU[address,4] = R[t];
4439 else // Can only occur before ARMv7
4440 MemU[address,4] = bits(32) UNKNOWN;
4441 if wback then R[n] = offset_addr;
4442#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004443
Caroline Tice7fac8572011-02-15 22:53:54 +00004444 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004445
Greg Clayton7bc39082011-03-24 23:53:38 +00004446 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004447 {
4448 const uint32_t addr_byte_size = GetAddressByteSize();
4449
4450 uint32_t t;
4451 uint32_t n;
4452 uint32_t imm32;
4453 bool index;
4454 bool add;
4455 bool wback;
4456 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4457 switch (encoding)
4458 {
4459 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004460 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004461 t = Bits32 (opcode, 2, 0);
4462 n = Bits32 (opcode, 5, 3);
4463 imm32 = Bits32 (opcode, 10, 6) << 2;
4464
4465 // index = TRUE; add = TRUE; wback = FALSE;
4466 index = true;
4467 add = false;
4468 wback = false;
4469 break;
4470
4471 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004472 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004473 t = Bits32 (opcode, 10, 8);
4474 n = 13;
4475 imm32 = Bits32 (opcode, 7, 0) << 2;
4476
4477 // index = TRUE; add = TRUE; wback = FALSE;
4478 index = true;
4479 add = true;
4480 wback = false;
4481 break;
4482
4483 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004484 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004485 if (Bits32 (opcode, 19, 16) == 15)
4486 return false;
4487
4488 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4489 t = Bits32 (opcode, 15, 12);
4490 n = Bits32 (opcode, 19, 16);
4491 imm32 = Bits32 (opcode, 11, 0);
4492
4493 // index = TRUE; add = TRUE; wback = FALSE;
4494 index = true;
4495 add = true;
4496 wback = false;
4497
4498 // if t == 15 then UNPREDICTABLE;
4499 if (t == 15)
4500 return false;
4501 break;
4502
4503 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004504 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4505 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4506 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004507 if ((Bits32 (opcode, 19, 16) == 15)
4508 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4509 return false;
4510
4511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4512 t = Bits32 (opcode, 15, 12);
4513 n = Bits32 (opcode, 19, 16);
4514 imm32 = Bits32 (opcode, 7, 0);
4515
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004516 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004517 index = BitIsSet (opcode, 10);
4518 add = BitIsSet (opcode, 9);
4519 wback = BitIsSet (opcode, 8);
4520
4521 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4522 if ((t == 15) || (wback && (n == t)))
4523 return false;
4524 break;
4525
4526 default:
4527 return false;
4528 }
4529
4530 addr_t offset_addr;
4531 addr_t address;
4532
4533 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004534 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004535 if (!success)
4536 return false;
4537
4538 if (add)
4539 offset_addr = base_address + imm32;
4540 else
4541 offset_addr = base_address - imm32;
4542
4543 // address = if index then offset_addr else R[n];
4544 if (index)
4545 address = offset_addr;
4546 else
4547 address = base_address;
4548
4549 EmulateInstruction::Context context;
4550 context.type = eContextRegisterStore;
4551 Register base_reg;
4552 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4553
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004554 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004555 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4556 {
4557 // MemU[address,4] = R[t];
4558 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4559 if (!success)
4560 return false;
4561
4562 Register data_reg;
4563 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4564 int32_t offset = address - base_address;
4565 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004566 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004567 return false;
4568 }
4569 else
4570 {
4571 // MemU[address,4] = bits(32) UNKNOWN;
4572 WriteBits32UnknownToMemory (address);
4573 }
4574
4575 // if wback then R[n] = offset_addr;
4576 if (wback)
4577 {
4578 context.type = eContextRegisterLoad;
4579 context.SetAddress (offset_addr);
4580 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4581 return false;
4582 }
4583 }
4584 return true;
4585}
Caroline Ticeaf556562011-02-15 18:42:15 +00004586
Caroline Tice3fd63e92011-02-16 00:33:43 +00004587// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4588// word from a register to memory. The offset register value can optionally be shifted.
4589bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004590EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004591{
4592#if 0
4593 if ConditionPassed() then
4594 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4595 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4596 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4597 address = if index then offset_addr else R[n];
4598 if t == 15 then // Only possible for encoding A1
4599 data = PCStoreValue();
4600 else
4601 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004602 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004603 MemU[address,4] = data;
4604 else // Can only occur before ARMv7
4605 MemU[address,4] = bits(32) UNKNOWN;
4606 if wback then R[n] = offset_addr;
4607#endif
4608
4609 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004610
Greg Clayton7bc39082011-03-24 23:53:38 +00004611 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004612 {
4613 const uint32_t addr_byte_size = GetAddressByteSize();
4614
4615 uint32_t t;
4616 uint32_t n;
4617 uint32_t m;
4618 ARM_ShifterType shift_t;
4619 uint32_t shift_n;
4620 bool index;
4621 bool add;
4622 bool wback;
4623
4624 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4625 switch (encoding)
4626 {
4627 case eEncodingT1:
4628 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4629 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4630 t = Bits32 (opcode, 2, 0);
4631 n = Bits32 (opcode, 5, 3);
4632 m = Bits32 (opcode, 8, 6);
4633
4634 // index = TRUE; add = TRUE; wback = FALSE;
4635 index = true;
4636 add = true;
4637 wback = false;
4638
4639 // (shift_t, shift_n) = (SRType_LSL, 0);
4640 shift_t = SRType_LSL;
4641 shift_n = 0;
4642 break;
4643
4644 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004645 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004646 if (Bits32 (opcode, 19, 16) == 15)
4647 return false;
4648
4649 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4650 t = Bits32 (opcode, 15, 12);
4651 n = Bits32 (opcode, 19, 16);
4652 m = Bits32 (opcode, 3, 0);
4653
4654 // index = TRUE; add = TRUE; wback = FALSE;
4655 index = true;
4656 add = true;
4657 wback = false;
4658
4659 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4660 shift_t = SRType_LSL;
4661 shift_n = Bits32 (opcode, 5, 4);
4662
4663 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4664 if ((t == 15) || (BadReg (m)))
4665 return false;
4666 break;
4667
4668 case eEncodingA1:
4669 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004670 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004671 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4672 t = Bits32 (opcode, 15, 12);
4673 n = Bits32 (opcode, 19, 16);
4674 m = Bits32 (opcode, 3, 0);
4675
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004676 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004677 index = BitIsSet (opcode, 24);
4678 add = BitIsSet (opcode, 23);
4679 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4680
4681 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4682 uint32_t typ = Bits32 (opcode, 6, 5);
4683 uint32_t imm5 = Bits32 (opcode, 11, 7);
4684 shift_n = DecodeImmShift(typ, imm5, shift_t);
4685
4686 // if m == 15 then UNPREDICTABLE;
4687 if (m == 15)
4688 return false;
4689
4690 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4691 if (wback && ((n == 15) || (n == t)))
4692 return false;
4693
4694 break;
4695 }
4696 default:
4697 return false;
4698 }
4699
4700 addr_t offset_addr;
4701 addr_t address;
4702 int32_t offset = 0;
4703
4704 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4705 if (!success)
4706 return false;
4707
4708 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4709 if (!success)
4710 return false;
4711
4712 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004713 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004714
4715 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4716 if (add)
4717 offset_addr = base_address + offset;
4718 else
4719 offset_addr = base_address - offset;
4720
4721 // address = if index then offset_addr else R[n];
4722 if (index)
4723 address = offset_addr;
4724 else
4725 address = base_address;
4726
4727 uint32_t data;
4728 // if t == 15 then // Only possible for encoding A1
4729 if (t == 15)
4730 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004731 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004732 else
4733 // data = R[t];
4734 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4735
4736 if (!success)
4737 return false;
4738
4739 EmulateInstruction::Context context;
4740 context.type = eContextRegisterStore;
4741
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004742 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004743 if (UnalignedSupport ()
4744 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4745 || CurrentInstrSet() == eModeARM)
4746 {
4747 // MemU[address,4] = data;
4748
4749 Register base_reg;
4750 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4751
4752 Register data_reg;
4753 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4754
4755 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004756 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004757 return false;
4758
4759 }
4760 else
4761 // MemU[address,4] = bits(32) UNKNOWN;
4762 WriteBits32UnknownToMemory (address);
4763
4764 // if wback then R[n] = offset_addr;
4765 if (wback)
4766 {
4767 context.type = eContextRegisterLoad;
4768 context.SetAddress (offset_addr);
4769 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4770 return false;
4771 }
4772
4773 }
4774 return true;
4775}
Caroline Tice73a29de2011-02-16 20:22:22 +00004776
4777bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004778EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004779{
4780#if 0
4781 if ConditionPassed() then
4782 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4783 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4784 address = if index then offset_addr else R[n];
4785 MemU[address,1] = R[t]<7:0>;
4786 if wback then R[n] = offset_addr;
4787#endif
4788
4789
4790 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004791
Greg Clayton7bc39082011-03-24 23:53:38 +00004792 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004793 {
4794 uint32_t t;
4795 uint32_t n;
4796 uint32_t imm32;
4797 bool index;
4798 bool add;
4799 bool wback;
4800 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4801 switch (encoding)
4802 {
4803 case eEncodingT1:
4804 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4805 t = Bits32 (opcode, 2, 0);
4806 n = Bits32 (opcode, 5, 3);
4807 imm32 = Bits32 (opcode, 10, 6);
4808
4809 // index = TRUE; add = TRUE; wback = FALSE;
4810 index = true;
4811 add = true;
4812 wback = false;
4813 break;
4814
4815 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004816 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004817 if (Bits32 (opcode, 19, 16) == 15)
4818 return false;
4819
4820 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4821 t = Bits32 (opcode, 15, 12);
4822 n = Bits32 (opcode, 19, 16);
4823 imm32 = Bits32 (opcode, 11, 0);
4824
4825 // index = TRUE; add = TRUE; wback = FALSE;
4826 index = true;
4827 add = true;
4828 wback = false;
4829
4830 // if BadReg(t) then UNPREDICTABLE;
4831 if (BadReg (t))
4832 return false;
4833 break;
4834
4835 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004836 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4837 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004838 if (Bits32 (opcode, 19, 16) == 15)
4839 return false;
4840
4841 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4842 t = Bits32 (opcode, 15, 12);
4843 n = Bits32 (opcode, 19, 16);
4844 imm32 = Bits32 (opcode, 7, 0);
4845
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004846 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004847 index = BitIsSet (opcode, 10);
4848 add = BitIsSet (opcode, 9);
4849 wback = BitIsSet (opcode, 8);
4850
4851 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4852 if ((BadReg (t)) || (wback && (n == t)))
4853 return false;
4854 break;
4855
4856 default:
4857 return false;
4858 }
4859
4860 addr_t offset_addr;
4861 addr_t address;
4862 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4863 if (!success)
4864 return false;
4865
4866 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4867 if (add)
4868 offset_addr = base_address + imm32;
4869 else
4870 offset_addr = base_address - imm32;
4871
4872 // address = if index then offset_addr else R[n];
4873 if (index)
4874 address = offset_addr;
4875 else
4876 address = base_address;
4877
Caroline Ticecc96eb52011-02-17 19:20:40 +00004878 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004879 Register base_reg;
4880 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4881
4882 Register data_reg;
4883 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4884
4885 EmulateInstruction::Context context;
4886 context.type = eContextRegisterStore;
4887 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4888
4889 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4890 if (!success)
4891 return false;
4892
4893 data = Bits32 (data, 7, 0);
4894
Caroline Ticecc96eb52011-02-17 19:20:40 +00004895 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004896 return false;
4897
4898 // if wback then R[n] = offset_addr;
4899 if (wback)
4900 {
4901 context.type = eContextRegisterLoad;
4902 context.SetAddress (offset_addr);
4903 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4904 return false;
4905 }
4906
4907 }
4908
4909 return true;
4910}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004911
4912// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4913// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4914bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004915EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004916{
4917#if 0
4918 if ConditionPassed() then
4919 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4920 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4921 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4922 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004923 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004924 MemU[address,2] = R[t]<15:0>;
4925 else // Can only occur before ARMv7
4926 MemU[address,2] = bits(16) UNKNOWN;
4927 if wback then R[n] = offset_addr;
4928#endif
4929
4930 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004931
Greg Clayton7bc39082011-03-24 23:53:38 +00004932 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004933 {
4934 uint32_t t;
4935 uint32_t n;
4936 uint32_t m;
4937 bool index;
4938 bool add;
4939 bool wback;
4940 ARM_ShifterType shift_t;
4941 uint32_t shift_n;
4942
4943 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4944 switch (encoding)
4945 {
4946 case eEncodingT1:
4947 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4948 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4949 t = Bits32 (opcode, 2, 0);
4950 n = Bits32 (opcode, 5, 3);
4951 m = Bits32 (opcode, 8, 6);
4952
4953 // index = TRUE; add = TRUE; wback = FALSE;
4954 index = true;
4955 add = true;
4956 wback = false;
4957
4958 // (shift_t, shift_n) = (SRType_LSL, 0);
4959 shift_t = SRType_LSL;
4960 shift_n = 0;
4961
4962 break;
4963
4964 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004965 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004966 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4967 t = Bits32 (opcode, 15, 12);
4968 n = Bits32 (opcode, 19, 16);
4969 m = Bits32 (opcode, 3, 0);
4970 if (n == 15)
4971 return false;
4972
4973 // index = TRUE; add = TRUE; wback = FALSE;
4974 index = true;
4975 add = true;
4976 wback = false;
4977
4978 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4979 shift_t = SRType_LSL;
4980 shift_n = Bits32 (opcode, 5, 4);
4981
4982 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4983 if (BadReg (t) || BadReg (m))
4984 return false;
4985
4986 break;
4987
4988 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004989 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004990 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4991 t = Bits32 (opcode, 15, 12);
4992 n = Bits32 (opcode, 19, 16);
4993 m = Bits32 (opcode, 3, 0);
4994
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004995 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004996 index = BitIsSet (opcode, 24);
4997 add = BitIsSet (opcode, 23);
4998 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4999
5000 // (shift_t, shift_n) = (SRType_LSL, 0);
5001 shift_t = SRType_LSL;
5002 shift_n = 0;
5003
5004 // if t == 15 || m == 15 then UNPREDICTABLE;
5005 if ((t == 15) || (m == 15))
5006 return false;
5007
5008 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5009 if (wback && ((n == 15) || (n == t)))
5010 return false;
5011
5012 break;
5013
5014 default:
5015 return false;
5016 }
5017
5018 uint32_t Rm = ReadCoreReg (m, &success);
5019 if (!success)
5020 return false;
5021
5022 uint32_t Rn = ReadCoreReg (n, &success);
5023 if (!success)
5024 return false;
5025
5026 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5027 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5028
5029 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5030 addr_t offset_addr;
5031 if (add)
5032 offset_addr = Rn + offset;
5033 else
5034 offset_addr = Rn - offset;
5035
5036 // address = if index then offset_addr else R[n];
5037 addr_t address;
5038 if (index)
5039 address = offset_addr;
5040 else
5041 address = Rn;
5042
5043 EmulateInstruction::Context context;
5044 context.type = eContextRegisterStore;
5045 Register base_reg;
5046 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5047 Register offset_reg;
5048 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5049
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005050 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005051 if (UnalignedSupport() || BitIsClear (address, 0))
5052 {
5053 // MemU[address,2] = R[t]<15:0>;
5054 uint32_t Rt = ReadCoreReg (t, &success);
5055 if (!success)
5056 return false;
5057
5058 EmulateInstruction::Context context;
5059 context.type = eContextRegisterStore;
5060 Register base_reg;
5061 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5062 Register offset_reg;
5063 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5064 Register data_reg;
5065 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5066 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5067
5068 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5069 return false;
5070 }
5071 else // Can only occur before ARMv7
5072 {
5073 // MemU[address,2] = bits(16) UNKNOWN;
5074 }
5075
5076 // if wback then R[n] = offset_addr;
5077 if (wback)
5078 {
5079 context.type = eContextAdjustBaseRegister;
5080 context.SetAddress (offset_addr);
5081 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5082 return false;
5083 }
5084 }
5085
5086 return true;
5087}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005088
Johnny Chen157b9592011-02-18 21:13:05 +00005089// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5090// and writes the result to the destination register. It can optionally update the condition flags
5091// based on the result.
5092bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005093EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005094{
5095#if 0
5096 // ARM pseudo code...
5097 if ConditionPassed() then
5098 EncodingSpecificOperations();
5099 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5100 if d == 15 then // Can only occur for ARM encoding
5101 ALUWritePC(result); // setflags is always FALSE here
5102 else
5103 R[d] = result;
5104 if setflags then
5105 APSR.N = result<31>;
5106 APSR.Z = IsZeroBit(result);
5107 APSR.C = carry;
5108 APSR.V = overflow;
5109#endif
5110
5111 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005112
Greg Clayton7bc39082011-03-24 23:53:38 +00005113 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005114 {
5115 uint32_t Rd, Rn;
5116 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5117 bool setflags;
5118 switch (encoding)
5119 {
5120 case eEncodingT1:
5121 Rd = Bits32(opcode, 11, 8);
5122 Rn = Bits32(opcode, 19, 16);
5123 setflags = BitIsSet(opcode, 20);
5124 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5125 if (BadReg(Rd) || BadReg(Rn))
5126 return false;
5127 break;
5128 case eEncodingA1:
5129 Rd = Bits32(opcode, 15, 12);
5130 Rn = Bits32(opcode, 19, 16);
5131 setflags = BitIsSet(opcode, 20);
5132 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5133 // TODO: Emulate SUBS PC, LR and related instructions.
5134 if (Rd == 15 && setflags)
5135 return false;
5136 break;
5137 default:
5138 return false;
5139 }
5140
5141 // Read the first operand.
5142 int32_t val1 = ReadCoreReg(Rn, &success);
5143 if (!success)
5144 return false;
5145
5146 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5147
5148 EmulateInstruction::Context context;
5149 context.type = EmulateInstruction::eContextImmediate;
5150 context.SetNoArgs ();
5151
5152 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5153 return false;
5154 }
5155 return true;
5156}
5157
5158// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5159// register value, and writes the result to the destination register. It can optionally update the
5160// condition flags based on the result.
5161bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005162EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005163{
5164#if 0
5165 // ARM pseudo code...
5166 if ConditionPassed() then
5167 EncodingSpecificOperations();
5168 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5169 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5170 if d == 15 then // Can only occur for ARM encoding
5171 ALUWritePC(result); // setflags is always FALSE here
5172 else
5173 R[d] = result;
5174 if setflags then
5175 APSR.N = result<31>;
5176 APSR.Z = IsZeroBit(result);
5177 APSR.C = carry;
5178 APSR.V = overflow;
5179#endif
5180
5181 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005182
Greg Clayton7bc39082011-03-24 23:53:38 +00005183 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005184 {
5185 uint32_t Rd, Rn, Rm;
5186 ARM_ShifterType shift_t;
5187 uint32_t shift_n; // the shift applied to the value read from Rm
5188 bool setflags;
5189 switch (encoding)
5190 {
5191 case eEncodingT1:
5192 Rd = Rn = Bits32(opcode, 2, 0);
5193 Rm = Bits32(opcode, 5, 3);
5194 setflags = !InITBlock();
5195 shift_t = SRType_LSL;
5196 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005197 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005198 case eEncodingT2:
5199 Rd = Bits32(opcode, 11, 8);
5200 Rn = Bits32(opcode, 19, 16);
5201 Rm = Bits32(opcode, 3, 0);
5202 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005203 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005204 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5205 return false;
5206 break;
5207 case eEncodingA1:
5208 Rd = Bits32(opcode, 15, 12);
5209 Rn = Bits32(opcode, 19, 16);
5210 Rm = Bits32(opcode, 3, 0);
5211 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005212 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005213 // TODO: Emulate SUBS PC, LR and related instructions.
5214 if (Rd == 15 && setflags)
5215 return false;
5216 break;
5217 default:
5218 return false;
5219 }
5220
5221 // Read the first operand.
5222 int32_t val1 = ReadCoreReg(Rn, &success);
5223 if (!success)
5224 return false;
5225
5226 // Read the second operand.
5227 int32_t val2 = ReadCoreReg(Rm, &success);
5228 if (!success)
5229 return false;
5230
5231 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5232 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5233
5234 EmulateInstruction::Context context;
5235 context.type = EmulateInstruction::eContextImmediate;
5236 context.SetNoArgs ();
5237
5238 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5239 return false;
5240 }
5241 return true;
5242}
5243
Johnny Chena695f952011-02-23 21:24:25 +00005244// This instruction adds an immediate value to the PC value to form a PC-relative address,
5245// and writes the result to the destination register.
5246bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005247EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005248{
5249#if 0
5250 // ARM pseudo code...
5251 if ConditionPassed() then
5252 EncodingSpecificOperations();
5253 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5254 if d == 15 then // Can only occur for ARM encodings
5255 ALUWritePC(result);
5256 else
5257 R[d] = result;
5258#endif
5259
5260 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005261
Greg Clayton7bc39082011-03-24 23:53:38 +00005262 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005263 {
5264 uint32_t Rd;
5265 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5266 bool add;
5267 switch (encoding)
5268 {
5269 case eEncodingT1:
5270 Rd = Bits32(opcode, 10, 8);
5271 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5272 break;
5273 case eEncodingT2:
5274 case eEncodingT3:
5275 Rd = Bits32(opcode, 11, 8);
5276 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5277 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5278 if (BadReg(Rd))
5279 return false;
5280 break;
5281 case eEncodingA1:
5282 case eEncodingA2:
5283 Rd = Bits32(opcode, 15, 12);
5284 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5285 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5286 break;
5287 default:
5288 return false;
5289 }
5290
5291 // Read the PC value.
5292 uint32_t pc = ReadCoreReg(PC_REG, &success);
5293 if (!success)
5294 return false;
5295
5296 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5297
5298 EmulateInstruction::Context context;
5299 context.type = EmulateInstruction::eContextImmediate;
5300 context.SetNoArgs ();
5301
5302 if (!WriteCoreReg(context, result, Rd))
5303 return false;
5304 }
5305 return true;
5306}
5307
Johnny Chene97c0d52011-02-18 19:32:20 +00005308// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5309// to the destination register. It can optionally update the condition flags based on the result.
5310bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005311EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005312{
5313#if 0
5314 // ARM pseudo code...
5315 if ConditionPassed() then
5316 EncodingSpecificOperations();
5317 result = R[n] AND imm32;
5318 if d == 15 then // Can only occur for ARM encoding
5319 ALUWritePC(result); // setflags is always FALSE here
5320 else
5321 R[d] = result;
5322 if setflags then
5323 APSR.N = result<31>;
5324 APSR.Z = IsZeroBit(result);
5325 APSR.C = carry;
5326 // APSR.V unchanged
5327#endif
5328
5329 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005330
Greg Clayton7bc39082011-03-24 23:53:38 +00005331 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005332 {
5333 uint32_t Rd, Rn;
5334 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5335 bool setflags;
5336 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5337 switch (encoding)
5338 {
5339 case eEncodingT1:
5340 Rd = Bits32(opcode, 11, 8);
5341 Rn = Bits32(opcode, 19, 16);
5342 setflags = BitIsSet(opcode, 20);
5343 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005344 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005345 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005346 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005347 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5348 return false;
5349 break;
5350 case eEncodingA1:
5351 Rd = Bits32(opcode, 15, 12);
5352 Rn = Bits32(opcode, 19, 16);
5353 setflags = BitIsSet(opcode, 20);
5354 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5355 // TODO: Emulate SUBS PC, LR and related instructions.
5356 if (Rd == 15 && setflags)
5357 return false;
5358 break;
5359 default:
5360 return false;
5361 }
5362
Johnny Chene97c0d52011-02-18 19:32:20 +00005363 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005364 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005365 if (!success)
5366 return false;
5367
5368 uint32_t result = val1 & imm32;
5369
5370 EmulateInstruction::Context context;
5371 context.type = EmulateInstruction::eContextImmediate;
5372 context.SetNoArgs ();
5373
5374 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5375 return false;
5376 }
5377 return true;
5378}
5379
5380// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5381// and writes the result to the destination register. It can optionally update the condition flags
5382// based on the result.
5383bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005384EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005385{
5386#if 0
5387 // ARM pseudo code...
5388 if ConditionPassed() then
5389 EncodingSpecificOperations();
5390 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5391 result = R[n] AND shifted;
5392 if d == 15 then // Can only occur for ARM encoding
5393 ALUWritePC(result); // setflags is always FALSE here
5394 else
5395 R[d] = result;
5396 if setflags then
5397 APSR.N = result<31>;
5398 APSR.Z = IsZeroBit(result);
5399 APSR.C = carry;
5400 // APSR.V unchanged
5401#endif
5402
5403 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005404
Greg Clayton7bc39082011-03-24 23:53:38 +00005405 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005406 {
5407 uint32_t Rd, Rn, Rm;
5408 ARM_ShifterType shift_t;
5409 uint32_t shift_n; // the shift applied to the value read from Rm
5410 bool setflags;
5411 uint32_t carry;
5412 switch (encoding)
5413 {
5414 case eEncodingT1:
5415 Rd = Rn = Bits32(opcode, 2, 0);
5416 Rm = Bits32(opcode, 5, 3);
5417 setflags = !InITBlock();
5418 shift_t = SRType_LSL;
5419 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005420 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005421 case eEncodingT2:
5422 Rd = Bits32(opcode, 11, 8);
5423 Rn = Bits32(opcode, 19, 16);
5424 Rm = Bits32(opcode, 3, 0);
5425 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005426 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005427 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005428 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005429 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005430 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5431 return false;
5432 break;
5433 case eEncodingA1:
5434 Rd = Bits32(opcode, 15, 12);
5435 Rn = Bits32(opcode, 19, 16);
5436 Rm = Bits32(opcode, 3, 0);
5437 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005438 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005439 // TODO: Emulate SUBS PC, LR and related instructions.
5440 if (Rd == 15 && setflags)
5441 return false;
5442 break;
5443 default:
5444 return false;
5445 }
5446
Johnny Chene97c0d52011-02-18 19:32:20 +00005447 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005448 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005449 if (!success)
5450 return false;
5451
5452 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005453 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005454 if (!success)
5455 return false;
5456
5457 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5458 uint32_t result = val1 & shifted;
5459
5460 EmulateInstruction::Context context;
5461 context.type = EmulateInstruction::eContextImmediate;
5462 context.SetNoArgs ();
5463
5464 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5465 return false;
5466 }
5467 return true;
5468}
5469
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005470// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5471// immediate value, and writes the result to the destination register. It can optionally update the
5472// condition flags based on the result.
5473bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005474EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005475{
5476#if 0
5477 // ARM pseudo code...
5478 if ConditionPassed() then
5479 EncodingSpecificOperations();
5480 result = R[n] AND NOT(imm32);
5481 if d == 15 then // Can only occur for ARM encoding
5482 ALUWritePC(result); // setflags is always FALSE here
5483 else
5484 R[d] = result;
5485 if setflags then
5486 APSR.N = result<31>;
5487 APSR.Z = IsZeroBit(result);
5488 APSR.C = carry;
5489 // APSR.V unchanged
5490#endif
5491
5492 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005493
Greg Clayton7bc39082011-03-24 23:53:38 +00005494 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005495 {
5496 uint32_t Rd, Rn;
5497 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5498 bool setflags;
5499 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5500 switch (encoding)
5501 {
5502 case eEncodingT1:
5503 Rd = Bits32(opcode, 11, 8);
5504 Rn = Bits32(opcode, 19, 16);
5505 setflags = BitIsSet(opcode, 20);
5506 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5507 if (BadReg(Rd) || BadReg(Rn))
5508 return false;
5509 break;
5510 case eEncodingA1:
5511 Rd = Bits32(opcode, 15, 12);
5512 Rn = Bits32(opcode, 19, 16);
5513 setflags = BitIsSet(opcode, 20);
5514 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005515 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005516 // TODO: Emulate SUBS PC, LR and related instructions.
5517 if (Rd == 15 && setflags)
5518 return false;
5519 break;
5520 default:
5521 return false;
5522 }
5523
5524 // Read the first operand.
5525 uint32_t val1 = ReadCoreReg(Rn, &success);
5526 if (!success)
5527 return false;
5528
5529 uint32_t result = val1 & ~imm32;
5530
5531 EmulateInstruction::Context context;
5532 context.type = EmulateInstruction::eContextImmediate;
5533 context.SetNoArgs ();
5534
5535 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5536 return false;
5537 }
5538 return true;
5539}
5540
5541// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5542// optionally-shifted register value, and writes the result to the destination register.
5543// It can optionally update the condition flags based on the result.
5544bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005545EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005546{
5547#if 0
5548 // ARM pseudo code...
5549 if ConditionPassed() then
5550 EncodingSpecificOperations();
5551 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5552 result = R[n] AND NOT(shifted);
5553 if d == 15 then // Can only occur for ARM encoding
5554 ALUWritePC(result); // setflags is always FALSE here
5555 else
5556 R[d] = result;
5557 if setflags then
5558 APSR.N = result<31>;
5559 APSR.Z = IsZeroBit(result);
5560 APSR.C = carry;
5561 // APSR.V unchanged
5562#endif
5563
5564 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005565
Greg Clayton7bc39082011-03-24 23:53:38 +00005566 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005567 {
5568 uint32_t Rd, Rn, Rm;
5569 ARM_ShifterType shift_t;
5570 uint32_t shift_n; // the shift applied to the value read from Rm
5571 bool setflags;
5572 uint32_t carry;
5573 switch (encoding)
5574 {
5575 case eEncodingT1:
5576 Rd = Rn = Bits32(opcode, 2, 0);
5577 Rm = Bits32(opcode, 5, 3);
5578 setflags = !InITBlock();
5579 shift_t = SRType_LSL;
5580 shift_n = 0;
5581 break;
5582 case eEncodingT2:
5583 Rd = Bits32(opcode, 11, 8);
5584 Rn = Bits32(opcode, 19, 16);
5585 Rm = Bits32(opcode, 3, 0);
5586 setflags = BitIsSet(opcode, 20);
5587 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5588 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5589 return false;
5590 break;
5591 case eEncodingA1:
5592 Rd = Bits32(opcode, 15, 12);
5593 Rn = Bits32(opcode, 19, 16);
5594 Rm = Bits32(opcode, 3, 0);
5595 setflags = BitIsSet(opcode, 20);
5596 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005597 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005598 // TODO: Emulate SUBS PC, LR and related instructions.
5599 if (Rd == 15 && setflags)
5600 return false;
5601 break;
5602 default:
5603 return false;
5604 }
5605
5606 // Read the first operand.
5607 uint32_t val1 = ReadCoreReg(Rn, &success);
5608 if (!success)
5609 return false;
5610
5611 // Read the second operand.
5612 uint32_t val2 = ReadCoreReg(Rm, &success);
5613 if (!success)
5614 return false;
5615
5616 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5617 uint32_t result = val1 & ~shifted;
5618
5619 EmulateInstruction::Context context;
5620 context.type = EmulateInstruction::eContextImmediate;
5621 context.SetNoArgs ();
5622
5623 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5624 return false;
5625 }
5626 return true;
5627}
5628
Caroline Tice4d729c52011-02-18 00:55:53 +00005629// 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 +00005630// 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 +00005631bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005632EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005633{
5634#if 0
5635 if ConditionPassed() then
5636 EncodingSpecificOperations();
5637 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5638 address = if index then offset_addr else R[n];
5639 data = MemU[address,4];
5640 if wback then R[n] = offset_addr;
5641 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005642 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5643 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005644 R[t] = data;
5645 else // Can only apply before ARMv7
5646 R[t] = ROR(data, 8*UInt(address<1:0>));
5647#endif
5648
5649 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005650
Greg Clayton7bc39082011-03-24 23:53:38 +00005651 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005652 {
5653 const uint32_t addr_byte_size = GetAddressByteSize();
5654
5655 uint32_t t;
5656 uint32_t n;
5657 uint32_t imm32;
5658 bool index;
5659 bool add;
5660 bool wback;
5661
5662 switch (encoding)
5663 {
5664 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005665 // if Rn == '1111' then SEE LDR (literal);
5666 // if P == '0' && W == '1' then SEE LDRT;
5667 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005668 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5669 t = Bits32 (opcode, 15, 12);
5670 n = Bits32 (opcode, 19, 16);
5671 imm32 = Bits32 (opcode, 11, 0);
5672
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005673 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5674 index = BitIsSet (opcode, 24);
5675 add = BitIsSet (opcode, 23);
5676 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005677
5678 // if wback && n == t then UNPREDICTABLE;
5679 if (wback && (n == t))
5680 return false;
5681
5682 break;
5683
5684 default:
5685 return false;
5686 }
5687
5688 addr_t address;
5689 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005690 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005691 if (!success)
5692 return false;
5693
5694 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5695 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005696 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005697 else
5698 offset_addr = base_address - imm32;
5699
5700 // address = if index then offset_addr else R[n];
5701 if (index)
5702 address = offset_addr;
5703 else
5704 address = base_address;
5705
5706 // data = MemU[address,4];
5707
5708 Register base_reg;
5709 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5710
5711 EmulateInstruction::Context context;
5712 context.type = eContextRegisterLoad;
5713 context.SetRegisterPlusOffset (base_reg, address - base_address);
5714
5715 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5716 if (!success)
5717 return false;
5718
5719 // if wback then R[n] = offset_addr;
5720 if (wback)
5721 {
5722 context.type = eContextAdjustBaseRegister;
5723 context.SetAddress (offset_addr);
5724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5725 return false;
5726 }
5727
5728 // if t == 15 then
5729 if (t == 15)
5730 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005731 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005732 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5733 {
5734 // LoadWritePC (data);
5735 context.type = eContextRegisterLoad;
5736 context.SetRegisterPlusOffset (base_reg, address - base_address);
5737 LoadWritePC (context, data);
5738 }
5739 else
5740 return false;
5741 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005742 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005743 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5744 {
5745 // R[t] = data;
5746 context.type = eContextRegisterLoad;
5747 context.SetRegisterPlusOffset (base_reg, address - base_address);
5748 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5749 return false;
5750 }
5751 // else // Can only apply before ARMv7
5752 else
5753 {
5754 // R[t] = ROR(data, 8*UInt(address<1:0>));
5755 data = ROR (data, Bits32 (address, 1, 0));
5756 context.type = eContextRegisterLoad;
5757 context.SetImmediate (data);
5758 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5759 return false;
5760 }
5761
5762 }
5763 return true;
5764}
5765
Caroline Ticefe479112011-02-18 18:52:37 +00005766// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5767// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005769EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005770{
5771#if 0
5772 if ConditionPassed() then
5773 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5774 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5775 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5776 address = if index then offset_addr else R[n];
5777 data = MemU[address,4];
5778 if wback then R[n] = offset_addr;
5779 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005780 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5781 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005782 R[t] = data;
5783 else // Can only apply before ARMv7
5784 if CurrentInstrSet() == InstrSet_ARM then
5785 R[t] = ROR(data, 8*UInt(address<1:0>));
5786 else
5787 R[t] = bits(32) UNKNOWN;
5788#endif
5789
5790 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005791
Greg Clayton7bc39082011-03-24 23:53:38 +00005792 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005793 {
5794 const uint32_t addr_byte_size = GetAddressByteSize();
5795
5796 uint32_t t;
5797 uint32_t n;
5798 uint32_t m;
5799 bool index;
5800 bool add;
5801 bool wback;
5802 ARM_ShifterType shift_t;
5803 uint32_t shift_n;
5804
5805 switch (encoding)
5806 {
5807 case eEncodingT1:
5808 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5809 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5810 t = Bits32 (opcode, 2, 0);
5811 n = Bits32 (opcode, 5, 3);
5812 m = Bits32 (opcode, 8, 6);
5813
5814 // index = TRUE; add = TRUE; wback = FALSE;
5815 index = true;
5816 add = true;
5817 wback = false;
5818
5819 // (shift_t, shift_n) = (SRType_LSL, 0);
5820 shift_t = SRType_LSL;
5821 shift_n = 0;
5822
5823 break;
5824
5825 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005826 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005827 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5828 t = Bits32 (opcode, 15, 12);
5829 n = Bits32 (opcode, 19, 16);
5830 m = Bits32 (opcode, 3, 0);
5831
5832 // index = TRUE; add = TRUE; wback = FALSE;
5833 index = true;
5834 add = true;
5835 wback = false;
5836
5837 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5838 shift_t = SRType_LSL;
5839 shift_n = Bits32 (opcode, 5, 4);
5840
5841 // if BadReg(m) then UNPREDICTABLE;
5842 if (BadReg (m))
5843 return false;
5844
5845 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5846 if ((t == 15) && InITBlock() && !LastInITBlock())
5847 return false;
5848
5849 break;
5850
5851 case eEncodingA1:
5852 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005853 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005854 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5855 t = Bits32 (opcode, 15, 12);
5856 n = Bits32 (opcode, 19, 16);
5857 m = Bits32 (opcode, 3, 0);
5858
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005859 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005860 index = BitIsSet (opcode, 24);
5861 add = BitIsSet (opcode, 23);
5862 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5863
5864 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5865 uint32_t type = Bits32 (opcode, 6, 5);
5866 uint32_t imm5 = Bits32 (opcode, 11, 7);
5867 shift_n = DecodeImmShift (type, imm5, shift_t);
5868
5869 // if m == 15 then UNPREDICTABLE;
5870 if (m == 15)
5871 return false;
5872
5873 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5874 if (wback && ((n == 15) || (n == t)))
5875 return false;
5876 }
5877 break;
5878
5879
5880 default:
5881 return false;
5882 }
5883
5884 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5885 if (!success)
5886 return false;
5887
5888 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5889 if (!success)
5890 return false;
5891
5892 addr_t offset_addr;
5893 addr_t address;
5894
5895 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Greg Claytonb3448432011-03-24 21:19:54 +00005896 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005897
5898 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5899 if (add)
5900 offset_addr = Rn + offset;
5901 else
5902 offset_addr = Rn - offset;
5903
5904 // address = if index then offset_addr else R[n];
5905 if (index)
5906 address = offset_addr;
5907 else
5908 address = Rn;
5909
5910 // data = MemU[address,4];
5911 Register base_reg;
5912 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5913
5914 EmulateInstruction::Context context;
5915 context.type = eContextRegisterLoad;
5916 context.SetRegisterPlusOffset (base_reg, address - Rn);
5917
5918 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5919 if (!success)
5920 return false;
5921
5922 // if wback then R[n] = offset_addr;
5923 if (wback)
5924 {
5925 context.type = eContextAdjustBaseRegister;
5926 context.SetAddress (offset_addr);
5927 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5928 return false;
5929 }
5930
5931 // if t == 15 then
5932 if (t == 15)
5933 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005934 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005935 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5936 {
5937 context.type = eContextRegisterLoad;
5938 context.SetRegisterPlusOffset (base_reg, address - Rn);
5939 LoadWritePC (context, data);
5940 }
5941 else
5942 return false;
5943 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005944 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005945 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5946 {
5947 // R[t] = data;
5948 context.type = eContextRegisterLoad;
5949 context.SetRegisterPlusOffset (base_reg, address - Rn);
5950 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5951 return false;
5952 }
5953 else // Can only apply before ARMv7
5954 {
5955 // if CurrentInstrSet() == InstrSet_ARM then
5956 if (CurrentInstrSet () == eModeARM)
5957 {
5958 // R[t] = ROR(data, 8*UInt(address<1:0>));
5959 data = ROR (data, Bits32 (address, 1, 0));
5960 context.type = eContextRegisterLoad;
5961 context.SetImmediate (data);
5962 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5963 return false;
5964 }
5965 else
5966 {
5967 // R[t] = bits(32) UNKNOWN;
5968 WriteBits32Unknown (t);
5969 }
5970 }
5971 }
5972 return true;
5973}
Caroline Tice21b604b2011-02-18 21:06:04 +00005974
5975// LDRB (immediate, Thumb)
5976bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005977EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005978{
5979#if 0
5980 if ConditionPassed() then
5981 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5982 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5983 address = if index then offset_addr else R[n];
5984 R[t] = ZeroExtend(MemU[address,1], 32);
5985 if wback then R[n] = offset_addr;
5986#endif
5987
5988 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005989
Greg Clayton7bc39082011-03-24 23:53:38 +00005990 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005991 {
5992 uint32_t t;
5993 uint32_t n;
5994 uint32_t imm32;
5995 bool index;
5996 bool add;
5997 bool wback;
5998
5999 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6000 switch (encoding)
6001 {
6002 case eEncodingT1:
6003 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6004 t = Bits32 (opcode, 2, 0);
6005 n = Bits32 (opcode, 5, 3);
6006 imm32 = Bits32 (opcode, 10, 6);
6007
6008 // index = TRUE; add = TRUE; wback = FALSE;
6009 index = true;
6010 add = true;
6011 wback= false;
6012
6013 break;
6014
6015 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006016 // if Rt == '1111' then SEE PLD;
6017 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006018 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6019 t = Bits32 (opcode, 15, 12);
6020 n = Bits32 (opcode, 19, 16);
6021 imm32 = Bits32 (opcode, 11, 0);
6022
6023 // index = TRUE; add = TRUE; wback = FALSE;
6024 index = true;
6025 add = true;
6026 wback = false;
6027
6028 // if t == 13 then UNPREDICTABLE;
6029 if (t == 13)
6030 return false;
6031
6032 break;
6033
6034 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006035 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6036 // if Rn == '1111' then SEE LDRB (literal);
6037 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6038 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006039 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6040 return false;
6041
6042 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6043 t = Bits32 (opcode, 15, 12);
6044 n = Bits32 (opcode, 19, 16);
6045 imm32 = Bits32 (opcode, 7, 0);
6046
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006047 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006048 index = BitIsSet (opcode, 10);
6049 add = BitIsSet (opcode, 9);
6050 wback = BitIsSet (opcode, 8);
6051
6052 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6053 if (BadReg (t) || (wback && (n == t)))
6054 return false;
6055
6056 break;
6057
6058 default:
6059 return false;
6060 }
6061
6062 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6063 if (!success)
6064 return false;
6065
6066 addr_t address;
6067 addr_t offset_addr;
6068
6069 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6070 if (add)
6071 offset_addr = Rn + imm32;
6072 else
6073 offset_addr = Rn - imm32;
6074
6075 // address = if index then offset_addr else R[n];
6076 if (index)
6077 address = offset_addr;
6078 else
6079 address = Rn;
6080
6081 // R[t] = ZeroExtend(MemU[address,1], 32);
6082 Register base_reg;
6083 Register data_reg;
6084 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6085 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6086
6087 EmulateInstruction::Context context;
6088 context.type = eContextRegisterLoad;
6089 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6090
6091 uint64_t data = MemURead (context, address, 1, 0, &success);
6092 if (!success)
6093 return false;
6094
6095 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6096 return false;
6097
6098 // if wback then R[n] = offset_addr;
6099 if (wback)
6100 {
6101 context.type = eContextAdjustBaseRegister;
6102 context.SetAddress (offset_addr);
6103 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6104 return false;
6105 }
6106 }
6107 return true;
6108}
Caroline Ticef55261f2011-02-18 22:24:22 +00006109
6110// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6111// zero-extends it to form a 32-bit word and writes it to a register.
6112bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006113EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006114{
6115#if 0
6116 if ConditionPassed() then
6117 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6118 base = Align(PC,4);
6119 address = if add then (base + imm32) else (base - imm32);
6120 R[t] = ZeroExtend(MemU[address,1], 32);
6121#endif
6122
6123 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006124
Greg Clayton7bc39082011-03-24 23:53:38 +00006125 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006126 {
6127 uint32_t t;
6128 uint32_t imm32;
6129 bool add;
6130 switch (encoding)
6131 {
6132 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006133 // if Rt == '1111' then SEE PLD;
6134 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006135 t = Bits32 (opcode, 15, 12);
6136 imm32 = Bits32 (opcode, 11, 0);
6137 add = BitIsSet (opcode, 23);
6138
6139 // if t == 13 then UNPREDICTABLE;
6140 if (t == 13)
6141 return false;
6142
6143 break;
6144
6145 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006146 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006147 t = Bits32 (opcode, 15, 12);
6148 imm32 = Bits32 (opcode, 11, 0);
6149 add = BitIsSet (opcode, 23);
6150
6151 // if t == 15 then UNPREDICTABLE;
6152 if (t == 15)
6153 return false;
6154 break;
6155
6156 default:
6157 return false;
6158 }
6159
6160 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006161 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006162 if (!success)
6163 return false;
6164
6165 uint32_t base = AlignPC (pc_val);
6166
6167 addr_t address;
6168 // address = if add then (base + imm32) else (base - imm32);
6169 if (add)
6170 address = base + imm32;
6171 else
6172 address = base - imm32;
6173
6174 // R[t] = ZeroExtend(MemU[address,1], 32);
6175 EmulateInstruction::Context context;
6176 context.type = eContextRelativeBranchImmediate;
6177 context.SetImmediate (address - base);
6178
6179 uint64_t data = MemURead (context, address, 1, 0, &success);
6180 if (!success)
6181 return false;
6182
6183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6184 return false;
6185 }
6186 return true;
6187}
Caroline Tice30fec122011-02-18 23:52:21 +00006188
6189// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6190// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6191// optionally be shifted.
6192bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006193EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006194{
6195#if 0
6196 if ConditionPassed() then
6197 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6198 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6199 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6200 address = if index then offset_addr else R[n];
6201 R[t] = ZeroExtend(MemU[address,1],32);
6202 if wback then R[n] = offset_addr;
6203#endif
6204
6205 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006206
Greg Clayton7bc39082011-03-24 23:53:38 +00006207 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006208 {
6209 uint32_t t;
6210 uint32_t n;
6211 uint32_t m;
6212 bool index;
6213 bool add;
6214 bool wback;
6215 ARM_ShifterType shift_t;
6216 uint32_t shift_n;
6217
6218 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6219 switch (encoding)
6220 {
6221 case eEncodingT1:
6222 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6223 t = Bits32 (opcode, 2, 0);
6224 n = Bits32 (opcode, 5, 3);
6225 m = Bits32 (opcode, 8, 6);
6226
6227 // index = TRUE; add = TRUE; wback = FALSE;
6228 index = true;
6229 add = true;
6230 wback = false;
6231
6232 // (shift_t, shift_n) = (SRType_LSL, 0);
6233 shift_t = SRType_LSL;
6234 shift_n = 0;
6235 break;
6236
6237 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006238 // if Rt == '1111' then SEE PLD;
6239 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006240 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6241 t = Bits32 (opcode, 15, 12);
6242 n = Bits32 (opcode, 19, 16);
6243 m = Bits32 (opcode, 3, 0);
6244
6245 // index = TRUE; add = TRUE; wback = FALSE;
6246 index = true;
6247 add = true;
6248 wback = false;
6249
6250 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6251 shift_t = SRType_LSL;
6252 shift_n = Bits32 (opcode, 5, 4);
6253
6254 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6255 if ((t == 13) || BadReg (m))
6256 return false;
6257 break;
6258
6259 case eEncodingA1:
6260 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006261 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006262 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6263 t = Bits32 (opcode, 15, 12);
6264 n = Bits32 (opcode, 19, 16);
6265 m = Bits32 (opcode, 3, 0);
6266
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006267 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006268 index = BitIsSet (opcode, 24);
6269 add = BitIsSet (opcode, 23);
6270 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6271
6272 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6273 uint32_t type = Bits32 (opcode, 6, 5);
6274 uint32_t imm5 = Bits32 (opcode, 11, 7);
6275 shift_n = DecodeImmShift (type, imm5, shift_t);
6276
6277 // if t == 15 || m == 15 then UNPREDICTABLE;
6278 if ((t == 15) || (m == 15))
6279 return false;
6280
6281 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6282 if (wback && ((n == 15) || (n == t)))
6283 return false;
6284 }
6285 break;
6286
6287 default:
6288 return false;
6289 }
6290
6291 addr_t offset_addr;
6292 addr_t address;
6293
6294 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6295 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6296 if (!success)
6297 return false;
6298
6299 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6300
6301 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6302 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6303 if (!success)
6304 return false;
6305
6306 if (add)
6307 offset_addr = Rn + offset;
6308 else
6309 offset_addr = Rn - offset;
6310
6311 // address = if index then offset_addr else R[n];
6312 if (index)
6313 address = offset_addr;
6314 else
6315 address = Rn;
6316
6317 // R[t] = ZeroExtend(MemU[address,1],32);
6318 Register base_reg;
6319 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6320
6321 EmulateInstruction::Context context;
6322 context.type = eContextRegisterLoad;
6323 context.SetRegisterPlusOffset (base_reg, address - Rn);
6324
6325 uint64_t data = MemURead (context, address, 1, 0, &success);
6326 if (!success)
6327 return false;
6328
6329 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6330 return false;
6331
6332 // if wback then R[n] = offset_addr;
6333 if (wback)
6334 {
6335 context.type = eContextAdjustBaseRegister;
6336 context.SetAddress (offset_addr);
6337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6338 return false;
6339 }
6340 }
6341 return true;
6342}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006343
6344// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6345// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6346// post-indexed, or pre-indexed addressing.
6347bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006348EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006349{
6350#if 0
6351 if ConditionPassed() then
6352 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6353 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6354 address = if index then offset_addr else R[n];
6355 data = MemU[address,2];
6356 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006357 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006358 R[t] = ZeroExtend(data, 32);
6359 else // Can only apply before ARMv7
6360 R[t] = bits(32) UNKNOWN;
6361#endif
6362
6363
6364 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006365
Greg Clayton7bc39082011-03-24 23:53:38 +00006366 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006367 {
6368 uint32_t t;
6369 uint32_t n;
6370 uint32_t imm32;
6371 bool index;
6372 bool add;
6373 bool wback;
6374
6375 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6376 switch (encoding)
6377 {
6378 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006379 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006380 t = Bits32 (opcode, 2, 0);
6381 n = Bits32 (opcode, 5, 3);
6382 imm32 = Bits32 (opcode, 10, 6) << 1;
6383
6384 // index = TRUE; add = TRUE; wback = FALSE;
6385 index = true;
6386 add = true;
6387 wback = false;
6388
6389 break;
6390
6391 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006392 // if Rt == '1111' then SEE "Unallocated memory hints";
6393 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006394 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6395 t = Bits32 (opcode, 15, 12);
6396 n = Bits32 (opcode, 19, 16);
6397 imm32 = Bits32 (opcode, 11, 0);
6398
6399 // index = TRUE; add = TRUE; wback = FALSE;
6400 index = true;
6401 add = true;
6402 wback = false;
6403
6404 // if t == 13 then UNPREDICTABLE;
6405 if (t == 13)
6406 return false;
6407 break;
6408
6409 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006410 // if Rn == '1111' then SEE LDRH (literal);
6411 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6412 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6413 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006414 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6415 return false;
6416
6417 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6418 t = Bits32 (opcode, 15, 12);
6419 n = Bits32 (opcode, 19, 16);
6420 imm32 = Bits32 (opcode, 7, 0);
6421
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006422 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006423 index = BitIsSet (opcode, 10);
6424 add = BitIsSet (opcode, 9);
6425 wback = BitIsSet (opcode, 8);
6426
6427 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6428 if (BadReg (t) || (wback && (n == t)))
6429 return false;
6430 break;
6431
6432 default:
6433 return false;
6434 }
6435
6436 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6437 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6438 if (!success)
6439 return false;
6440
6441 addr_t offset_addr;
6442 addr_t address;
6443
6444 if (add)
6445 offset_addr = Rn + imm32;
6446 else
6447 offset_addr = Rn - imm32;
6448
6449 // address = if index then offset_addr else R[n];
6450 if (index)
6451 address = offset_addr;
6452 else
6453 address = Rn;
6454
6455 // data = MemU[address,2];
6456 Register base_reg;
6457 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6458
6459 EmulateInstruction::Context context;
6460 context.type = eContextRegisterLoad;
6461 context.SetRegisterPlusOffset (base_reg, address - Rn);
6462
6463 uint64_t data = MemURead (context, address, 2, 0, &success);
6464 if (!success)
6465 return false;
6466
6467 // if wback then R[n] = offset_addr;
6468 if (wback)
6469 {
6470 context.type = eContextAdjustBaseRegister;
6471 context.SetAddress (offset_addr);
6472 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6473 return false;
6474 }
6475
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006476 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006477 if (UnalignedSupport () || BitIsClear (address, 0))
6478 {
6479 // R[t] = ZeroExtend(data, 32);
6480 context.type = eContextRegisterLoad;
6481 context.SetRegisterPlusOffset (base_reg, address - Rn);
6482 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6483 return false;
6484 }
6485 else // Can only apply before ARMv7
6486 {
6487 // R[t] = bits(32) UNKNOWN;
6488 WriteBits32Unknown (t);
6489 }
6490 }
6491 return true;
6492}
Caroline Ticefe479112011-02-18 18:52:37 +00006493
Caroline Tice952b5382011-02-28 23:15:24 +00006494// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6495// zero-extends it to form a 32-bit word, and writes it to a register.
6496bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006497EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006498{
6499#if 0
6500 if ConditionPassed() then
6501 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6502 base = Align(PC,4);
6503 address = if add then (base + imm32) else (base - imm32);
6504 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006505 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006506 R[t] = ZeroExtend(data, 32);
6507 else // Can only apply before ARMv7
6508 R[t] = bits(32) UNKNOWN;
6509#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006510
Caroline Tice952b5382011-02-28 23:15:24 +00006511 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006512
Greg Clayton7bc39082011-03-24 23:53:38 +00006513 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006514 {
6515 uint32_t t;
6516 uint32_t imm32;
6517 bool add;
6518
6519 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6520 switch (encoding)
6521 {
6522 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006523 // if Rt == '1111' then SEE "Unallocated memory hints";
6524 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006525 t = Bits32 (opcode, 15, 12);
6526 imm32 = Bits32 (opcode, 11, 0);
6527 add = BitIsSet (opcode, 23);
6528
6529 // if t == 13 then UNPREDICTABLE;
6530 if (t == 13)
6531 return false;
6532
6533 break;
6534
6535 case eEncodingA1:
6536 {
6537 uint32_t imm4H = Bits32 (opcode, 11, 8);
6538 uint32_t imm4L = Bits32 (opcode, 3, 0);
6539
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006540 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006541 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006542 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006543 add = BitIsSet (opcode, 23);
6544
6545 // if t == 15 then UNPREDICTABLE;
6546 if (t == 15)
6547 return false;
6548 break;
6549 }
6550
6551 default:
6552 return false;
6553 }
6554
6555 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006556 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006557 if (!success)
6558 return false;
6559
6560 addr_t base = AlignPC (pc_value);
6561 addr_t address;
6562
6563 // address = if add then (base + imm32) else (base - imm32);
6564 if (add)
6565 address = base + imm32;
6566 else
6567 address = base - imm32;
6568
6569 // data = MemU[address,2];
6570 Register base_reg;
6571 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6572
6573 EmulateInstruction::Context context;
6574 context.type = eContextRegisterLoad;
6575 context.SetRegisterPlusOffset (base_reg, address - base);
6576
6577 uint64_t data = MemURead (context, address, 2, 0, &success);
6578 if (!success)
6579 return false;
6580
6581
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006582 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006583 if (UnalignedSupport () || BitIsClear (address, 0))
6584 {
6585 // R[t] = ZeroExtend(data, 32);
6586 context.type = eContextRegisterLoad;
6587 context.SetRegisterPlusOffset (base_reg, address - base);
6588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6589 return false;
6590
6591 }
6592 else // Can only apply before ARMv7
6593 {
6594 // R[t] = bits(32) UNKNOWN;
6595 WriteBits32Unknown (t);
6596 }
6597 }
6598 return true;
6599}
6600
Caroline Tice0e6bc952011-03-01 18:00:42 +00006601// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6602// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6603// be shifted left by 0, 1, 2, or 3 bits.
6604bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006605EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006606{
6607#if 0
6608 if ConditionPassed() then
6609 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6610 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6611 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6612 address = if index then offset_addr else R[n];
6613 data = MemU[address,2];
6614 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006615 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006616 R[t] = ZeroExtend(data, 32);
6617 else // Can only apply before ARMv7
6618 R[t] = bits(32) UNKNOWN;
6619#endif
6620
6621 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006622
Greg Clayton7bc39082011-03-24 23:53:38 +00006623 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006624 {
6625 uint32_t t;
6626 uint32_t n;
6627 uint32_t m;
6628 bool index;
6629 bool add;
6630 bool wback;
6631 ARM_ShifterType shift_t;
6632 uint32_t shift_n;
6633
6634 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6635 switch (encoding)
6636 {
6637 case eEncodingT1:
6638 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6639 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6640 t = Bits32 (opcode, 2, 0);
6641 n = Bits32 (opcode, 5, 3);
6642 m = Bits32 (opcode, 8, 6);
6643
6644 // index = TRUE; add = TRUE; wback = FALSE;
6645 index = true;
6646 add = true;
6647 wback = false;
6648
6649 // (shift_t, shift_n) = (SRType_LSL, 0);
6650 shift_t = SRType_LSL;
6651 shift_n = 0;
6652
6653 break;
6654
6655 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006656 // if Rn == '1111' then SEE LDRH (literal);
6657 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006658 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6659 t = Bits32 (opcode, 15, 12);
6660 n = Bits32 (opcode, 19, 16);
6661 m = Bits32 (opcode, 3, 0);
6662
6663 // index = TRUE; add = TRUE; wback = FALSE;
6664 index = true;
6665 add = true;
6666 wback = false;
6667
6668 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6669 shift_t = SRType_LSL;
6670 shift_n = Bits32 (opcode, 5, 4);
6671
6672 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6673 if ((t == 13) || BadReg (m))
6674 return false;
6675 break;
6676
6677 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006678 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6680 t = Bits32 (opcode, 15, 12);
6681 n = Bits32 (opcode, 19, 16);
6682 m = Bits32 (opcode, 3, 0);
6683
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006684 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006685 index = BitIsSet (opcode, 24);
6686 add = BitIsSet (opcode, 23);
6687 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6688
6689 // (shift_t, shift_n) = (SRType_LSL, 0);
6690 shift_t = SRType_LSL;
6691 shift_n = 0;
6692
6693 // if t == 15 || m == 15 then UNPREDICTABLE;
6694 if ((t == 15) || (m == 15))
6695 return false;
6696
6697 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6698 if (wback && ((n == 15) || (n == t)))
6699 return false;
6700
6701 break;
6702
6703 default:
6704 return false;
6705 }
6706
6707 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6708
6709 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6710 if (!success)
6711 return false;
6712
6713 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6714
6715 addr_t offset_addr;
6716 addr_t address;
6717
6718 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6719 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6720 if (!success)
6721 return false;
6722
6723 if (add)
6724 offset_addr = Rn + offset;
6725 else
6726 offset_addr = Rn - offset;
6727
6728 // address = if index then offset_addr else R[n];
6729 if (index)
6730 address = offset_addr;
6731 else
6732 address = Rn;
6733
6734 // data = MemU[address,2];
6735 Register base_reg;
6736 Register offset_reg;
6737 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6738 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6739
6740 EmulateInstruction::Context context;
6741 context.type = eContextRegisterLoad;
6742 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6743 uint64_t data = MemURead (context, address, 2, 0, &success);
6744 if (!success)
6745 return false;
6746
6747 // if wback then R[n] = offset_addr;
6748 if (wback)
6749 {
6750 context.type = eContextAdjustBaseRegister;
6751 context.SetAddress (offset_addr);
6752 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6753 return false;
6754 }
6755
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006756 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006757 if (UnalignedSupport() || BitIsClear (address, 0))
6758 {
6759 // R[t] = ZeroExtend(data, 32);
6760 context.type = eContextRegisterLoad;
6761 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6762 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6763 return false;
6764 }
6765 else // Can only apply before ARMv7
6766 {
6767 // R[t] = bits(32) UNKNOWN;
6768 WriteBits32Unknown (t);
6769 }
6770 }
6771 return true;
6772}
6773
Caroline Ticea5e28af2011-03-01 21:53:03 +00006774// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6775// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6776// or pre-indexed addressing.
6777bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006778EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006779{
6780#if 0
6781 if ConditionPassed() then
6782 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6783 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6784 address = if index then offset_addr else R[n];
6785 R[t] = SignExtend(MemU[address,1], 32);
6786 if wback then R[n] = offset_addr;
6787#endif
6788
6789 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006790
Greg Clayton7bc39082011-03-24 23:53:38 +00006791 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006792 {
6793 uint32_t t;
6794 uint32_t n;
6795 uint32_t imm32;
6796 bool index;
6797 bool add;
6798 bool wback;
6799
6800 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6801 switch (encoding)
6802 {
6803 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006804 // if Rt == '1111' then SEE PLI;
6805 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006806 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6807 t = Bits32 (opcode, 15, 12);
6808 n = Bits32 (opcode, 19, 16);
6809 imm32 = Bits32 (opcode, 11, 0);
6810
6811 // index = TRUE; add = TRUE; wback = FALSE;
6812 index = true;
6813 add = true;
6814 wback = false;
6815
6816 // if t == 13 then UNPREDICTABLE;
6817 if (t == 13)
6818 return false;
6819
6820 break;
6821
6822 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006823 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6824 // if Rn == '1111' then SEE LDRSB (literal);
6825 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6826 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006827 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6828 return false;
6829
6830 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6831 t = Bits32 (opcode, 15, 12);
6832 n = Bits32 (opcode, 19, 16);
6833 imm32 = Bits32 (opcode, 7, 0);
6834
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006835 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006836 index = BitIsSet (opcode, 10);
6837 add = BitIsSet (opcode, 9);
6838 wback = BitIsSet (opcode, 8);
6839
6840 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006841 if (((t == 13) || ((t == 15)
6842 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6843 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006844 return false;
6845
6846 break;
6847
6848 case eEncodingA1:
6849 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006850 // if Rn == '1111' then SEE LDRSB (literal);
6851 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006852 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6853 t = Bits32 (opcode, 15, 12);
6854 n = Bits32 (opcode, 19, 16);
6855
6856 uint32_t imm4H = Bits32 (opcode, 11, 8);
6857 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006858 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006859
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006860 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006861 index = BitIsSet (opcode, 24);
6862 add = BitIsSet (opcode, 23);
6863 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6864
6865 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6866 if ((t == 15) || (wback && (n == t)))
6867 return false;
6868
6869 break;
6870 }
6871
6872 default:
6873 return false;
6874 }
6875
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006876 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006877 if (!success)
6878 return false;
6879
6880 addr_t offset_addr;
6881 addr_t address;
6882
6883 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6884 if (add)
6885 offset_addr = Rn + imm32;
6886 else
6887 offset_addr = Rn - imm32;
6888
6889 // address = if index then offset_addr else R[n];
6890 if (index)
6891 address = offset_addr;
6892 else
6893 address = Rn;
6894
6895 // R[t] = SignExtend(MemU[address,1], 32);
6896 Register base_reg;
6897 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6898
6899 EmulateInstruction::Context context;
6900 context.type = eContextRegisterLoad;
6901 context.SetRegisterPlusOffset (base_reg, address - Rn);
6902
6903 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6904 if (!success)
6905 return false;
6906
6907 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6908 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6909 return false;
6910
6911 // if wback then R[n] = offset_addr;
6912 if (wback)
6913 {
6914 context.type = eContextAdjustBaseRegister;
6915 context.SetAddress (offset_addr);
6916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6917 return false;
6918 }
6919 }
6920
6921 return true;
6922}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006923
Caroline Tice5f593912011-03-01 22:25:17 +00006924// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6925// sign-extends it to form a 32-bit word, and writes tit to a register.
6926bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006927EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006928{
6929#if 0
6930 if ConditionPassed() then
6931 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6932 base = Align(PC,4);
6933 address = if add then (base + imm32) else (base - imm32);
6934 R[t] = SignExtend(MemU[address,1], 32);
6935#endif
6936
6937 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006938
Greg Clayton7bc39082011-03-24 23:53:38 +00006939 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006940 {
6941 uint32_t t;
6942 uint32_t imm32;
6943 bool add;
6944
6945 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6946 switch (encoding)
6947 {
6948 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006949 // if Rt == '1111' then SEE PLI;
6950 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006951 t = Bits32 (opcode, 15, 12);
6952 imm32 = Bits32 (opcode, 11, 0);
6953 add = BitIsSet (opcode, 23);
6954
6955 // if t == 13 then UNPREDICTABLE;
6956 if (t == 13)
6957 return false;
6958
6959 break;
6960
6961 case eEncodingA1:
6962 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006963 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006964 t = Bits32 (opcode, 15, 12);
6965 uint32_t imm4H = Bits32 (opcode, 11, 8);
6966 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006967 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006968 add = BitIsSet (opcode, 23);
6969
6970 // if t == 15 then UNPREDICTABLE;
6971 if (t == 15)
6972 return false;
6973
6974 break;
6975 }
6976
6977 default:
6978 return false;
6979 }
6980
6981 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006982 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006983 if (!success)
6984 return false;
6985 uint64_t base = AlignPC (pc_value);
6986
6987 // address = if add then (base + imm32) else (base - imm32);
6988 addr_t address;
6989 if (add)
6990 address = base + imm32;
6991 else
6992 address = base - imm32;
6993
6994 // R[t] = SignExtend(MemU[address,1], 32);
6995 Register base_reg;
6996 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6997
6998 EmulateInstruction::Context context;
6999 context.type = eContextRegisterLoad;
7000 context.SetRegisterPlusOffset (base_reg, address - base);
7001
7002 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7003 if (!success)
7004 return false;
7005
7006 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7007 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7008 return false;
7009 }
7010 return true;
7011}
7012
Caroline Tice672f3112011-03-01 23:55:59 +00007013// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7014// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7015// shifted left by 0, 1, 2, or 3 bits.
7016bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007017EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007018{
7019#if 0
7020 if ConditionPassed() then
7021 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7022 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7023 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7024 address = if index then offset_addr else R[n];
7025 R[t] = SignExtend(MemU[address,1], 32);
7026 if wback then R[n] = offset_addr;
7027#endif
7028
7029 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007030
Greg Clayton7bc39082011-03-24 23:53:38 +00007031 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007032 {
7033 uint32_t t;
7034 uint32_t n;
7035 uint32_t m;
7036 bool index;
7037 bool add;
7038 bool wback;
7039 ARM_ShifterType shift_t;
7040 uint32_t shift_n;
7041
7042 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7043 switch (encoding)
7044 {
7045 case eEncodingT1:
7046 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7047 t = Bits32 (opcode, 2, 0);
7048 n = Bits32 (opcode, 5, 3);
7049 m = Bits32 (opcode, 8, 6);
7050
7051 // index = TRUE; add = TRUE; wback = FALSE;
7052 index = true;
7053 add = true;
7054 wback = false;
7055
7056 // (shift_t, shift_n) = (SRType_LSL, 0);
7057 shift_t = SRType_LSL;
7058 shift_n = 0;
7059
7060 break;
7061
7062 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007063 // if Rt == '1111' then SEE PLI;
7064 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007065 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7066 t = Bits32 (opcode, 15, 12);
7067 n = Bits32 (opcode, 19, 16);
7068 m = Bits32 (opcode, 3, 0);
7069
7070 // index = TRUE; add = TRUE; wback = FALSE;
7071 index = true;
7072 add = true;
7073 wback = false;
7074
7075 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7076 shift_t = SRType_LSL;
7077 shift_n = Bits32 (opcode, 5, 4);
7078
7079 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7080 if ((t == 13) || BadReg (m))
7081 return false;
7082 break;
7083
7084 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007085 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007086 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7087 t = Bits32 (opcode, 15, 12);
7088 n = Bits32 (opcode, 19, 16);
7089 m = Bits32 (opcode, 3, 0);
7090
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007091 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007092 index = BitIsSet (opcode, 24);
7093 add = BitIsSet (opcode, 23);
7094 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7095
7096 // (shift_t, shift_n) = (SRType_LSL, 0);
7097 shift_t = SRType_LSL;
7098 shift_n = 0;
7099
7100 // if t == 15 || m == 15 then UNPREDICTABLE;
7101 if ((t == 15) || (m == 15))
7102 return false;
7103
7104 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7105 if (wback && ((n == 15) || (n == t)))
7106 return false;
7107 break;
7108
7109 default:
7110 return false;
7111 }
7112
7113 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7114 if (!success)
7115 return false;
7116
7117 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7118 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7119
7120 addr_t offset_addr;
7121 addr_t address;
7122
7123 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7124 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7125 if (!success)
7126 return false;
7127
7128 if (add)
7129 offset_addr = Rn + offset;
7130 else
7131 offset_addr = Rn - offset;
7132
7133 // address = if index then offset_addr else R[n];
7134 if (index)
7135 address = offset_addr;
7136 else
7137 address = Rn;
7138
7139 // R[t] = SignExtend(MemU[address,1], 32);
7140 Register base_reg;
7141 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7142 Register offset_reg;
7143 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7144
7145 EmulateInstruction::Context context;
7146 context.type = eContextRegisterLoad;
7147 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7148
7149 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7150 if (!success)
7151 return false;
7152
7153 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7154 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7155 return false;
7156
7157 // if wback then R[n] = offset_addr;
7158 if (wback)
7159 {
7160 context.type = eContextAdjustBaseRegister;
7161 context.SetAddress (offset_addr);
7162 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7163 return false;
7164 }
7165 }
7166 return true;
7167}
7168
Caroline Tice78fb5632011-03-02 00:39:42 +00007169// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7170// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7171// pre-indexed addressing.
7172bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007173EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007174{
7175#if 0
7176 if ConditionPassed() then
7177 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7178 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7179 address = if index then offset_addr else R[n];
7180 data = MemU[address,2];
7181 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007182 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007183 R[t] = SignExtend(data, 32);
7184 else // Can only apply before ARMv7
7185 R[t] = bits(32) UNKNOWN;
7186#endif
7187
7188 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007189
Greg Clayton7bc39082011-03-24 23:53:38 +00007190 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007191 {
7192 uint32_t t;
7193 uint32_t n;
7194 uint32_t imm32;
7195 bool index;
7196 bool add;
7197 bool wback;
7198
7199 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7200 switch (encoding)
7201 {
7202 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007203 // if Rn == '1111' then SEE LDRSH (literal);
7204 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007205 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7206 t = Bits32 (opcode, 15, 12);
7207 n = Bits32 (opcode, 19, 16);
7208 imm32 = Bits32 (opcode, 11, 0);
7209
7210 // index = TRUE; add = TRUE; wback = FALSE;
7211 index = true;
7212 add = true;
7213 wback = false;
7214
7215 // if t == 13 then UNPREDICTABLE;
7216 if (t == 13)
7217 return false;
7218
7219 break;
7220
7221 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007222 // if Rn == '1111' then SEE LDRSH (literal);
7223 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7224 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7225 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007226 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7227 return false;
7228
7229 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7230 t = Bits32 (opcode, 15, 12);
7231 n = Bits32 (opcode, 19, 16);
7232 imm32 = Bits32 (opcode, 7, 0);
7233
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007234 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007235 index = BitIsSet (opcode, 10);
7236 add = BitIsSet (opcode, 9);
7237 wback = BitIsSet (opcode, 8);
7238
7239 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7240 if (BadReg (t) || (wback && (n == t)))
7241 return false;
7242
7243 break;
7244
7245 case eEncodingA1:
7246 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007247 // if Rn == '1111' then SEE LDRSH (literal);
7248 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007249 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7250 t = Bits32 (opcode, 15, 12);
7251 n = Bits32 (opcode, 19, 16);
7252 uint32_t imm4H = Bits32 (opcode, 11,8);
7253 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007254 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007255
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007256 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007257 index = BitIsSet (opcode, 24);
7258 add = BitIsSet (opcode, 23);
7259 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7260
7261 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7262 if ((t == 15) || (wback && (n == t)))
7263 return false;
7264
7265 break;
7266 }
7267
7268 default:
7269 return false;
7270 }
7271
7272 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7273 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7274 if (!success)
7275 return false;
7276
7277 addr_t offset_addr;
7278 if (add)
7279 offset_addr = Rn + imm32;
7280 else
7281 offset_addr = Rn - imm32;
7282
7283 // address = if index then offset_addr else R[n];
7284 addr_t address;
7285 if (index)
7286 address = offset_addr;
7287 else
7288 address = Rn;
7289
7290 // data = MemU[address,2];
7291 Register base_reg;
7292 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7293
7294 EmulateInstruction::Context context;
7295 context.type = eContextRegisterLoad;
7296 context.SetRegisterPlusOffset (base_reg, address - Rn);
7297
7298 uint64_t data = MemURead (context, address, 2, 0, &success);
7299 if (!success)
7300 return false;
7301
7302 // if wback then R[n] = offset_addr;
7303 if (wback)
7304 {
7305 context.type = eContextAdjustBaseRegister;
7306 context.SetAddress (offset_addr);
7307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7308 return false;
7309 }
7310
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007311 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007312 if (UnalignedSupport() || BitIsClear (address, 0))
7313 {
7314 // R[t] = SignExtend(data, 32);
7315 int64_t signed_data = llvm::SignExtend64<16>(data);
7316 context.type = eContextRegisterLoad;
7317 context.SetRegisterPlusOffset (base_reg, address - Rn);
7318 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7319 return false;
7320 }
7321 else // Can only apply before ARMv7
7322 {
7323 // R[t] = bits(32) UNKNOWN;
7324 WriteBits32Unknown (t);
7325 }
7326 }
7327 return true;
7328}
7329
Caroline Ticed2fac092011-03-02 19:45:34 +00007330// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7331// sign-extends it to from a 32-bit word, and writes it to a register.
7332bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007333EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007334{
7335#if 0
7336 if ConditionPassed() then
7337 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7338 base = Align(PC,4);
7339 address = if add then (base + imm32) else (base - imm32);
7340 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007341 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007342 R[t] = SignExtend(data, 32);
7343 else // Can only apply before ARMv7
7344 R[t] = bits(32) UNKNOWN;
7345#endif
7346
7347 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007348
Greg Clayton7bc39082011-03-24 23:53:38 +00007349 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007350 {
7351 uint32_t t;
7352 uint32_t imm32;
7353 bool add;
7354
7355 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7356 switch (encoding)
7357 {
7358 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007359 // if Rt == '1111' then SEE "Unallocated memory hints";
7360 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007361 t = Bits32 (opcode, 15, 12);
7362 imm32 = Bits32 (opcode, 11, 0);
7363 add = BitIsSet (opcode, 23);
7364
7365 // if t == 13 then UNPREDICTABLE;
7366 if (t == 13)
7367 return false;
7368
7369 break;
7370
7371 case eEncodingA1:
7372 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007373 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007374 t = Bits32 (opcode, 15, 12);
7375 uint32_t imm4H = Bits32 (opcode, 11, 8);
7376 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007377 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007378 add = BitIsSet (opcode, 23);
7379
7380 // if t == 15 then UNPREDICTABLE;
7381 if (t == 15)
7382 return false;
7383
7384 break;
7385 }
7386 default:
7387 return false;
7388 }
7389
7390 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007391 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007392 if (!success)
7393 return false;
7394
7395 uint64_t base = AlignPC (pc_value);
7396
7397 addr_t address;
7398 // address = if add then (base + imm32) else (base - imm32);
7399 if (add)
7400 address = base + imm32;
7401 else
7402 address = base - imm32;
7403
7404 // data = MemU[address,2];
7405 Register base_reg;
7406 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7407
7408 EmulateInstruction::Context context;
7409 context.type = eContextRegisterLoad;
7410 context.SetRegisterPlusOffset (base_reg, imm32);
7411
7412 uint64_t data = MemURead (context, address, 2, 0, &success);
7413 if (!success)
7414 return false;
7415
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007416 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007417 if (UnalignedSupport() || BitIsClear (address, 0))
7418 {
7419 // R[t] = SignExtend(data, 32);
7420 int64_t signed_data = llvm::SignExtend64<16>(data);
7421 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7422 return false;
7423 }
7424 else // Can only apply before ARMv7
7425 {
7426 // R[t] = bits(32) UNKNOWN;
7427 WriteBits32Unknown (t);
7428 }
7429 }
7430 return true;
7431}
7432
Caroline Tice291a3e92011-03-02 21:13:44 +00007433// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7434// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7435// shifted left by 0, 1, 2, or 3 bits.
7436bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007437EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007438{
7439#if 0
7440 if ConditionPassed() then
7441 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7442 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7443 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7444 address = if index then offset_addr else R[n];
7445 data = MemU[address,2];
7446 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007447 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007448 R[t] = SignExtend(data, 32);
7449 else // Can only apply before ARMv7
7450 R[t] = bits(32) UNKNOWN;
7451#endif
7452
7453 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007454
Greg Clayton7bc39082011-03-24 23:53:38 +00007455 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007456 {
7457 uint32_t t;
7458 uint32_t n;
7459 uint32_t m;
7460 bool index;
7461 bool add;
7462 bool wback;
7463 ARM_ShifterType shift_t;
7464 uint32_t shift_n;
7465
7466 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7467 switch (encoding)
7468 {
7469 case eEncodingT1:
7470 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7471 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7472 t = Bits32 (opcode, 2, 0);
7473 n = Bits32 (opcode, 5, 3);
7474 m = Bits32 (opcode, 8, 6);
7475
7476 // index = TRUE; add = TRUE; wback = FALSE;
7477 index = true;
7478 add = true;
7479 wback = false;
7480
7481 // (shift_t, shift_n) = (SRType_LSL, 0);
7482 shift_t = SRType_LSL;
7483 shift_n = 0;
7484
7485 break;
7486
7487 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007488 // if Rn == '1111' then SEE LDRSH (literal);
7489 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007490 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7491 t = Bits32 (opcode, 15, 12);
7492 n = Bits32 (opcode, 19, 16);
7493 m = Bits32 (opcode, 3, 0);
7494
7495 // index = TRUE; add = TRUE; wback = FALSE;
7496 index = true;
7497 add = true;
7498 wback = false;
7499
7500 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7501 shift_t = SRType_LSL;
7502 shift_n = Bits32 (opcode, 5, 4);
7503
7504 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7505 if ((t == 13) || BadReg (m))
7506 return false;
7507
7508 break;
7509
7510 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007511 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007512 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7513 t = Bits32 (opcode, 15, 12);
7514 n = Bits32 (opcode, 19, 16);
7515 m = Bits32 (opcode, 3, 0);
7516
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007517 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007518 index = BitIsSet (opcode, 24);
7519 add = BitIsSet (opcode, 23);
7520 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7521
7522 // (shift_t, shift_n) = (SRType_LSL, 0);
7523 shift_t = SRType_LSL;
7524 shift_n = 0;
7525
7526 // if t == 15 || m == 15 then UNPREDICTABLE;
7527 if ((t == 15) || (m == 15))
7528 return false;
7529
7530 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7531 if (wback && ((n == 15) || (n == t)))
7532 return false;
7533
7534 break;
7535
7536 default:
7537 break;
7538 }
7539
7540 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7541 if (!success)
7542 return false;
7543
7544 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7545 if (!success)
7546 return false;
7547
7548 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7549 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7550
7551 addr_t offset_addr;
7552 addr_t address;
7553
7554 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7555 if (add)
7556 offset_addr = Rn + offset;
7557 else
7558 offset_addr = Rn - offset;
7559
7560 // address = if index then offset_addr else R[n];
7561 if (index)
7562 address = offset_addr;
7563 else
7564 address = Rn;
7565
7566 // data = MemU[address,2];
7567 Register base_reg;
7568 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7569
7570 Register offset_reg;
7571 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7572
7573 EmulateInstruction::Context context;
7574 context.type = eContextRegisterLoad;
7575 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7576
7577 uint64_t data = MemURead (context, address, 2, 0, &success);
7578 if (!success)
7579 return false;
7580
7581 // if wback then R[n] = offset_addr;
7582 if (wback)
7583 {
7584 context.type = eContextAdjustBaseRegister;
7585 context.SetAddress (offset_addr);
7586 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7587 return false;
7588 }
7589
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007590 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007591 if (UnalignedSupport() || BitIsClear (address, 0))
7592 {
7593 // R[t] = SignExtend(data, 32);
7594 context.type = eContextRegisterLoad;
7595 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7596
7597 int64_t signed_data = llvm::SignExtend64<16>(data);
7598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7599 return false;
7600 }
7601 else // Can only apply before ARMv7
7602 {
7603 // R[t] = bits(32) UNKNOWN;
7604 WriteBits32Unknown (t);
7605 }
7606 }
7607 return true;
7608}
Caroline Tice6bf65162011-03-03 17:42:58 +00007609
7610// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7611// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7612bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007613EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007614{
7615#if 0
7616 if ConditionPassed() then
7617 EncodingSpecificOperations();
7618 rotated = ROR(R[m], rotation);
7619 R[d] = SignExtend(rotated<7:0>, 32);
7620#endif
7621
7622 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007623
Greg Clayton7bc39082011-03-24 23:53:38 +00007624 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007625 {
7626 uint32_t d;
7627 uint32_t m;
7628 uint32_t rotation;
7629
7630 // EncodingSpecificOperations();
7631 switch (encoding)
7632 {
7633 case eEncodingT1:
7634 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7635 d = Bits32 (opcode, 2, 0);
7636 m = Bits32 (opcode, 5, 3);
7637 rotation = 0;
7638
7639 break;
7640
7641 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007642 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007643 d = Bits32 (opcode, 11, 8);
7644 m = Bits32 (opcode, 3, 0);
7645 rotation = Bits32 (opcode, 5, 4) << 3;
7646
7647 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7648 if (BadReg (d) || BadReg (m))
7649 return false;
7650
7651 break;
7652
7653 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007654 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007655 d = Bits32 (opcode, 15, 12);
7656 m = Bits32 (opcode, 3, 0);
7657 rotation = Bits32 (opcode, 11, 10) << 3;
7658
7659 // if d == 15 || m == 15 then UNPREDICTABLE;
7660 if ((d == 15) || (m == 15))
7661 return false;
7662
7663 break;
7664
7665 default:
7666 return false;
7667 }
7668
Caroline Tice868198b2011-03-03 18:04:49 +00007669 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7670 if (!success)
7671 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007672
7673 // rotated = ROR(R[m], rotation);
7674 uint64_t rotated = ROR (Rm, rotation);
7675
7676 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007677 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007678
7679 Register source_reg;
7680 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7681
7682 EmulateInstruction::Context context;
7683 context.type = eContextRegisterLoad;
7684 context.SetRegister (source_reg);
7685
Caroline Tice8ce96d92011-03-03 18:27:17 +00007686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007687 return false;
7688 }
7689 return true;
7690}
Caroline Tice291a3e92011-03-02 21:13:44 +00007691
Caroline Tice868198b2011-03-03 18:04:49 +00007692// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7693// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7694bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007695EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007696{
7697#if 0
7698 if ConditionPassed() then
7699 EncodingSpecificOperations();
7700 rotated = ROR(R[m], rotation);
7701 R[d] = SignExtend(rotated<15:0>, 32);
7702#endif
7703
7704 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007705
Greg Clayton7bc39082011-03-24 23:53:38 +00007706 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007707 {
7708 uint32_t d;
7709 uint32_t m;
7710 uint32_t rotation;
7711
7712 // EncodingSpecificOperations();
7713 switch (encoding)
7714 {
7715 case eEncodingT1:
7716 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7717 d = Bits32 (opcode, 2, 0);
7718 m = Bits32 (opcode, 5, 3);
7719 rotation = 0;
7720
7721 break;
7722
7723 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007724 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007725 d = Bits32 (opcode, 11, 8);
7726 m = Bits32 (opcode, 3, 0);
7727 rotation = Bits32 (opcode, 5, 4) << 3;
7728
7729 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7730 if (BadReg (d) || BadReg (m))
7731 return false;
7732
7733 break;
7734
7735 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007736 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007737 d = Bits32 (opcode, 15, 12);
7738 m = Bits32 (opcode, 3, 0);
7739 rotation = Bits32 (opcode, 11, 10) << 3;
7740
7741 // if d == 15 || m == 15 then UNPREDICTABLE;
7742 if ((d == 15) || (m == 15))
7743 return false;
7744
7745 break;
7746
7747 default:
7748 return false;
7749 }
7750
7751 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7752 if (!success)
7753 return false;
7754
7755 // rotated = ROR(R[m], rotation);
7756 uint64_t rotated = ROR (Rm, rotation);
7757
7758 // R[d] = SignExtend(rotated<15:0>, 32);
7759 Register source_reg;
7760 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7761
7762 EmulateInstruction::Context context;
7763 context.type = eContextRegisterLoad;
7764 context.SetRegister (source_reg);
7765
Caroline Tice8ce96d92011-03-03 18:27:17 +00007766 int64_t data = llvm::SignExtend64<16> (rotated);
7767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007768 return false;
7769 }
7770
7771 return true;
7772}
7773
Caroline Tice8ce96d92011-03-03 18:27:17 +00007774// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7775// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7776bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007777EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007778{
7779#if 0
7780 if ConditionPassed() then
7781 EncodingSpecificOperations();
7782 rotated = ROR(R[m], rotation);
7783 R[d] = ZeroExtend(rotated<7:0>, 32);
7784#endif
7785
7786 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007787
Greg Clayton7bc39082011-03-24 23:53:38 +00007788 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007789 {
7790 uint32_t d;
7791 uint32_t m;
7792 uint32_t rotation;
7793
7794 // EncodingSpecificOperations();
7795 switch (encoding)
7796 {
7797 case eEncodingT1:
7798 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7799 d = Bits32 (opcode, 2, 0);
7800 m = Bits32 (opcode, 5, 3);
7801 rotation = 0;
7802
7803 break;
7804
7805 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007806 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007807 d = Bits32 (opcode, 11, 8);
7808 m = Bits32 (opcode, 3, 0);
7809 rotation = Bits32 (opcode, 5, 4) << 3;
7810
7811 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7812 if (BadReg (d) || BadReg (m))
7813 return false;
7814
7815 break;
7816
7817 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007818 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007819 d = Bits32 (opcode, 15, 12);
7820 m = Bits32 (opcode, 3, 0);
7821 rotation = Bits32 (opcode, 11, 10) << 3;
7822
7823 // if d == 15 || m == 15 then UNPREDICTABLE;
7824 if ((d == 15) || (m == 15))
7825 return false;
7826
7827 break;
7828
7829 default:
7830 return false;
7831 }
7832
7833 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7834 if (!success)
7835 return false;
7836
7837 // rotated = ROR(R[m], rotation);
7838 uint64_t rotated = ROR (Rm, rotation);
7839
7840 // R[d] = ZeroExtend(rotated<7:0>, 32);
7841 Register source_reg;
7842 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7843
7844 EmulateInstruction::Context context;
7845 context.type = eContextRegisterLoad;
7846 context.SetRegister (source_reg);
7847
7848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7849 return false;
7850 }
7851 return true;
7852}
7853
Caroline Tice11555f22011-03-03 18:48:58 +00007854// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7855// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7856bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007857EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007858{
7859#if 0
7860 if ConditionPassed() then
7861 EncodingSpecificOperations();
7862 rotated = ROR(R[m], rotation);
7863 R[d] = ZeroExtend(rotated<15:0>, 32);
7864#endif
7865
7866 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007867
Greg Clayton7bc39082011-03-24 23:53:38 +00007868 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007869 {
7870 uint32_t d;
7871 uint32_t m;
7872 uint32_t rotation;
7873
7874 switch (encoding)
7875 {
7876 case eEncodingT1:
7877 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7878 d = Bits32 (opcode, 2, 0);
7879 m = Bits32 (opcode, 5, 3);
7880 rotation = 0;
7881
7882 break;
7883
7884 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007885 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007886 d = Bits32 (opcode, 11, 8);
7887 m = Bits32 (opcode, 3, 0);
7888 rotation = Bits32 (opcode, 5, 4) << 3;
7889
7890 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7891 if (BadReg (d) || BadReg (m))
7892 return false;
7893
7894 break;
7895
7896 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007897 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007898 d = Bits32 (opcode, 15, 12);
7899 m = Bits32 (opcode, 3, 0);
7900 rotation = Bits32 (opcode, 11, 10) << 3;
7901
7902 // if d == 15 || m == 15 then UNPREDICTABLE;
7903 if ((d == 15) || (m == 15))
7904 return false;
7905
7906 break;
7907
7908 default:
7909 return false;
7910 }
7911
7912 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7913 if (!success)
7914 return false;
7915
7916 // rotated = ROR(R[m], rotation);
7917 uint64_t rotated = ROR (Rm, rotation);
7918
7919 // R[d] = ZeroExtend(rotated<15:0>, 32);
7920 Register source_reg;
7921 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7922
7923 EmulateInstruction::Context context;
7924 context.type = eContextRegisterLoad;
7925 context.SetRegister (source_reg);
7926
7927 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7928 return false;
7929 }
7930 return true;
7931}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007932
7933// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7934// word respectively.
7935bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007936EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007937{
7938#if 0
7939 if ConditionPassed() then
7940 EncodingSpecificOperations();
7941 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7942 UNPREDICTABLE;
7943 else
7944 address = if increment then R[n] else R[n]-8;
7945 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007946 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007947 BranchWritePC(MemA[address,4]);
7948 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7949#endif
7950
7951 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007952
Greg Clayton7bc39082011-03-24 23:53:38 +00007953 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007954 {
7955 uint32_t n;
7956 bool wback;
7957 bool increment;
7958 bool wordhigher;
7959
7960 // EncodingSpecificOperations();
7961 switch (encoding)
7962 {
7963 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007964 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007965 n = Bits32 (opcode, 19, 16);
7966 wback = BitIsSet (opcode, 21);
7967 increment = false;
7968 wordhigher = false;
7969
7970 // if n == 15 then UNPREDICTABLE;
7971 if (n == 15)
7972 return false;
7973
7974 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7975 if (InITBlock() && !LastInITBlock())
7976 return false;
7977
7978 break;
7979
7980 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007981 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007982 n = Bits32 (opcode, 19, 16);
7983 wback = BitIsSet (opcode, 21);
7984 increment = true;
7985 wordhigher = false;
7986
7987 // if n == 15 then UNPREDICTABLE;
7988 if (n == 15)
7989 return false;
7990
7991 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7992 if (InITBlock() && !LastInITBlock())
7993 return false;
7994
7995 break;
7996
7997 case eEncodingA1:
7998 // n = UInt(Rn);
7999 n = Bits32 (opcode, 19, 16);
8000
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008001 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008002 wback = BitIsSet (opcode, 21);
8003 increment = BitIsSet (opcode, 23);
8004 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8005
8006 // if n == 15 then UNPREDICTABLE;
8007 if (n == 15)
8008 return false;
8009
8010 break;
8011
8012 default:
8013 return false;
8014 }
8015
8016 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8017 if (!CurrentModeIsPrivileged ())
8018 // UNPREDICTABLE;
8019 return false;
8020 else
8021 {
8022 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8023 if (!success)
8024 return false;
8025
8026 addr_t address;
8027 // address = if increment then R[n] else R[n]-8;
8028 if (increment)
8029 address = Rn;
8030 else
8031 address = Rn - 8;
8032
8033 // if wordhigher then address = address+4;
8034 if (wordhigher)
8035 address = address + 4;
8036
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008037 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008038 Register base_reg;
8039 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8040
8041 EmulateInstruction::Context context;
8042 context.type = eContextReturnFromException;
8043 context.SetRegisterPlusOffset (base_reg, address - Rn);
8044
8045 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8046 if (!success)
8047 return false;
8048
8049 CPSRWriteByInstr (data, 15, true);
8050
8051 // BranchWritePC(MemA[address,4]);
8052 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8053 if (!success)
8054 return false;
8055
8056 BranchWritePC (context, data2);
8057
8058 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8059 if (wback)
8060 {
8061 context.type = eContextAdjustBaseRegister;
8062 if (increment)
8063 {
8064 context.SetOffset (8);
8065 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8066 return false;
8067 }
8068 else
8069 {
8070 context.SetOffset (-8);
8071 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8072 return false;
8073 }
8074 } // if wback
8075 }
8076 } // if ConditionPassed()
8077 return true;
8078}
Caroline Tice11555f22011-03-03 18:48:58 +00008079
Johnny Chen2115b412011-02-21 23:42:44 +00008080// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8081// and writes the result to the destination register. It can optionally update the condition flags based on
8082// the result.
8083bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008084EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008085{
8086#if 0
8087 // ARM pseudo code...
8088 if ConditionPassed() then
8089 EncodingSpecificOperations();
8090 result = R[n] EOR imm32;
8091 if d == 15 then // Can only occur for ARM encoding
8092 ALUWritePC(result); // setflags is always FALSE here
8093 else
8094 R[d] = result;
8095 if setflags then
8096 APSR.N = result<31>;
8097 APSR.Z = IsZeroBit(result);
8098 APSR.C = carry;
8099 // APSR.V unchanged
8100#endif
8101
8102 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008103
Greg Clayton7bc39082011-03-24 23:53:38 +00008104 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008105 {
8106 uint32_t Rd, Rn;
8107 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8108 bool setflags;
8109 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8110 switch (encoding)
8111 {
8112 case eEncodingT1:
8113 Rd = Bits32(opcode, 11, 8);
8114 Rn = Bits32(opcode, 19, 16);
8115 setflags = BitIsSet(opcode, 20);
8116 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8117 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8118 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008119 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008120 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8121 return false;
8122 break;
8123 case eEncodingA1:
8124 Rd = Bits32(opcode, 15, 12);
8125 Rn = Bits32(opcode, 19, 16);
8126 setflags = BitIsSet(opcode, 20);
8127 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8128 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8129 // TODO: Emulate SUBS PC, LR and related instructions.
8130 if (Rd == 15 && setflags)
8131 return false;
8132 break;
8133 default:
8134 return false;
8135 }
8136
8137 // Read the first operand.
8138 uint32_t val1 = ReadCoreReg(Rn, &success);
8139 if (!success)
8140 return false;
8141
8142 uint32_t result = val1 ^ imm32;
8143
8144 EmulateInstruction::Context context;
8145 context.type = EmulateInstruction::eContextImmediate;
8146 context.SetNoArgs ();
8147
8148 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8149 return false;
8150 }
8151 return true;
8152}
8153
8154// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8155// optionally-shifted register value, and writes the result to the destination register.
8156// It can optionally update the condition flags based on the result.
8157bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008158EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008159{
8160#if 0
8161 // ARM pseudo code...
8162 if ConditionPassed() then
8163 EncodingSpecificOperations();
8164 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8165 result = R[n] EOR shifted;
8166 if d == 15 then // Can only occur for ARM encoding
8167 ALUWritePC(result); // setflags is always FALSE here
8168 else
8169 R[d] = result;
8170 if setflags then
8171 APSR.N = result<31>;
8172 APSR.Z = IsZeroBit(result);
8173 APSR.C = carry;
8174 // APSR.V unchanged
8175#endif
8176
8177 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008178
Greg Clayton7bc39082011-03-24 23:53:38 +00008179 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008180 {
8181 uint32_t Rd, Rn, Rm;
8182 ARM_ShifterType shift_t;
8183 uint32_t shift_n; // the shift applied to the value read from Rm
8184 bool setflags;
8185 uint32_t carry;
8186 switch (encoding)
8187 {
8188 case eEncodingT1:
8189 Rd = Rn = Bits32(opcode, 2, 0);
8190 Rm = Bits32(opcode, 5, 3);
8191 setflags = !InITBlock();
8192 shift_t = SRType_LSL;
8193 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008194 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008195 case eEncodingT2:
8196 Rd = Bits32(opcode, 11, 8);
8197 Rn = Bits32(opcode, 19, 16);
8198 Rm = Bits32(opcode, 3, 0);
8199 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008200 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8201 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008202 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008203 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008204 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8205 return false;
8206 break;
8207 case eEncodingA1:
8208 Rd = Bits32(opcode, 15, 12);
8209 Rn = Bits32(opcode, 19, 16);
8210 Rm = Bits32(opcode, 3, 0);
8211 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008212 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008213 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8214 // TODO: Emulate SUBS PC, LR and related instructions.
8215 if (Rd == 15 && setflags)
8216 return false;
8217 break;
8218 default:
8219 return false;
8220 }
8221
8222 // Read the first operand.
8223 uint32_t val1 = ReadCoreReg(Rn, &success);
8224 if (!success)
8225 return false;
8226
8227 // Read the second operand.
8228 uint32_t val2 = ReadCoreReg(Rm, &success);
8229 if (!success)
8230 return false;
8231
8232 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8233 uint32_t result = val1 ^ shifted;
8234
8235 EmulateInstruction::Context context;
8236 context.type = EmulateInstruction::eContextImmediate;
8237 context.SetNoArgs ();
8238
8239 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8240 return false;
8241 }
8242 return true;
8243}
8244
Johnny Chen7c5234d2011-02-18 23:41:11 +00008245// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8246// writes the result to the destination register. It can optionally update the condition flags based
8247// on the result.
8248bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008249EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008250{
8251#if 0
8252 // ARM pseudo code...
8253 if ConditionPassed() then
8254 EncodingSpecificOperations();
8255 result = R[n] OR imm32;
8256 if d == 15 then // Can only occur for ARM encoding
8257 ALUWritePC(result); // setflags is always FALSE here
8258 else
8259 R[d] = result;
8260 if setflags then
8261 APSR.N = result<31>;
8262 APSR.Z = IsZeroBit(result);
8263 APSR.C = carry;
8264 // APSR.V unchanged
8265#endif
8266
8267 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008268
Greg Clayton7bc39082011-03-24 23:53:38 +00008269 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008270 {
8271 uint32_t Rd, Rn;
8272 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8273 bool setflags;
8274 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8275 switch (encoding)
8276 {
8277 case eEncodingT1:
8278 Rd = Bits32(opcode, 11, 8);
8279 Rn = Bits32(opcode, 19, 16);
8280 setflags = BitIsSet(opcode, 20);
8281 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008282 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008283 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008284 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008285 if (BadReg(Rd) || Rn == 13)
8286 return false;
8287 break;
8288 case eEncodingA1:
8289 Rd = Bits32(opcode, 15, 12);
8290 Rn = Bits32(opcode, 19, 16);
8291 setflags = BitIsSet(opcode, 20);
8292 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8293 // TODO: Emulate SUBS PC, LR and related instructions.
8294 if (Rd == 15 && setflags)
8295 return false;
8296 break;
8297 default:
8298 return false;
8299 }
8300
8301 // Read the first operand.
8302 uint32_t val1 = ReadCoreReg(Rn, &success);
8303 if (!success)
8304 return false;
8305
8306 uint32_t result = val1 | imm32;
8307
8308 EmulateInstruction::Context context;
8309 context.type = EmulateInstruction::eContextImmediate;
8310 context.SetNoArgs ();
8311
8312 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8313 return false;
8314 }
8315 return true;
8316}
8317
8318// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8319// value, and writes the result to the destination register. It can optionally update the condition flags based
8320// on the result.
8321bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008322EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008323{
8324#if 0
8325 // ARM pseudo code...
8326 if ConditionPassed() then
8327 EncodingSpecificOperations();
8328 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8329 result = R[n] OR shifted;
8330 if d == 15 then // Can only occur for ARM encoding
8331 ALUWritePC(result); // setflags is always FALSE here
8332 else
8333 R[d] = result;
8334 if setflags then
8335 APSR.N = result<31>;
8336 APSR.Z = IsZeroBit(result);
8337 APSR.C = carry;
8338 // APSR.V unchanged
8339#endif
8340
8341 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008342
Greg Clayton7bc39082011-03-24 23:53:38 +00008343 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008344 {
8345 uint32_t Rd, Rn, Rm;
8346 ARM_ShifterType shift_t;
8347 uint32_t shift_n; // the shift applied to the value read from Rm
8348 bool setflags;
8349 uint32_t carry;
8350 switch (encoding)
8351 {
8352 case eEncodingT1:
8353 Rd = Rn = Bits32(opcode, 2, 0);
8354 Rm = Bits32(opcode, 5, 3);
8355 setflags = !InITBlock();
8356 shift_t = SRType_LSL;
8357 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008358 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008359 case eEncodingT2:
8360 Rd = Bits32(opcode, 11, 8);
8361 Rn = Bits32(opcode, 19, 16);
8362 Rm = Bits32(opcode, 3, 0);
8363 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008364 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8365 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008366 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008367 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008368 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8369 return false;
8370 break;
8371 case eEncodingA1:
8372 Rd = Bits32(opcode, 15, 12);
8373 Rn = Bits32(opcode, 19, 16);
8374 Rm = Bits32(opcode, 3, 0);
8375 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008376 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008377 // TODO: Emulate SUBS PC, LR and related instructions.
8378 if (Rd == 15 && setflags)
8379 return false;
8380 break;
8381 default:
8382 return false;
8383 }
8384
8385 // Read the first operand.
8386 uint32_t val1 = ReadCoreReg(Rn, &success);
8387 if (!success)
8388 return false;
8389
8390 // Read the second operand.
8391 uint32_t val2 = ReadCoreReg(Rm, &success);
8392 if (!success)
8393 return false;
8394
8395 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008396 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008397
8398 EmulateInstruction::Context context;
8399 context.type = EmulateInstruction::eContextImmediate;
8400 context.SetNoArgs ();
8401
8402 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8403 return false;
8404 }
8405 return true;
8406}
8407
Johnny Chened32e7c2011-02-22 23:42:58 +00008408// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8409// the destination register. It can optionally update the condition flags based on the result.
8410bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008411EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008412{
8413#if 0
8414 // ARM pseudo code...
8415 if ConditionPassed() then
8416 EncodingSpecificOperations();
8417 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8418 if d == 15 then // Can only occur for ARM encoding
8419 ALUWritePC(result); // setflags is always FALSE here
8420 else
8421 R[d] = result;
8422 if setflags then
8423 APSR.N = result<31>;
8424 APSR.Z = IsZeroBit(result);
8425 APSR.C = carry;
8426 APSR.V = overflow;
8427#endif
8428
8429 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008430
8431 uint32_t Rd; // the destination register
8432 uint32_t Rn; // the first operand
8433 bool setflags;
8434 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8435 switch (encoding) {
8436 case eEncodingT1:
8437 Rd = Bits32(opcode, 2, 0);
8438 Rn = Bits32(opcode, 5, 3);
8439 setflags = !InITBlock();
8440 imm32 = 0;
8441 break;
8442 case eEncodingT2:
8443 Rd = Bits32(opcode, 11, 8);
8444 Rn = Bits32(opcode, 19, 16);
8445 setflags = BitIsSet(opcode, 20);
8446 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8447 if (BadReg(Rd) || BadReg(Rn))
8448 return false;
8449 break;
8450 case eEncodingA1:
8451 Rd = Bits32(opcode, 15, 12);
8452 Rn = Bits32(opcode, 19, 16);
8453 setflags = BitIsSet(opcode, 20);
8454 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8455 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8456 // TODO: Emulate SUBS PC, LR and related instructions.
8457 if (Rd == 15 && setflags)
8458 return false;
8459 break;
8460 default:
8461 return false;
8462 }
8463 // Read the register value from the operand register Rn.
8464 uint32_t reg_val = ReadCoreReg(Rn, &success);
8465 if (!success)
8466 return false;
8467
8468 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8469
8470 EmulateInstruction::Context context;
8471 context.type = EmulateInstruction::eContextImmediate;
8472 context.SetNoArgs ();
8473
8474 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8475 return false;
8476
8477 return true;
8478}
8479
8480// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8481// result to the destination register. It can optionally update the condition flags based on the result.
8482bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008483EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008484{
8485#if 0
8486 // ARM pseudo code...
8487 if ConditionPassed() then
8488 EncodingSpecificOperations();
8489 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8490 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8491 if d == 15 then // Can only occur for ARM encoding
8492 ALUWritePC(result); // setflags is always FALSE here
8493 else
8494 R[d] = result;
8495 if setflags then
8496 APSR.N = result<31>;
8497 APSR.Z = IsZeroBit(result);
8498 APSR.C = carry;
8499 APSR.V = overflow;
8500#endif
8501
8502 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008503
8504 uint32_t Rd; // the destination register
8505 uint32_t Rn; // the first operand
8506 uint32_t Rm; // the second operand
8507 bool setflags;
8508 ARM_ShifterType shift_t;
8509 uint32_t shift_n; // the shift applied to the value read from Rm
8510 switch (encoding) {
8511 case eEncodingT1:
8512 Rd = Bits32(opcode, 11, 8);
8513 Rn = Bits32(opcode, 19, 16);
8514 Rm = Bits32(opcode, 3, 0);
8515 setflags = BitIsSet(opcode, 20);
8516 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8517 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8518 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8519 return false;
8520 break;
8521 case eEncodingA1:
8522 Rd = Bits32(opcode, 15, 12);
8523 Rn = Bits32(opcode, 19, 16);
8524 Rm = Bits32(opcode, 3, 0);
8525 setflags = BitIsSet(opcode, 20);
8526 shift_n = DecodeImmShiftARM(opcode, shift_t);
8527 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8528 // TODO: Emulate SUBS PC, LR and related instructions.
8529 if (Rd == 15 && setflags)
8530 return false;
8531 break;
8532 default:
8533 return false;
8534 }
8535 // Read the register value from register Rn.
8536 uint32_t val1 = ReadCoreReg(Rn, &success);
8537 if (!success)
8538 return false;
8539
8540 // Read the register value from register Rm.
8541 uint32_t val2 = ReadCoreReg(Rm, &success);
8542 if (!success)
8543 return false;
8544
8545 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8546 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8547
8548 EmulateInstruction::Context context;
8549 context.type = EmulateInstruction::eContextImmediate;
8550 context.SetNoArgs();
8551 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8552 return false;
8553
8554 return true;
8555}
8556
Johnny Chen90e607b2011-02-23 00:07:09 +00008557// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8558// an immediate value, and writes the result to the destination register. It can optionally update the condition
8559// flags based on the result.
8560bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008561EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008562{
8563#if 0
8564 // ARM pseudo code...
8565 if ConditionPassed() then
8566 EncodingSpecificOperations();
8567 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8568 if d == 15 then
8569 ALUWritePC(result); // setflags is always FALSE here
8570 else
8571 R[d] = result;
8572 if setflags then
8573 APSR.N = result<31>;
8574 APSR.Z = IsZeroBit(result);
8575 APSR.C = carry;
8576 APSR.V = overflow;
8577#endif
8578
8579 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008580
8581 uint32_t Rd; // the destination register
8582 uint32_t Rn; // the first operand
8583 bool setflags;
8584 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8585 switch (encoding) {
8586 case eEncodingA1:
8587 Rd = Bits32(opcode, 15, 12);
8588 Rn = Bits32(opcode, 19, 16);
8589 setflags = BitIsSet(opcode, 20);
8590 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8591 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8592 // TODO: Emulate SUBS PC, LR and related instructions.
8593 if (Rd == 15 && setflags)
8594 return false;
8595 break;
8596 default:
8597 return false;
8598 }
8599 // Read the register value from the operand register Rn.
8600 uint32_t reg_val = ReadCoreReg(Rn, &success);
8601 if (!success)
8602 return false;
8603
8604 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8605
8606 EmulateInstruction::Context context;
8607 context.type = EmulateInstruction::eContextImmediate;
8608 context.SetNoArgs ();
8609
8610 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8611 return false;
8612
8613 return true;
8614}
8615
8616// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8617// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8618// condition flags based on the result.
8619bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008620EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008621{
8622#if 0
8623 // ARM pseudo code...
8624 if ConditionPassed() then
8625 EncodingSpecificOperations();
8626 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8627 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8628 if d == 15 then
8629 ALUWritePC(result); // setflags is always FALSE here
8630 else
8631 R[d] = result;
8632 if setflags then
8633 APSR.N = result<31>;
8634 APSR.Z = IsZeroBit(result);
8635 APSR.C = carry;
8636 APSR.V = overflow;
8637#endif
8638
8639 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008640
8641 uint32_t Rd; // the destination register
8642 uint32_t Rn; // the first operand
8643 uint32_t Rm; // the second operand
8644 bool setflags;
8645 ARM_ShifterType shift_t;
8646 uint32_t shift_n; // the shift applied to the value read from Rm
8647 switch (encoding) {
8648 case eEncodingA1:
8649 Rd = Bits32(opcode, 15, 12);
8650 Rn = Bits32(opcode, 19, 16);
8651 Rm = Bits32(opcode, 3, 0);
8652 setflags = BitIsSet(opcode, 20);
8653 shift_n = DecodeImmShiftARM(opcode, shift_t);
8654 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8655 // TODO: Emulate SUBS PC, LR and related instructions.
8656 if (Rd == 15 && setflags)
8657 return false;
8658 break;
8659 default:
8660 return false;
8661 }
8662 // Read the register value from register Rn.
8663 uint32_t val1 = ReadCoreReg(Rn, &success);
8664 if (!success)
8665 return false;
8666
8667 // Read the register value from register Rm.
8668 uint32_t val2 = ReadCoreReg(Rm, &success);
8669 if (!success)
8670 return false;
8671
8672 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8673 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8674
8675 EmulateInstruction::Context context;
8676 context.type = EmulateInstruction::eContextImmediate;
8677 context.SetNoArgs();
8678 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8679 return false;
8680
8681 return true;
8682}
8683
Johnny Chen9b381772011-02-23 01:01:21 +00008684// Subtract with Carry (immediate) subtracts an immediate value and the value of
8685// NOT (Carry flag) from a register value, and writes the result to the destination register.
8686// It can optionally update the condition flags based on the result.
8687bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008688EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008689{
8690#if 0
8691 // ARM pseudo code...
8692 if ConditionPassed() then
8693 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008694 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008695 if d == 15 then // Can only occur for ARM encoding
8696 ALUWritePC(result); // setflags is always FALSE here
8697 else
8698 R[d] = result;
8699 if setflags then
8700 APSR.N = result<31>;
8701 APSR.Z = IsZeroBit(result);
8702 APSR.C = carry;
8703 APSR.V = overflow;
8704#endif
8705
8706 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008707
8708 uint32_t Rd; // the destination register
8709 uint32_t Rn; // the first operand
8710 bool setflags;
8711 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8712 switch (encoding) {
8713 case eEncodingT1:
8714 Rd = Bits32(opcode, 11, 8);
8715 Rn = Bits32(opcode, 19, 16);
8716 setflags = BitIsSet(opcode, 20);
8717 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8718 if (BadReg(Rd) || BadReg(Rn))
8719 return false;
8720 break;
8721 case eEncodingA1:
8722 Rd = Bits32(opcode, 15, 12);
8723 Rn = Bits32(opcode, 19, 16);
8724 setflags = BitIsSet(opcode, 20);
8725 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8726 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8727 // TODO: Emulate SUBS PC, LR and related instructions.
8728 if (Rd == 15 && setflags)
8729 return false;
8730 break;
8731 default:
8732 return false;
8733 }
8734 // Read the register value from the operand register Rn.
8735 uint32_t reg_val = ReadCoreReg(Rn, &success);
8736 if (!success)
8737 return false;
8738
8739 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8740
8741 EmulateInstruction::Context context;
8742 context.type = EmulateInstruction::eContextImmediate;
8743 context.SetNoArgs ();
8744
8745 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8746 return false;
8747
8748 return true;
8749}
8750
8751// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8752// NOT (Carry flag) from a register value, and writes the result to the destination register.
8753// It can optionally update the condition flags based on the result.
8754bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008755EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008756{
8757#if 0
8758 // ARM pseudo code...
8759 if ConditionPassed() then
8760 EncodingSpecificOperations();
8761 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8762 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8763 if d == 15 then // Can only occur for ARM encoding
8764 ALUWritePC(result); // setflags is always FALSE here
8765 else
8766 R[d] = result;
8767 if setflags then
8768 APSR.N = result<31>;
8769 APSR.Z = IsZeroBit(result);
8770 APSR.C = carry;
8771 APSR.V = overflow;
8772#endif
8773
8774 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008775
8776 uint32_t Rd; // the destination register
8777 uint32_t Rn; // the first operand
8778 uint32_t Rm; // the second operand
8779 bool setflags;
8780 ARM_ShifterType shift_t;
8781 uint32_t shift_n; // the shift applied to the value read from Rm
8782 switch (encoding) {
8783 case eEncodingT1:
8784 Rd = Rn = Bits32(opcode, 2, 0);
8785 Rm = Bits32(opcode, 5, 3);
8786 setflags = !InITBlock();
8787 shift_t = SRType_LSL;
8788 shift_n = 0;
8789 break;
8790 case eEncodingT2:
8791 Rd = Bits32(opcode, 11, 8);
8792 Rn = Bits32(opcode, 19, 16);
8793 Rm = Bits32(opcode, 3, 0);
8794 setflags = BitIsSet(opcode, 20);
8795 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8796 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8797 return false;
8798 break;
8799 case eEncodingA1:
8800 Rd = Bits32(opcode, 15, 12);
8801 Rn = Bits32(opcode, 19, 16);
8802 Rm = Bits32(opcode, 3, 0);
8803 setflags = BitIsSet(opcode, 20);
8804 shift_n = DecodeImmShiftARM(opcode, shift_t);
8805 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8806 // TODO: Emulate SUBS PC, LR and related instructions.
8807 if (Rd == 15 && setflags)
8808 return false;
8809 break;
8810 default:
8811 return false;
8812 }
8813 // Read the register value from register Rn.
8814 uint32_t val1 = ReadCoreReg(Rn, &success);
8815 if (!success)
8816 return false;
8817
8818 // Read the register value from register Rm.
8819 uint32_t val2 = ReadCoreReg(Rm, &success);
8820 if (!success)
8821 return false;
8822
8823 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8824 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8825
8826 EmulateInstruction::Context context;
8827 context.type = EmulateInstruction::eContextImmediate;
8828 context.SetNoArgs();
8829 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8830 return false;
8831
8832 return true;
8833}
8834
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008835// This instruction subtracts an immediate value from a register value, and writes the result
8836// to the destination register. It can optionally update the condition flags based on the result.
8837bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008838EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008839{
8840#if 0
8841 // ARM pseudo code...
8842 if ConditionPassed() then
8843 EncodingSpecificOperations();
8844 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8845 R[d] = result;
8846 if setflags then
8847 APSR.N = result<31>;
8848 APSR.Z = IsZeroBit(result);
8849 APSR.C = carry;
8850 APSR.V = overflow;
8851#endif
8852
8853 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008854
8855 uint32_t Rd; // the destination register
8856 uint32_t Rn; // the first operand
8857 bool setflags;
8858 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8859 switch (encoding) {
8860 case eEncodingT1:
8861 Rd = Bits32(opcode, 2, 0);
8862 Rn = Bits32(opcode, 5, 3);
8863 setflags = !InITBlock();
8864 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8865 break;
8866 case eEncodingT2:
8867 Rd = Rn = Bits32(opcode, 10, 8);
8868 setflags = !InITBlock();
8869 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8870 break;
8871 case eEncodingT3:
8872 Rd = Bits32(opcode, 11, 8);
8873 Rn = Bits32(opcode, 19, 16);
8874 setflags = BitIsSet(opcode, 20);
8875 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8876
8877 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8878 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008879 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008880
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008881 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008882 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008883 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008884
8885 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8886 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8887 return false;
8888 break;
8889 case eEncodingT4:
8890 Rd = Bits32(opcode, 11, 8);
8891 Rn = Bits32(opcode, 19, 16);
8892 setflags = BitIsSet(opcode, 20);
8893 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8894
8895 // if Rn == '1111' then SEE ADR;
8896 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008897 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008898
8899 // if Rn == '1101' then SEE SUB (SP minus immediate);
8900 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008901 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008902
8903 if (BadReg(Rd))
8904 return false;
8905 break;
8906 default:
8907 return false;
8908 }
8909 // Read the register value from the operand register Rn.
8910 uint32_t reg_val = ReadCoreReg(Rn, &success);
8911 if (!success)
8912 return false;
8913
8914 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8915
8916 EmulateInstruction::Context context;
8917 context.type = EmulateInstruction::eContextImmediate;
8918 context.SetNoArgs ();
8919
8920 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8921 return false;
8922
8923 return true;
8924}
8925
8926// This instruction subtracts an immediate value from a register value, and writes the result
8927// to the destination register. It can optionally update the condition flags based on the result.
8928bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008929EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008930{
8931#if 0
8932 // ARM pseudo code...
8933 if ConditionPassed() then
8934 EncodingSpecificOperations();
8935 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8936 if d == 15 then
8937 ALUWritePC(result); // setflags is always FALSE here
8938 else
8939 R[d] = result;
8940 if setflags then
8941 APSR.N = result<31>;
8942 APSR.Z = IsZeroBit(result);
8943 APSR.C = carry;
8944 APSR.V = overflow;
8945#endif
8946
8947 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008948
8949 uint32_t Rd; // the destination register
8950 uint32_t Rn; // the first operand
8951 bool setflags;
8952 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8953 switch (encoding) {
8954 case eEncodingA1:
8955 Rd = Bits32(opcode, 15, 12);
8956 Rn = Bits32(opcode, 19, 16);
8957 setflags = BitIsSet(opcode, 20);
8958 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8959
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008960 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008961 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008962 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008963
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008964 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008965 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008966 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008967
8968 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8969 // TODO: Emulate SUBS PC, LR and related instructions.
8970 if (Rd == 15 && setflags)
8971 return false;
8972 break;
8973 default:
8974 return false;
8975 }
8976 // Read the register value from the operand register Rn.
8977 uint32_t reg_val = ReadCoreReg(Rn, &success);
8978 if (!success)
8979 return false;
8980
8981 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8982
8983 EmulateInstruction::Context context;
8984 context.type = EmulateInstruction::eContextImmediate;
8985 context.SetNoArgs ();
8986
8987 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8988 return false;
8989
8990 return true;
8991}
8992
Johnny Chen2115b412011-02-21 23:42:44 +00008993// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8994// immediate value. It updates the condition flags based on the result, and discards the result.
8995bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008996EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008997{
8998#if 0
8999 // ARM pseudo code...
9000 if ConditionPassed() then
9001 EncodingSpecificOperations();
9002 result = R[n] EOR imm32;
9003 APSR.N = result<31>;
9004 APSR.Z = IsZeroBit(result);
9005 APSR.C = carry;
9006 // APSR.V unchanged
9007#endif
9008
9009 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009010
Greg Clayton7bc39082011-03-24 23:53:38 +00009011 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009012 {
9013 uint32_t Rn;
9014 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9015 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9016 switch (encoding)
9017 {
9018 case eEncodingT1:
9019 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009020 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009021 if (BadReg(Rn))
9022 return false;
9023 break;
9024 case eEncodingA1:
9025 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009026 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009027 break;
9028 default:
9029 return false;
9030 }
9031
9032 // Read the first operand.
9033 uint32_t val1 = ReadCoreReg(Rn, &success);
9034 if (!success)
9035 return false;
9036
9037 uint32_t result = val1 ^ imm32;
9038
9039 EmulateInstruction::Context context;
9040 context.type = EmulateInstruction::eContextImmediate;
9041 context.SetNoArgs ();
9042
9043 if (!WriteFlags(context, result, carry))
9044 return false;
9045 }
9046 return true;
9047}
9048
9049// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9050// optionally-shifted register value. It updates the condition flags based on the result, and discards
9051// the result.
9052bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009053EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009054{
9055#if 0
9056 // ARM pseudo code...
9057 if ConditionPassed() then
9058 EncodingSpecificOperations();
9059 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9060 result = R[n] EOR shifted;
9061 APSR.N = result<31>;
9062 APSR.Z = IsZeroBit(result);
9063 APSR.C = carry;
9064 // APSR.V unchanged
9065#endif
9066
9067 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009068
Greg Clayton7bc39082011-03-24 23:53:38 +00009069 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009070 {
9071 uint32_t Rn, Rm;
9072 ARM_ShifterType shift_t;
9073 uint32_t shift_n; // the shift applied to the value read from Rm
9074 uint32_t carry;
9075 switch (encoding)
9076 {
9077 case eEncodingT1:
9078 Rn = Bits32(opcode, 19, 16);
9079 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009080 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009081 if (BadReg(Rn) || BadReg(Rm))
9082 return false;
9083 break;
9084 case eEncodingA1:
9085 Rn = Bits32(opcode, 19, 16);
9086 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009087 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009088 break;
9089 default:
9090 return false;
9091 }
9092
9093 // Read the first operand.
9094 uint32_t val1 = ReadCoreReg(Rn, &success);
9095 if (!success)
9096 return false;
9097
9098 // Read the second operand.
9099 uint32_t val2 = ReadCoreReg(Rm, &success);
9100 if (!success)
9101 return false;
9102
9103 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9104 uint32_t result = val1 ^ shifted;
9105
9106 EmulateInstruction::Context context;
9107 context.type = EmulateInstruction::eContextImmediate;
9108 context.SetNoArgs ();
9109
9110 if (!WriteFlags(context, result, carry))
9111 return false;
9112 }
9113 return true;
9114}
9115
Johnny Chende3cce32011-02-21 21:24:49 +00009116// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9117// It updates the condition flags based on the result, and discards the result.
9118bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009119EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009120{
9121#if 0
9122 // ARM pseudo code...
9123 if ConditionPassed() then
9124 EncodingSpecificOperations();
9125 result = R[n] AND imm32;
9126 APSR.N = result<31>;
9127 APSR.Z = IsZeroBit(result);
9128 APSR.C = carry;
9129 // APSR.V unchanged
9130#endif
9131
9132 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009133
Greg Clayton7bc39082011-03-24 23:53:38 +00009134 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009135 {
9136 uint32_t Rn;
9137 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9138 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9139 switch (encoding)
9140 {
9141 case eEncodingT1:
9142 Rn = Bits32(opcode, 19, 16);
9143 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9144 if (BadReg(Rn))
9145 return false;
9146 break;
9147 case eEncodingA1:
9148 Rn = Bits32(opcode, 19, 16);
9149 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9150 break;
9151 default:
9152 return false;
9153 }
9154
9155 // Read the first operand.
9156 uint32_t val1 = ReadCoreReg(Rn, &success);
9157 if (!success)
9158 return false;
9159
9160 uint32_t result = val1 & imm32;
9161
9162 EmulateInstruction::Context context;
9163 context.type = EmulateInstruction::eContextImmediate;
9164 context.SetNoArgs ();
9165
9166 if (!WriteFlags(context, result, carry))
9167 return false;
9168 }
9169 return true;
9170}
9171
9172// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9173// It updates the condition flags based on the result, and discards the result.
9174bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009175EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009176{
9177#if 0
9178 // ARM pseudo code...
9179 if ConditionPassed() then
9180 EncodingSpecificOperations();
9181 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9182 result = R[n] AND shifted;
9183 APSR.N = result<31>;
9184 APSR.Z = IsZeroBit(result);
9185 APSR.C = carry;
9186 // APSR.V unchanged
9187#endif
9188
9189 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009190
Greg Clayton7bc39082011-03-24 23:53:38 +00009191 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009192 {
9193 uint32_t Rn, Rm;
9194 ARM_ShifterType shift_t;
9195 uint32_t shift_n; // the shift applied to the value read from Rm
9196 uint32_t carry;
9197 switch (encoding)
9198 {
9199 case eEncodingT1:
9200 Rn = Bits32(opcode, 2, 0);
9201 Rm = Bits32(opcode, 5, 3);
9202 shift_t = SRType_LSL;
9203 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009204 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009205 case eEncodingT2:
9206 Rn = Bits32(opcode, 19, 16);
9207 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009208 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009209 if (BadReg(Rn) || BadReg(Rm))
9210 return false;
9211 break;
9212 case eEncodingA1:
9213 Rn = Bits32(opcode, 19, 16);
9214 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009215 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009216 break;
9217 default:
9218 return false;
9219 }
9220
9221 // Read the first operand.
9222 uint32_t val1 = ReadCoreReg(Rn, &success);
9223 if (!success)
9224 return false;
9225
9226 // Read the second operand.
9227 uint32_t val2 = ReadCoreReg(Rm, &success);
9228 if (!success)
9229 return false;
9230
9231 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9232 uint32_t result = val1 & shifted;
9233
9234 EmulateInstruction::Context context;
9235 context.type = EmulateInstruction::eContextImmediate;
9236 context.SetNoArgs ();
9237
9238 if (!WriteFlags(context, result, carry))
9239 return false;
9240 }
9241 return true;
9242}
Caroline Ticed05b4902011-03-29 21:24:06 +00009243
9244// A8.6.216 SUB (SP minus register)
9245bool
9246EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9247{
9248#if 0
9249 if ConditionPassed() then
9250 EncodingSpecificOperations();
9251 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9252 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9253 if d == 15 then // Can only occur for ARM encoding
9254 ALUWritePC(result); // setflags is always FALSE here
9255 else
9256 R[d] = result;
9257 if setflags then
9258 APSR.N = result<31>;
9259 APSR.Z = IsZeroBit(result);
9260 APSR.C = carry;
9261 APSR.V = overflow;
9262#endif
9263
9264 bool success = false;
9265
9266 if (ConditionPassed(opcode))
9267 {
9268 uint32_t d;
9269 uint32_t m;
9270 bool setflags;
9271 ARM_ShifterType shift_t;
9272 uint32_t shift_n;
9273
9274 switch (encoding)
9275 {
9276 case eEncodingT1:
9277 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9278 d = Bits32 (opcode, 11, 8);
9279 m = Bits32 (opcode, 3, 0);
9280 setflags = BitIsSet (opcode, 20);
9281
9282 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9283 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9284
9285 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9286 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9287 return false;
9288
9289 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9290 if ((d == 15) || BadReg (m))
9291 return false;
9292 break;
9293
9294 case eEncodingA1:
9295 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9296 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9297 d = Bits32 (opcode, 15, 12);
9298 m = Bits32 (opcode, 3, 0);
9299 setflags = BitIsSet (opcode, 20);
9300
9301 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9302 shift_n = DecodeImmShiftARM (opcode, shift_t);
9303 break;
9304
9305 default:
9306 return false;
9307 }
9308
9309 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9310 uint32_t Rm = ReadCoreReg (m, &success);
9311 if (!success)
9312 return false;
9313
9314 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9315
9316 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9317 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9318 if (!success)
9319 return false;
9320
9321 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9322
9323 EmulateInstruction::Context context;
9324 context.type = eContextSubtraction;
9325 Register sp_reg;
9326 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9327 Register dwarf_reg;
9328 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9329 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9330
Caroline Ticeef440002011-03-30 05:40:56 +00009331 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009332 return false;
9333 }
9334 return true;
9335}
9336
9337
9338// A8.6.7 ADD (register-shifted register)
9339bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009340EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009341{
9342#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009343 if ConditionPassed() then
9344 EncodingSpecificOperations();
9345 shift_n = UInt(R[s]<7:0>);
9346 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9347 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9348 R[d] = result;
9349 if setflags then
9350 APSR.N = result<31>;
9351 APSR.Z = IsZeroBit(result);
9352 APSR.C = carry;
9353 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009354#endif
9355
Caroline Ticec08ed382011-03-29 23:03:16 +00009356 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009357
9358 if (ConditionPassed(opcode))
9359 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009360 uint32_t d;
9361 uint32_t n;
9362 uint32_t m;
9363 uint32_t s;
9364 bool setflags;
9365 ARM_ShifterType shift_t;
9366
Caroline Ticed05b4902011-03-29 21:24:06 +00009367 switch (encoding)
9368 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009369 case eEncodingA1:
9370 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9371 d = Bits32 (opcode, 15, 12);
9372 n = Bits32 (opcode, 19, 16);
9373 m = Bits32 (opcode, 3, 0);
9374 s = Bits32 (opcode, 11, 8);
9375
9376 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9377 setflags = BitIsSet (opcode, 20);
9378 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9379
9380 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9381 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9382 return false;
9383 break;
9384
9385 default:
9386 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009387 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009388
9389 // shift_n = UInt(R[s]<7:0>);
9390 uint32_t Rs = ReadCoreReg (s, &success);
9391 if (!success)
9392 return false;
9393
9394 uint32_t shift_n = Bits32 (Rs, 7, 0);
9395
9396 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9397 uint32_t Rm = ReadCoreReg (m, &success);
9398 if (!success)
9399 return false;
9400
9401 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9402
9403 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9404 uint32_t Rn = ReadCoreReg (n, &success);
9405 if (!success)
9406 return false;
9407
9408 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9409
9410 // R[d] = result;
9411 EmulateInstruction::Context context;
9412 context.type = eContextAddition;
9413 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009414 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009415 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009416 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009417
9418 context.SetRegisterRegisterOperands (reg_n, reg_m);
9419
9420 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9421 return false;
9422
9423 // if setflags then
9424 // APSR.N = result<31>;
9425 // APSR.Z = IsZeroBit(result);
9426 // APSR.C = carry;
9427 // APSR.V = overflow;
9428 if (setflags)
9429 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009430 }
9431 return true;
9432}
9433
9434// A8.6.213 SUB (register)
9435bool
9436EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9437{
9438#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009439 if ConditionPassed() then
9440 EncodingSpecificOperations();
9441 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9442 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9443 if d == 15 then // Can only occur for ARM encoding
9444 ALUWritePC(result); // setflags is always FALSE here
9445 else
9446 R[d] = result;
9447 if setflags then
9448 APSR.N = result<31>;
9449 APSR.Z = IsZeroBit(result);
9450 APSR.C = carry;
9451 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009452#endif
9453
Caroline Tice4cccd532011-03-29 23:44:20 +00009454 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009455
9456 if (ConditionPassed(opcode))
9457 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009458 uint32_t d;
9459 uint32_t n;
9460 uint32_t m;
9461 bool setflags;
9462 ARM_ShifterType shift_t;
9463 uint32_t shift_n;
9464
Caroline Ticed05b4902011-03-29 21:24:06 +00009465 switch (encoding)
9466 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009467 case eEncodingT1:
9468 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9469 d = Bits32 (opcode, 2, 0);
9470 n = Bits32 (opcode, 5, 3);
9471 m = Bits32 (opcode, 8, 6);
9472 setflags = !InITBlock();
9473
9474 // (shift_t, shift_n) = (SRType_LSL, 0);
9475 shift_t = SRType_LSL;
9476 shift_n = 0;
9477
9478 break;
9479
9480 case eEncodingT2:
9481 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9482 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9483 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9484 d = Bits32 (opcode, 11, 8);
9485 n = Bits32 (opcode, 19, 16);
9486 m = Bits32 (opcode, 3, 0);
9487 setflags = BitIsSet (opcode, 20);
9488
9489 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9490 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9491
9492 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9493 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9494 return false;
9495
9496 break;
9497
9498 case eEncodingA1:
9499 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9500 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9501 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9502 d = Bits32 (opcode, 15, 12);
9503 n = Bits32 (opcode, 19, 16);
9504 m = Bits32 (opcode, 3, 0);
9505 setflags = BitIsSet (opcode, 20);
9506
9507 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9508 shift_n = DecodeImmShiftARM (opcode, shift_t);
9509
9510 break;
9511
9512 default:
9513 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009514 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009515
9516 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9517 uint32_t Rm = ReadCoreReg (m, &success);
9518 if (!success)
9519 return false;
9520
9521 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9522
9523 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9524 uint32_t Rn = ReadCoreReg (n, &success);
9525 if (!success)
9526 return false;
9527
9528 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9529
9530 // if d == 15 then // Can only occur for ARM encoding
9531 // ALUWritePC(result); // setflags is always FALSE here
9532 // else
9533 // R[d] = result;
9534 // if setflags then
9535 // APSR.N = result<31>;
9536 // APSR.Z = IsZeroBit(result);
9537 // APSR.C = carry;
9538 // APSR.V = overflow;
9539
9540 EmulateInstruction::Context context;
9541 context.type = eContextSubtraction;
9542 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009543 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009544 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009545 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009546 context.SetRegisterRegisterOperands (reg_n, reg_m);
9547
Caroline Ticeef440002011-03-30 05:40:56 +00009548 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009549 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009550 }
9551 return true;
9552}
Caroline Tice4cccd532011-03-29 23:44:20 +00009553
Caroline Ticed05b4902011-03-29 21:24:06 +00009554// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009555// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9556// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009557bool
9558EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9559{
9560#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009561 if ConditionPassed() then
9562 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9563 address = R[n] + imm32;
9564 if ExclusiveMonitorsPass(address,4) then
9565 MemA[address,4] = R[t];
9566 R[d] = 0;
9567 else
9568 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009569#endif
9570
Caroline Tice5168b6c2011-03-30 05:15:46 +00009571 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009572
9573 if (ConditionPassed(opcode))
9574 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009575 uint32_t d;
9576 uint32_t t;
9577 uint32_t n;
9578 uint32_t imm32;
9579 const uint32_t addr_byte_size = GetAddressByteSize();
9580
Caroline Ticed05b4902011-03-29 21:24:06 +00009581 switch (encoding)
9582 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009583 case eEncodingT1:
9584 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9585 d = Bits32 (opcode, 11, 8);
9586 t = Bits32 (opcode, 15, 12);
9587 n = Bits32 (opcode, 19, 16);
9588 imm32 = Bits32 (opcode, 7, 0) << 2;
9589
9590 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9591 if (BadReg (d) || BadReg (t) || (n == 15))
9592 return false;
9593
9594 // if d == n || d == t then UNPREDICTABLE;
9595 if ((d == n) || (d == t))
9596 return false;
9597
9598 break;
9599
9600 case eEncodingA1:
9601 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9602 d = Bits32 (opcode, 15, 12);
9603 t = Bits32 (opcode, 3, 0);
9604 n = Bits32 (opcode, 19, 16);
9605 imm32 = 0;
9606
9607 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9608 if ((d == 15) || (t == 15) || (n == 15))
9609 return false;
9610
9611 // if d == n || d == t then UNPREDICTABLE;
9612 if ((d == n) || (d == t))
9613 return false;
9614
9615 break;
9616
9617 default:
9618 return false;
9619 }
9620
9621 // address = R[n] + imm32;
9622 uint32_t Rn = ReadCoreReg (n, &success);
9623 if (!success)
9624 return false;
9625
9626 addr_t address = Rn + imm32;
9627
9628 Register base_reg;
9629 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9630 Register data_reg;
9631 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9632 EmulateInstruction::Context context;
9633 context.type = eContextRegisterStore;
9634 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9635
9636 // if ExclusiveMonitorsPass(address,4) then
9637 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9638 // always return true.
9639 if (true)
9640 {
9641 // MemA[address,4] = R[t];
9642 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9643 if (!success)
9644 return false;
9645
9646 if (!MemAWrite (context, address, Rt, addr_byte_size))
9647 return false;
9648
9649 // R[d] = 0;
9650 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9651 return false;
9652 }
9653 else
9654 {
9655 // R[d] = 1;
9656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9657 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009658 }
9659 }
9660 return true;
9661}
9662
9663// A8.6.197 STRB (immediate, ARM)
9664bool
9665EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9666{
9667#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009668 if ConditionPassed() then
9669 EncodingSpecificOperations();
9670 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9671 address = if index then offset_addr else R[n];
9672 MemU[address,1] = R[t]<7:0>;
9673 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009674#endif
9675
Caroline Ticeef440002011-03-30 05:40:56 +00009676 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009677
9678 if (ConditionPassed(opcode))
9679 {
Caroline Ticeef440002011-03-30 05:40:56 +00009680 uint32_t t;
9681 uint32_t n;
9682 uint32_t imm32;
9683 bool index;
9684 bool add;
9685 bool wback;
9686
Caroline Ticed05b4902011-03-29 21:24:06 +00009687 switch (encoding)
9688 {
Caroline Ticeef440002011-03-30 05:40:56 +00009689 case eEncodingA1:
9690 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9691 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9692 t = Bits32 (opcode, 15, 12);
9693 n = Bits32 (opcode, 19, 16);
9694 imm32 = Bits32 (opcode, 11, 0);
9695
9696 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9697 index = BitIsSet (opcode, 24);
9698 add = BitIsSet (opcode, 23);
9699 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9700
9701 // if t == 15 then UNPREDICTABLE;
9702 if (t == 15)
9703 return false;
9704
9705 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9706 if (wback && ((n == 15) || (n == t)))
9707 return false;
9708
9709 break;
9710
9711 default:
9712 return false;
9713 }
9714
9715 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9716 uint32_t Rn = ReadCoreReg (n, &success);
9717 if (!success)
9718 return false;
9719
9720 addr_t offset_addr;
9721 if (add)
9722 offset_addr = Rn + imm32;
9723 else
9724 offset_addr = Rn - imm32;
9725
9726 // address = if index then offset_addr else R[n];
9727 addr_t address;
9728 if (index)
9729 address = offset_addr;
9730 else
9731 address = Rn;
9732
9733 // MemU[address,1] = R[t]<7:0>;
9734 uint32_t Rt = ReadCoreReg (t, &success);
9735 if (!success)
9736 return false;
9737
9738 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009739 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009740 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009741 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009742 EmulateInstruction::Context context;
9743 context.type = eContextRegisterStore;
9744 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9745
9746 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9747 return false;
9748
9749 // if wback then R[n] = offset_addr;
9750 if (wback)
9751 {
9752 if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9753 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009754 }
9755 }
9756 return true;
9757}
9758
9759// A8.6.194 STR (immediate, ARM)
9760bool
9761EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9762{
9763#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009764 if ConditionPassed() then
9765 EncodingSpecificOperations();
9766 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9767 address = if index then offset_addr else R[n];
9768 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9769 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009770#endif
9771
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009772 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009773
9774 if (ConditionPassed(opcode))
9775 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009776 uint32_t t;
9777 uint32_t n;
9778 uint32_t imm32;
9779 bool index;
9780 bool add;
9781 bool wback;
9782
9783 const uint32_t addr_byte_size = GetAddressByteSize();
9784
Caroline Ticed05b4902011-03-29 21:24:06 +00009785 switch (encoding)
9786 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009787 case eEncodingA1:
9788 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9789 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9790 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9791 t = Bits32 (opcode, 15, 12);
9792 n = Bits32 (opcode, 19, 16);
9793 imm32 = Bits32 (opcode, 11, 0);
9794
9795 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9796 index = BitIsSet (opcode, 24);
9797 add = BitIsSet (opcode, 23);
9798 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9799
9800 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9801 if (wback && ((n == 15) || (n == t)))
9802 return false;
9803
9804 break;
9805
9806 default:
9807 return false;
9808 }
9809
9810 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9811 uint32_t Rn = ReadCoreReg (n, &success);
9812 if (!success)
9813 return false;
9814
9815 addr_t offset_addr;
9816 if (add)
9817 offset_addr = Rn + imm32;
9818 else
9819 offset_addr = Rn - imm32;
9820
9821 // address = if index then offset_addr else R[n];
9822 addr_t address;
9823 if (index)
9824 address = offset_addr;
9825 else
9826 address = Rn;
9827
9828 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009829 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009830 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009831 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009832 EmulateInstruction::Context context;
9833 context.type = eContextRegisterStore;
9834 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9835
9836 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9837 uint32_t Rt = ReadCoreReg (t, &success);
9838 if (!success)
9839 return false;
9840
9841 if (t == 15)
9842 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009843 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009844 if (!success)
9845 return false;
9846
9847 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9848 return false;
9849 }
9850 else
9851 {
9852 if (!MemUWrite (context, address, Rt, addr_byte_size))
9853 return false;
9854 }
9855
9856 // if wback then R[n] = offset_addr;
9857 if (wback)
9858 {
9859 context.type = eContextAdjustBaseRegister;
9860 context.SetImmediate (offset_addr);
9861
9862 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9863 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009864 }
9865 }
9866 return true;
9867}
9868
Caroline Ticed05b4902011-03-29 21:24:06 +00009869// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009870// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9871// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +00009872bool
9873EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9874{
9875#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009876 if ConditionPassed() then
9877 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9878 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9879 address = if index then offset_addr else R[n];
9880 R[t] = MemA[address,4];
9881 R[t2] = MemA[address+4,4];
9882 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009883#endif
9884
Caroline Tice1697dd72011-03-30 17:11:45 +00009885 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009886
9887 if (ConditionPassed(opcode))
9888 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009889 uint32_t t;
9890 uint32_t t2;
9891 uint32_t n;
9892 uint32_t imm32;
9893 bool index;
9894 bool add;
9895 bool wback;
9896
Caroline Ticed05b4902011-03-29 21:24:06 +00009897 switch (encoding)
9898 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009899 case eEncodingT1:
9900 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9901 //if Rn == ‘1111’ then SEE LDRD (literal);
9902 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9903 t = Bits32 (opcode, 15, 12);
9904 t2 = Bits32 (opcode, 11, 8);
9905 n = Bits32 (opcode, 19, 16);
9906 imm32 = Bits32 (opcode, 7, 0) << 2;
9907
9908 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9909 index = BitIsSet (opcode, 24);
9910 add = BitIsSet (opcode, 23);
9911 wback = BitIsSet (opcode, 21);
9912
9913 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9914 if (wback && ((n == t) || (n == t2)))
9915 return false;
9916
9917 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9918 if (BadReg (t) || BadReg (t2) || (t == t2))
9919 return false;
9920
9921 break;
9922
9923 case eEncodingA1:
9924 //if Rn == ‘1111’ then SEE LDRD (literal);
9925 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9926 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9927 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009928 if (BitIsSet (t, 0))
9929 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009930 t2 = t + 1;
9931 n = Bits32 (opcode, 19, 16);
9932 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9933
9934 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9935 index = BitIsSet (opcode, 24);
9936 add = BitIsSet (opcode, 23);
9937 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9938
9939 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9940 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9941 return false;
9942
9943 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9944 if (wback && ((n == t) || (n == t2)))
9945 return false;
9946
9947 //if t2 == 15 then UNPREDICTABLE;
9948 if (t2 == 15)
9949 return false;
9950
9951 break;
9952
9953 default:
9954 return false;
9955 }
9956
9957 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9958 uint32_t Rn = ReadCoreReg (n, &success);
9959 if (!success)
9960 return false;
9961
9962 addr_t offset_addr;
9963 if (add)
9964 offset_addr = Rn + imm32;
9965 else
9966 offset_addr = Rn - imm32;
9967
9968 //address = if index then offset_addr else R[n];
9969 addr_t address;
9970 if (index)
9971 address = offset_addr;
9972 else
9973 address = Rn;
9974
9975 //R[t] = MemA[address,4];
9976 Register base_reg;
9977 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9978
9979 EmulateInstruction::Context context;
9980 context.type = eContextRegisterLoad;
9981 context.SetRegisterPlusOffset (base_reg, address - Rn);
9982
9983 const uint32_t addr_byte_size = GetAddressByteSize();
9984 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
9985 if (!success)
9986 return false;
9987
9988 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
9989 return false;
9990
9991 //R[t2] = MemA[address+4,4];
9992
9993 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
9994 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
9995 if (!success)
9996 return false;
9997
9998 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
9999 return false;
10000
10001 //if wback then R[n] = offset_addr;
10002 if (wback)
10003 {
10004 context.type = eContextAdjustBaseRegister;
10005 context.SetAddress (offset_addr);
10006
10007 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10008 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010009 }
10010 }
10011 return true;
10012}
10013
Caroline Ticed05b4902011-03-29 21:24:06 +000010014// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010015// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10016// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +000010017bool
10018EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10019{
10020#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010021 if ConditionPassed() then
10022 EncodingSpecificOperations();
10023 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10024 address = if index then offset_addr else R[n];
10025 R[t] = MemA[address,4];
10026 R[t2] = MemA[address+4,4];
10027 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010028#endif
10029
Caroline Ticeeab301f2011-03-30 17:54:52 +000010030 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010031
10032 if (ConditionPassed(opcode))
10033 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010034 uint32_t t;
10035 uint32_t t2;
10036 uint32_t n;
10037 uint32_t m;
10038 bool index;
10039 bool add;
10040 bool wback;
10041
Caroline Ticed05b4902011-03-29 21:24:06 +000010042 switch (encoding)
10043 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010044 case eEncodingA1:
10045 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10046 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10047 t = Bits32 (opcode, 15, 12);
10048 if (BitIsSet (t, 0))
10049 return false;
10050 t2 = t + 1;
10051 n = Bits32 (opcode, 19, 16);
10052 m = Bits32 (opcode, 3, 0);
10053
10054 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10055 index = BitIsSet (opcode, 24);
10056 add = BitIsSet (opcode, 23);
10057 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10058
10059 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10060 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10061 return false;
10062
10063 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10064 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10065 return false;
10066
10067 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10068 if (wback && ((n == 15) || (n == t) || (n == t2)))
10069 return false;
10070
10071 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10072 if ((ArchVersion() < 6) && wback && (m == n))
10073 return false;
10074 break;
10075
10076 default:
10077 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010078 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010079
Caroline Ticeeab301f2011-03-30 17:54:52 +000010080 uint32_t Rn = ReadCoreReg (n, &success);
10081 if (!success)
10082 return false;
10083 Register base_reg;
10084 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed05b4902011-03-29 21:24:06 +000010085
Caroline Ticeeab301f2011-03-30 17:54:52 +000010086 uint32_t Rm = ReadCoreReg (m, &success);
10087 if (!success)
10088 return false;
10089 Register offset_reg;
10090 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticed05b4902011-03-29 21:24:06 +000010091
Caroline Ticeeab301f2011-03-30 17:54:52 +000010092 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10093 addr_t offset_addr;
10094 if (add)
10095 offset_addr = Rn + Rm;
10096 else
10097 offset_addr = Rn - Rm;
10098
10099 // address = if index then offset_addr else R[n];
10100 addr_t address;
10101 if (index)
10102 address = offset_addr;
10103 else
10104 address = Rn;
10105
10106 EmulateInstruction::Context context;
10107 context.type = eContextRegisterLoad;
10108 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10109
10110 // R[t] = MemA[address,4];
10111 const uint32_t addr_byte_size = GetAddressByteSize();
10112 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10113 if (!success)
10114 return false;
10115
10116 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10117 return false;
10118
10119 // R[t2] = MemA[address+4,4];
10120
10121 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10122 if (!success)
10123 return false;
10124
10125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10126 return false;
10127
10128 // if wback then R[n] = offset_addr;
10129 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010130 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010131 context.type = eContextAdjustBaseRegister;
10132 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010133
Caroline Ticeeab301f2011-03-30 17:54:52 +000010134 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10135 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010136 }
10137 }
10138 return true;
10139}
Caroline Ticed05b4902011-03-29 21:24:06 +000010140
10141// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010142// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10143// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +000010144bool
10145EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10146{
10147#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010148 if ConditionPassed() then
10149 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10150 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10151 address = if index then offset_addr else R[n];
10152 MemA[address,4] = R[t];
10153 MemA[address+4,4] = R[t2];
10154 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010155#endif
10156
Caroline Tice74467fe2011-03-30 19:02:56 +000010157 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010158
Caroline Tice74467fe2011-03-30 19:02:56 +000010159 if (ConditionPassed(opcode))
10160 {
10161 uint32_t t;
10162 uint32_t t2;
10163 uint32_t n;
10164 uint32_t imm32;
10165 bool index;
10166 bool add;
10167 bool wback;
10168
10169 switch (encoding)
10170 {
10171 case eEncodingT1:
10172 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10173 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10174 t = Bits32 (opcode, 15, 12);
10175 t2 = Bits32 (opcode, 11, 8);
10176 n = Bits32 (opcode, 19, 16);
10177 imm32 = Bits32 (opcode, 7, 0) << 2;
10178
10179 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10180 index = BitIsSet (opcode, 24);
10181 add = BitIsSet (opcode, 23);
10182 wback = BitIsSet (opcode, 21);
10183
10184 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10185 if (wback && ((n == t) || (n == t2)))
10186 return false;
10187
10188 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10189 if ((n == 15) || BadReg (t) || BadReg (t2))
10190 return false;
10191
10192 break;
10193
10194 case eEncodingA1:
10195 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10196 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10197 t = Bits32 (opcode, 15, 12);
10198 if (BitIsSet (t, 0))
10199 return false;
10200
10201 t2 = t + 1;
10202 n = Bits32 (opcode, 19, 16);
10203 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10204
10205 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10206 index = BitIsSet (opcode, 24);
10207 add = BitIsSet (opcode, 23);
10208 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10209
10210 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10211 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10212 return false;
10213
10214 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10215 if (wback && ((n == 15) || (n == t) || (n == t2)))
10216 return false;
10217
10218 // if t2 == 15 then UNPREDICTABLE;
10219 if (t2 == 15)
10220 return false;
10221
10222 break;
10223
10224 default:
10225 return false;
10226 }
10227
10228 Register base_reg;
10229 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10230
10231 uint32_t Rn = ReadCoreReg (n, &success);
10232 if (!success)
10233 return false;
10234
10235 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10236 addr_t offset_addr;
10237 if (add)
10238 offset_addr = Rn + imm32;
10239 else
10240 offset_addr = Rn - imm32;
10241
10242 //address = if index then offset_addr else R[n];
10243 addr_t address;
10244 if (index)
10245 address = offset_addr;
10246 else
10247 address = Rn;
10248
10249 //MemA[address,4] = R[t];
10250 Register data_reg;
10251 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10252
10253 uint32_t data = ReadCoreReg (t, &success);
10254 if (!success)
10255 return false;
10256
10257 EmulateInstruction::Context context;
10258 context.type = eContextRegisterStore;
10259 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10260
10261 const uint32_t addr_byte_size = GetAddressByteSize();
10262
10263 if (!MemAWrite (context, address, data, addr_byte_size))
10264 return false;
10265
10266 //MemA[address+4,4] = R[t2];
10267 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2);
10268 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10269
10270 data = ReadCoreReg (t2, &success);
10271 if (!success)
10272 return false;
10273
10274 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10275 return false;
10276
10277 //if wback then R[n] = offset_addr;
10278 if (wback)
10279 {
10280 context.type = eContextAdjustBaseRegister;
10281 context.SetAddress (offset_addr);
10282
10283 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10284 return false;
10285 }
10286 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010287 return true;
10288}
10289
10290
10291// A8.6.201 STRD (register)
10292bool
10293EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10294{
10295#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010296 if ConditionPassed() then
10297 EncodingSpecificOperations();
10298 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10299 address = if index then offset_addr else R[n];
10300 MemA[address,4] = R[t];
10301 MemA[address+4,4] = R[t2];
10302 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010303#endif
10304
Caroline Tice74467fe2011-03-30 19:02:56 +000010305 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010306
Caroline Tice74467fe2011-03-30 19:02:56 +000010307 if (ConditionPassed(opcode))
10308 {
10309 uint32_t t;
10310 uint32_t t2;
10311 uint32_t n;
10312 uint32_t m;
10313 bool index;
10314 bool add;
10315 bool wback;
10316
10317 switch (encoding)
10318 {
10319 case eEncodingA1:
10320 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10321 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10322 t = Bits32 (opcode, 15, 12);
10323 if (BitIsSet (t, 0))
10324 return false;
10325
10326 t2 = t+1;
10327 n = Bits32 (opcode, 19, 16);
10328 m = Bits32 (opcode, 3, 0);
10329
10330 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10331 index = BitIsSet (opcode, 24);
10332 add = BitIsSet (opcode, 23);
10333 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10334
10335 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10336 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10337 return false;
10338
10339 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10340 if ((t2 == 15) || (m == 15))
10341 return false;
10342
10343 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10344 if (wback && ((n == 15) || (n == t) || (n == t2)))
10345 return false;
10346
10347 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010348 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010349 return false;
10350
10351 break;
10352
10353 default:
10354 return false;
10355 }
10356
10357 Register base_reg;
10358 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10359 Register offset_reg;
10360 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10361 Register data_reg;
10362 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10363
10364 uint32_t Rn = ReadCoreReg (n, &success);
10365 if (!success)
10366 return false;
10367
10368 uint32_t Rm = ReadCoreReg (m, &success);
10369 if (!success)
10370 return false;
10371
10372 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10373 addr_t offset_addr;
10374 if (add)
10375 offset_addr = Rn + Rm;
10376 else
10377 offset_addr = Rn - Rm;
10378
10379 // address = if index then offset_addr else R[n];
10380 addr_t address;
10381 if (index)
10382 address = offset_addr;
10383 else
10384 address = Rn;
10385 // MemA[address,4] = R[t];
10386 uint32_t Rt = ReadCoreReg (t, &success);
10387 if (!success)
10388 return false;
10389
10390 EmulateInstruction::Context context;
10391 context.type = eContextRegisterStore;
10392 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10393
10394 const uint32_t addr_byte_size = GetAddressByteSize();
10395
10396 if (!MemAWrite (context, address, Rt, addr_byte_size))
10397 return false;
10398
10399 // MemA[address+4,4] = R[t2];
10400 uint32_t Rt2 = ReadCoreReg (t2, &success);
10401 if (!success)
10402 return false;
10403
10404 data_reg.num = dwarf_r0 + t2;
10405
10406 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10407
10408 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10409 return false;
10410
10411 // if wback then R[n] = offset_addr;
10412 if (wback)
10413 {
10414 context.type = eContextAdjustBaseRegister;
10415 context.SetAddress (offset_addr);
10416
10417 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10418 return false;
10419
10420 }
10421 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010422 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010423}
10424
Caroline Tice4f605582011-03-31 00:02:51 +000010425// A8.6.319 VLDM
10426// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10427// an ARM core register.
10428bool
10429EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10430{
10431#if 0
10432 if ConditionPassed() then
10433 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10434 address = if add then R[n] else R[n]-imm32;
10435 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10436 for r = 0 to regs-1
10437 if single_regs then
10438 S[d+r] = MemA[address,4]; address = address+4;
10439 else
10440 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10441 // Combine the word-aligned words in the correct order for current endianness.
10442 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10443#endif
10444
10445 bool success = false;
10446
10447 if (ConditionPassed(opcode))
10448 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010449 bool single_regs;
10450 bool add;
10451 bool wback;
10452 uint32_t d;
10453 uint32_t n;
10454 uint32_t imm32;
10455 uint32_t regs;
10456
Caroline Tice4f605582011-03-31 00:02:51 +000010457 switch (encoding)
10458 {
10459 case eEncodingT1:
10460 case eEncodingA1:
10461 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10462 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10463 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10464 // if P == U && W == ‘1’ then UNDEFINED;
10465 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10466 return false;
10467
10468 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10469 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10470 single_regs = false;
10471 add = BitIsSet (opcode, 23);
10472 wback = BitIsSet (opcode, 21);
10473
10474 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10475 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10476 n = Bits32 (opcode, 19, 16);
10477 imm32 = Bits32 (opcode, 7, 0) << 2;
10478
10479 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10480 regs = Bits32 (opcode, 7, 0) / 2;
10481
10482 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10483 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10484 return false;
10485
10486 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10487 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10488 return false;
10489
10490 break;
10491
10492 case eEncodingT2:
10493 case eEncodingA2:
10494 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10495 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10496 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10497 // if P == U && W == ‘1’ then UNDEFINED;
10498 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10499 return false;
10500
10501 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10502 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10503 single_regs = true;
10504 add = BitIsSet (opcode, 23);
10505 wback = BitIsSet (opcode, 21);
10506 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10507 n = Bits32 (opcode, 19, 16);
10508
10509 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10510 imm32 = Bits32 (opcode, 7, 0) << 2;
10511 regs = Bits32 (opcode, 7, 0);
10512
10513 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10514 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10515 return false;
10516
10517 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10518 if ((regs == 0) || ((d + regs) > 32))
10519 return false;
10520 break;
10521
10522 default:
10523 return false;
10524 }
10525
10526 Register base_reg;
10527 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10528
10529 uint32_t Rn = ReadCoreReg (n, &success);
10530 if (!success)
10531 return false;
10532
10533 // address = if add then R[n] else R[n]-imm32;
10534 addr_t address;
10535 if (add)
10536 address = Rn;
10537 else
10538 address = Rn - imm32;
10539
10540 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10541 EmulateInstruction::Context context;
10542
10543 if (wback)
10544 {
10545 uint32_t value;
10546 if (add)
10547 value = Rn + imm32;
10548 else
10549 value = Rn - imm32;
10550
10551 context.type = eContextAdjustBaseRegister;
10552 context.SetImmediateSigned (value - Rn);
10553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10554 return false;
10555
10556 }
10557
10558 const uint32_t addr_byte_size = GetAddressByteSize();
10559 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10560
10561 context.type = eContextRegisterLoad;
10562
10563 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010564 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010565 {
10566 if (single_regs)
10567 {
10568 // S[d+r] = MemA[address,4]; address = address+4;
10569 context.SetRegisterPlusOffset (base_reg, address - Rn);
10570
10571 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10572 if (!success)
10573 return false;
10574
10575 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10576 return false;
10577
10578 address = address + 4;
10579 }
10580 else
10581 {
10582 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10583 context.SetRegisterPlusOffset (base_reg, address - Rn);
10584 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10585 if (!success)
10586 return false;
10587
10588 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10589 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10590 if (!success)
10591 return false;
10592
10593 address = address + 8;
10594 // // Combine the word-aligned words in the correct order for current endianness.
10595 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10596 uint64_t data;
10597 if (m_byte_order == eByteOrderBig)
10598 {
10599 data = word1;
10600 data = (data << 32) | word2;
10601 }
10602 else
10603 {
10604 data = word2;
10605 data = (data << 32) | word1;
10606 }
10607
10608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10609 return false;
10610 }
10611 }
10612 }
10613 return true;
10614}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010615
10616// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010617// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10618// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010619bool
10620EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10621{
10622#if 0
10623 if ConditionPassed() then
10624 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10625 address = if add then R[n] else R[n]-imm32;
10626 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10627 for r = 0 to regs-1
10628 if single_regs then
10629 MemA[address,4] = S[d+r]; address = address+4;
10630 else
10631 // Store as two word-aligned words in the correct order for current endianness.
10632 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10633 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10634 address = address+8;
10635#endif
10636
10637 bool success = false;
10638
10639 if (ConditionPassed (opcode))
10640 {
10641 bool single_regs;
10642 bool add;
10643 bool wback;
10644 uint32_t d;
10645 uint32_t n;
10646 uint32_t imm32;
10647 uint32_t regs;
10648
10649 switch (encoding)
10650 {
10651 case eEncodingT1:
10652 case eEncodingA1:
10653 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10654 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10655 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10656 // if P == U && W == ‘1’ then UNDEFINED;
10657 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10658 return false;
10659
10660 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10661 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10662 single_regs = false;
10663 add = BitIsSet (opcode, 23);
10664 wback = BitIsSet (opcode, 21);
10665
10666 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10667 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10668 n = Bits32 (opcode, 19, 16);
10669 imm32 = Bits32 (opcode, 7, 0) << 2;
10670
10671 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”.
10672 regs = Bits32 (opcode, 7, 0) / 2;
10673
10674 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10675 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10676 return false;
10677
10678 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10679 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10680 return false;
10681
10682 break;
10683
10684 case eEncodingT2:
10685 case eEncodingA2:
10686 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10687 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10688 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10689 // if P == U && W == ‘1’ then UNDEFINED;
10690 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10691 return false;
10692
10693 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10694 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10695 single_regs = true;
10696 add = BitIsSet (opcode, 23);
10697 wback = BitIsSet (opcode, 21);
10698 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10699 n = Bits32 (opcode, 19, 16);
10700
10701 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10702 imm32 = Bits32 (opcode, 7, 0) << 2;
10703 regs = Bits32 (opcode, 7, 0);
10704
10705 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10706 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10707 return false;
10708
10709 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10710 if ((regs == 0) || ((d + regs) > 32))
10711 return false;
10712
10713 break;
10714
10715 default:
10716 return false;
10717 }
10718
10719 Register base_reg;
10720 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10721
10722 uint32_t Rn = ReadCoreReg (n, &success);
10723 if (!success)
10724 return false;
10725
10726 // address = if add then R[n] else R[n]-imm32;
10727 addr_t address;
10728 if (add)
10729 address = Rn;
10730 else
10731 address = Rn - imm32;
10732
10733 EmulateInstruction::Context context;
10734 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10735 if (wback)
10736 {
10737 uint32_t value;
10738 if (add)
10739 value = Rn + imm32;
10740 else
10741 value = Rn - imm32;
10742
10743 context.type = eContextAdjustBaseRegister;
10744 context.SetRegisterPlusOffset (base_reg, value - Rn);
10745
10746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10747 return false;
10748 }
10749
10750 const uint32_t addr_byte_size = GetAddressByteSize();
10751 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10752
10753 context.type = eContextRegisterStore;
10754 // for r = 0 to regs-1
10755 for (int r = 0; r < regs; ++r)
10756 {
10757 Register data_reg;
10758 data_reg.SetRegister (eRegisterKindDWARF, 0);
10759 if (single_regs)
10760 {
10761 // MemA[address,4] = S[d+r]; address = address+4;
10762 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10763 if (!success)
10764 return false;
10765
10766 data_reg.num = start_reg + d + r;
10767 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10768 if (!MemAWrite (context, address, data, addr_byte_size))
10769 return false;
10770
10771 address = address + 4;
10772 }
10773 else
10774 {
10775 // // Store as two word-aligned words in the correct order for current endianness.
10776 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10777 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10778 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10779 if (!success)
10780 return false;
10781
10782 data_reg.num = start_reg + d + r;
10783
10784 if (m_byte_order == eByteOrderBig)
10785 {
10786 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10787 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10788 return false;
10789
10790 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10791 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10792 return false;
10793 }
10794 else
10795 {
10796 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10797 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10798 return false;
10799
10800 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10801 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10802 return false;
10803 }
10804 // address = address+8;
10805 address = address + 8;
10806 }
10807 }
10808 }
10809 return true;
10810}
10811
Caroline Tice917ad352011-03-31 05:05:30 +000010812// A8.6.320
10813// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10814// an optional offset.
10815bool
10816EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10817{
10818#if 0
10819 if ConditionPassed() then
10820 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10821 base = if n == 15 then Align(PC,4) else R[n];
10822 address = if add then (base + imm32) else (base - imm32);
10823 if single_reg then
10824 S[d] = MemA[address,4];
10825 else
10826 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10827 // Combine the word-aligned words in the correct order for current endianness.
10828 D[d] = if BigEndian() then word1:word2 else word2:word1;
10829#endif
10830
10831 bool success = false;
10832
10833 if (ConditionPassed (opcode))
10834 {
10835 bool single_reg;
10836 bool add;
10837 uint32_t imm32;
10838 uint32_t d;
10839 uint32_t n;
10840
10841 switch (encoding)
10842 {
10843 case eEncodingT1:
10844 case eEncodingA1:
10845 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10846 single_reg = false;
10847 add = BitIsSet (opcode, 23);
10848 imm32 = Bits32 (opcode, 7, 0) << 2;
10849
10850 // d = UInt(D:Vd); n = UInt(Rn);
10851 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10852 n = Bits32 (opcode, 19, 16);
10853
10854 break;
10855
10856 case eEncodingT2:
10857 case eEncodingA2:
10858 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10859 single_reg = true;
10860 add = BitIsSet (opcode, 23);
10861 imm32 = Bits32 (opcode, 7, 0) << 2;
10862
10863 // d = UInt(Vd:D); n = UInt(Rn);
10864 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10865 n = Bits32 (opcode, 19, 16);
10866
10867 break;
10868
10869 default:
10870 return false;
10871 }
10872 Register base_reg;
10873 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10874
10875 uint32_t Rn = ReadCoreReg (n, &success);
10876 if (!success)
10877 return false;
10878
10879 // base = if n == 15 then Align(PC,4) else R[n];
10880 uint32_t base;
10881 if (n == 15)
10882 base = AlignPC (Rn);
10883 else
10884 base = Rn;
10885
10886 // address = if add then (base + imm32) else (base - imm32);
10887 addr_t address;
10888 if (add)
10889 address = base + imm32;
10890 else
10891 address = base - imm32;
10892
10893 const uint32_t addr_byte_size = GetAddressByteSize();
10894 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10895
10896 EmulateInstruction::Context context;
10897 context.type = eContextRegisterLoad;
10898 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010899
Caroline Tice917ad352011-03-31 05:05:30 +000010900 if (single_reg)
10901 {
10902 // S[d] = MemA[address,4];
10903 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10904 if (!success)
10905 return false;
10906
10907 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10908 return false;
10909 }
10910 else
10911 {
10912 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10913 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10914 if (!success)
10915 return false;
10916
10917 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10918 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10919 if (!success)
10920 return false;
10921 // // Combine the word-aligned words in the correct order for current endianness.
10922 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10923 uint64_t data64;
10924 if (m_byte_order == eByteOrderBig)
10925 {
10926 data64 = word1;
10927 data64 = (data64 << 32) | word2;
10928 }
10929 else
10930 {
10931 data64 = word2;
10932 data64 = (data64 << 32) | word1;
10933 }
10934
10935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10936 return false;
10937 }
10938 }
10939 return true;
10940}
Caroline Tice424652f2011-03-31 05:38:36 +000010941
10942// A8.6.400 VSTR
10943// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10944// optional offset.
10945bool
10946EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10947{
10948#if 0
10949 if ConditionPassed() then
10950 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10951 address = if add then (R[n] + imm32) else (R[n] - imm32);
10952 if single_reg then
10953 MemA[address,4] = S[d];
10954 else
10955 // Store as two word-aligned words in the correct order for current endianness.
10956 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10957 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10958#endif
10959
10960 bool success = false;
10961
10962 if (ConditionPassed (opcode))
10963 {
10964 bool single_reg;
10965 bool add;
10966 uint32_t imm32;
10967 uint32_t d;
10968 uint32_t n;
10969
10970 switch (encoding)
10971 {
10972 case eEncodingT1:
10973 case eEncodingA1:
10974 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10975 single_reg = false;
10976 add = BitIsSet (opcode, 23);
10977 imm32 = Bits32 (opcode, 7, 0) << 2;
10978
10979 // d = UInt(D:Vd); n = UInt(Rn);
10980 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10981 n = Bits32 (opcode, 19, 16);
10982
10983 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
10984 if ((n == 15) && (CurrentInstrSet() != eModeARM))
10985 return false;
10986
10987 break;
10988
10989 case eEncodingT2:
10990 case eEncodingA2:
10991 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10992 single_reg = true;
10993 add = BitIsSet (opcode, 23);
10994 imm32 = Bits32 (opcode, 7, 0) << 2;
10995
10996 // d = UInt(Vd:D); n = UInt(Rn);
10997 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10998 n = Bits32 (opcode, 19, 16);
10999
11000 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11001 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11002 return false;
11003
11004 break;
11005
11006 default:
11007 return false;
11008 }
11009
11010 Register base_reg;
11011 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11012
11013 uint32_t Rn = ReadCoreReg (n, &success);
11014 if (!success)
11015 return false;
11016
11017 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11018 addr_t address;
11019 if (add)
11020 address = Rn + imm32;
11021 else
11022 address = Rn - imm32;
11023
11024 const uint32_t addr_byte_size = GetAddressByteSize();
11025 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11026
11027 Register data_reg;
11028 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d);
11029 EmulateInstruction::Context context;
11030 context.type = eContextRegisterStore;
11031 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11032
11033 if (single_reg)
11034 {
11035 // MemA[address,4] = S[d];
11036 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11037 if (!success)
11038 return false;
11039
11040 if (!MemAWrite (context, address, data, addr_byte_size))
11041 return false;
11042 }
11043 else
11044 {
11045 // // Store as two word-aligned words in the correct order for current endianness.
11046 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11047 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11048 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11049 if (!success)
11050 return false;
11051
11052 if (m_byte_order == eByteOrderBig)
11053 {
11054 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11055 return false;
11056
11057 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11058 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11059 return false;
11060 }
11061 else
11062 {
11063 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11064 return false;
11065
11066 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11067 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11068 return false;
11069 }
11070 }
11071 }
11072 return true;
11073}
Caroline Tice9121b352011-03-31 16:41:19 +000011074
11075// A8.6.307 VLDI1 (multiple single elements)
11076// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11077// element of each register is loaded.
11078bool
11079EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11080{
11081#if 0
11082 if ConditionPassed() then
11083 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11084 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11085 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11086 for r = 0 to regs-1
11087 for e = 0 to elements-1
11088 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11089 address = address + ebytes;
11090#endif
11091
11092 bool success = false;
11093
11094 if (ConditionPassed (opcode))
11095 {
11096 uint32_t regs;
11097 uint32_t alignment;
11098 uint32_t ebytes;
11099 uint32_t esize;
11100 uint32_t elements;
11101 uint32_t d;
11102 uint32_t n;
11103 uint32_t m;
11104 bool wback;
11105 bool register_index;
11106
11107 switch (encoding)
11108 {
11109 case eEncodingT1:
11110 case eEncodingA1:
11111 {
11112 // case type of
11113 // when ‘0111’
11114 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11115 // when ‘1010’
11116 // regs = 2; if align == ‘11’ then UNDEFINED;
11117 // when ‘0110’
11118 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11119 // when ‘0010’
11120 // regs = 4;
11121 // otherwise
11122 // SEE “Related encodings”;
11123 uint32_t type = Bits32 (opcode, 11, 8);
11124 uint32_t align = Bits32 (opcode, 5, 4);
11125 if (type == 7) // '0111'
11126 {
11127 regs = 1;
11128 if (BitIsSet (align, 1))
11129 return false;
11130 }
11131 else if (type == 10) // '1010'
11132 {
11133 regs = 2;
11134 if (align == 3)
11135 return false;
11136
11137 }
11138 else if (type == 6) // '0110'
11139 {
11140 regs = 3;
11141 if (BitIsSet (align, 1))
11142 return false;
11143 }
11144 else if (type == 2) // '0010'
11145 {
11146 regs = 4;
11147 }
11148 else
11149 return false;
11150
11151 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11152 if (align == 0)
11153 alignment = 1;
11154 else
11155 alignment = 4 << align;
11156
11157 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11158 ebytes = 1 << Bits32 (opcode, 7, 6);
11159 esize = 8 * ebytes;
11160 elements = 8 / ebytes;
11161
11162 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11163 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11164 n = Bits32 (opcode, 19, 15);
11165 m = Bits32 (opcode, 3, 0);
11166
11167 // wback = (m != 15); register_index = (m != 15 && m != 13);
11168 wback = (m != 15);
11169 register_index = ((m != 15) && (m != 13));
11170
11171 // if d+regs > 32 then UNPREDICTABLE;
11172 if ((d + regs) > 32)
11173 return false;
11174 }
11175 break;
11176
11177 default:
11178 return false;
11179 }
11180
11181 Register base_reg;
11182 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11183
11184 uint32_t Rn = ReadCoreReg (n, &success);
11185 if (!success)
11186 return false;
11187
11188 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11189 addr_t address = Rn;
11190 if ((address % alignment) != 0)
11191 return false;
11192
11193 EmulateInstruction::Context context;
11194 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11195 if (wback)
11196 {
11197 uint32_t Rm = ReadCoreReg (m, &success);
11198 if (!success)
11199 return false;
11200
11201 uint32_t offset;
11202 if (register_index)
11203 offset = Rm;
11204 else
11205 offset = 8 * regs;
11206
11207 uint32_t value = Rn + offset;
11208 context.type = eContextAdjustBaseRegister;
11209 context.SetRegisterPlusOffset (base_reg, offset);
11210
11211 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11212 return false;
11213
11214 }
11215
11216 // for r = 0 to regs-1
11217 for (int r = 0; r < regs; ++r)
11218 {
11219 // for e = 0 to elements-1
11220 uint64_t assembled_data = 0;
11221 for (int e = 0; e < elements; ++e)
11222 {
11223 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11224 context.type = eContextRegisterLoad;
11225 context.SetRegisterPlusOffset (base_reg, address - Rn);
11226 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11227 if (!success)
11228 return false;
11229
11230 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11231
11232 // address = address + ebytes;
11233 address = address + ebytes;
11234 }
11235 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11236 return false;
11237 }
11238 }
11239 return true;
11240}
11241
Caroline Ticeb6281b12011-03-31 17:58:23 +000011242// A8.6.308 VLD1 (single element to one lane)
11243//
11244bool
11245EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11246{
11247#if 0
11248 if ConditionPassed() then
11249 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11250 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11251 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11252 Elem[D[d],index,esize] = MemU[address,ebytes];
11253#endif
11254
11255 bool success = false;
11256
11257 if (ConditionPassed (opcode))
11258 {
11259 uint32_t ebytes;
11260 uint32_t esize;
11261 uint32_t index;
11262 uint32_t alignment;
11263 uint32_t d;
11264 uint32_t n;
11265 uint32_t m;
11266 bool wback;
11267 bool register_index;
11268
11269 switch (encoding)
11270 {
11271 case eEncodingT1:
11272 case eEncodingA1:
11273 {
11274 uint32_t size = Bits32 (opcode, 11, 10);
11275 uint32_t index_align = Bits32 (opcode, 7, 4);
11276 // if size == ‘11’ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011277 if (size == 3)
11278 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011279 // case size of
11280 if (size == 0) // when '00'
11281 {
11282 // if index_align<0> != ‘0’ then UNDEFINED;
11283 if (BitIsClear (index_align, 0))
11284 return false;
11285
11286 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11287 ebytes = 1;
11288 esize = 8;
11289 index = Bits32 (index_align, 3, 1);
11290 alignment = 1;
11291 }
11292 else if (size == 1) // when ‘01’
11293 {
11294 // if index_align<1> != ‘0’ then UNDEFINED;
11295 if (BitIsClear (index_align, 1))
11296 return false;
11297
11298 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11299 ebytes = 2;
11300 esize = 16;
11301 index = Bits32 (index_align, 3, 2);
11302
11303 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11304 if (BitIsClear (index_align, 0))
11305 alignment = 1;
11306 else
11307 alignment = 2;
11308 }
11309 else if (size == 2) // when ‘10’
11310 {
11311 // if index_align<2> != ‘0’ then UNDEFINED;
11312 if (BitIsClear (index_align, 2))
11313 return false;
11314
11315 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11316 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11317 return false;
11318
11319 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11320 ebytes = 4;
11321 esize = 32;
11322 index = Bit32 (index_align, 3);
11323
11324 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11325 if (Bits32 (index_align, 1, 0) == 0)
11326 alignment = 1;
11327 else
11328 alignment = 4;
11329 }
11330 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11331 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11332 n = Bits32 (opcode, 19, 16);
11333 m = Bits32 (opcode, 3, 0);
11334
11335 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11336 wback = (m != 15);
11337 register_index = ((m != 15) && (m != 13));
11338
11339 if (n == 15)
11340 return false;
11341
11342 }
11343 break;
11344
11345 default:
11346 return false;
11347 }
11348
11349 Register base_reg;
11350 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11351
11352 uint32_t Rn = ReadCoreReg (n, &success);
11353 if (!success)
11354 return false;
11355
11356 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11357 addr_t address = Rn;
11358 if ((address % alignment) != 0)
11359 return false;
11360
11361 EmulateInstruction::Context context;
11362 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11363 if (wback)
11364 {
11365 uint32_t Rm = ReadCoreReg (m, &success);
11366 if (!success)
11367 return false;
11368
11369 uint32_t offset;
11370 if (register_index)
11371 offset = Rm;
11372 else
11373 offset = ebytes;
11374
11375 uint32_t value = Rn + offset;
11376
11377 context.type = eContextAdjustBaseRegister;
11378 context.SetRegisterPlusOffset (base_reg, offset);
11379
11380 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11381 return false;
11382 }
11383
11384 // Elem[D[d],index,esize] = MemU[address,ebytes];
11385 uint32_t element = MemURead (context, address, esize, 0, &success);
11386 if (!success)
11387 return false;
11388
11389 element = element << (index * esize);
11390
11391 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11392 if (!success)
11393 return false;
11394
11395 uint64_t all_ones = -1;
11396 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11397 // at element & to the right of element.
11398 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011399 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes.
Caroline Ticeb6281b12011-03-31 17:58:23 +000011400 // now mask should be 0's where element goes & 1's
11401 // everywhere else.
11402
11403 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11404 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11405
11406 context.type = eContextRegisterLoad;
11407 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11408 return false;
11409 }
11410 return true;
11411}
11412
Caroline Tice1e542e32011-03-31 18:44:04 +000011413// A8.6.391 VST1 (multiple single elements)
11414// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11415// interleaving. Every element of each register is stored.
11416bool
11417EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11418{
11419#if 0
11420 if ConditionPassed() then
11421 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11422 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11423 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11424 for r = 0 to regs-1
11425 for e = 0 to elements-1
11426 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11427 address = address + ebytes;
11428#endif
11429
11430 bool success = false;
11431
11432 if (ConditionPassed (opcode))
11433 {
11434 uint32_t regs;
11435 uint32_t alignment;
11436 uint32_t ebytes;
11437 uint32_t esize;
11438 uint32_t elements;
11439 uint32_t d;
11440 uint32_t n;
11441 uint32_t m;
11442 bool wback;
11443 bool register_index;
11444
11445 switch (encoding)
11446 {
11447 case eEncodingT1:
11448 case eEncodingA1:
11449 {
11450 uint32_t type = Bits32 (opcode, 11, 8);
11451 uint32_t align = Bits32 (opcode, 5, 4);
11452
11453 // case type of
11454 if (type == 7) // when ‘0111’
11455 {
11456 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11457 regs = 1;
11458 if (BitIsSet (align, 1))
11459 return false;
11460 }
11461 else if (type == 10) // when ‘1010’
11462 {
11463 // regs = 2; if align == ‘11’ then UNDEFINED;
11464 regs = 2;
11465 if (align == 3)
11466 return false;
11467 }
11468 else if (type == 6) // when ‘0110’
11469 {
11470 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11471 regs = 3;
11472 if (BitIsSet (align, 1))
11473 return false;
11474 }
11475 else if (type == 2) // when ‘0010’
11476 // regs = 4;
11477 regs = 4;
11478 else // otherwise
11479 // SEE “Related encodings”;
11480 return false;
11481
11482 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11483 if (align == 0)
11484 alignment = 0;
11485 else
11486 alignment = 4 << align;
11487
11488 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11489 ebytes = 1 << Bits32 (opcode,7, 6);
11490 esize = 8 * ebytes;
11491 elements = 8 / ebytes;
11492
11493 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11494 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11495 n = Bits32 (opcode, 19, 16);
11496 m = Bits32 (opcode, 3, 0);
11497
11498 // wback = (m != 15); register_index = (m != 15 && m != 13);
11499 wback = (m != 15);
11500 register_index = ((m != 15) && (m != 13));
11501
11502 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11503 if ((d + regs) > 32)
11504 return false;
11505
11506 if (n == 15)
11507 return false;
11508
11509 }
11510 break;
11511
11512 default:
11513 return false;
11514 }
11515
11516 Register base_reg;
11517 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11518
11519 uint32_t Rn = ReadCoreReg (n, &success);
11520 if (!success)
11521 return false;
11522
11523 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11524 addr_t address = Rn;
11525 if ((address % alignment) != 0)
11526 return false;
11527
11528 EmulateInstruction::Context context;
11529 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11530 if (wback)
11531 {
11532 uint32_t Rm = ReadCoreReg (m, &success);
11533 if (!success)
11534 return false;
11535
11536 uint32_t offset;
11537 if (register_index)
11538 offset = Rm;
11539 else
11540 offset = 8 * regs;
11541
11542 context.type = eContextAdjustBaseRegister;
11543 context.SetRegisterPlusOffset (base_reg, offset);
11544
11545 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11546 return false;
11547 }
11548
11549 context.type = eContextRegisterStore;
11550 Register data_reg;
11551 data_reg.SetRegister (eRegisterKindDWARF, 0);
11552 // for r = 0 to regs-1
11553 for (int r = 0; r < regs; ++r)
11554 {
11555 data_reg.num = dwarf_d0 + d + r;
11556 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11557 if (!success)
11558 return false;
11559
11560 // for e = 0 to elements-1
11561 for (int e = 0; e < elements; ++e)
11562 {
11563 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011564 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011565
11566 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11567 if (!MemUWrite (context, address, word, ebytes))
11568 return false;
11569
11570 // address = address + ebytes;
11571 address = address + ebytes;
11572 }
11573 }
11574 }
11575 return true;
11576}
11577
Caroline Tice7b880942011-03-31 19:17:12 +000011578// A8.6.392 VST1 (single element from one lane)
11579// This instruction stores one element to memory from one element of a register.
11580bool
11581EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11582{
11583#if 0
11584 if ConditionPassed() then
11585 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11586 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11587 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11588 MemU[address,ebytes] = Elem[D[d],index,esize];
11589#endif
11590
11591 bool success = false;
11592
11593 if (ConditionPassed (opcode))
11594 {
11595 uint32_t ebytes;
11596 uint32_t esize;
11597 uint32_t index;
11598 uint32_t alignment;
11599 uint32_t d;
11600 uint32_t n;
11601 uint32_t m;
11602 bool wback;
11603 bool register_index;
11604
11605 switch (encoding)
11606 {
11607 case eEncodingT1:
11608 case eEncodingA1:
11609 {
11610 uint32_t size = Bits32 (opcode, 11, 10);
11611 uint32_t index_align = Bits32 (opcode, 7, 4);
11612
11613 // if size == ‘11’ then UNDEFINED;
11614 if (size == 3)
11615 return false;
11616
11617 // case size of
11618 if (size == 0) // when ‘00’
11619 {
11620 // if index_align<0> != ‘0’ then UNDEFINED;
11621 if (BitIsClear (index_align, 0))
11622 return false;
11623 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11624 ebytes = 1;
11625 esize = 8;
11626 index = Bits32 (index_align, 3, 1);
11627 alignment = 1;
11628 }
11629 else if (size == 1) // when ‘01’
11630 {
11631 // if index_align<1> != ‘0’ then UNDEFINED;
11632 if (BitIsClear (index_align, 1))
11633 return false;
11634
11635 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11636 ebytes = 2;
11637 esize = 16;
11638 index = Bits32 (index_align, 3, 2);
11639
11640 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11641 if (BitIsClear (index_align, 0))
11642 alignment = 1;
11643 else
11644 alignment = 2;
11645 }
11646 else if (size == 2) // when ‘10’
11647 {
11648 // if index_align<2> != ‘0’ then UNDEFINED;
11649 if (BitIsClear (index_align, 2))
11650 return false;
11651
11652 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11653 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11654 return false;
11655
11656 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11657 ebytes = 4;
11658 esize = 32;
11659 index = Bit32 (index_align, 3);
11660
11661 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11662 if (Bits32 (index_align, 1, 0) == 0)
11663 alignment = 1;
11664 else
11665 alignment = 4;
11666 }
11667 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11668 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11669 n = Bits32 (opcode, 19, 16);
11670 m = Bits32 (opcode, 3, 0);
11671
11672 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11673 wback = (m != 15);
11674 register_index = ((m != 15) && (m != 13));
11675
11676 if (n == 15)
11677 return false;
11678 }
11679 break;
11680
11681 default:
11682 return false;
11683 }
11684
11685 Register base_reg;
11686 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11687
11688 uint32_t Rn = ReadCoreReg (n, &success);
11689 if (!success)
11690 return false;
11691
11692 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11693 addr_t address = Rn;
11694 if ((address % alignment) != 0)
11695 return false;
11696
11697 EmulateInstruction::Context context;
11698 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11699 if (wback)
11700 {
11701 uint32_t Rm = ReadCoreReg (m, &success);
11702 if (!success)
11703 return false;
11704
11705 uint32_t offset;
11706 if (register_index)
11707 offset = Rm;
11708 else
11709 offset = ebytes;
11710
11711 context.type = eContextAdjustBaseRegister;
11712 context.SetRegisterPlusOffset (base_reg, offset);
11713
11714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11715 return false;
11716 }
11717
11718 // MemU[address,ebytes] = Elem[D[d],index,esize];
11719 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11720 if (!success)
11721 return false;
11722
11723 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11724
11725 Register data_reg;
11726 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d);
11727 context.type = eContextRegisterStore;
11728 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11729
11730 if (!MemUWrite (context, address, word, ebytes))
11731 return false;
11732 }
11733 return true;
11734}
11735
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011736// A8.6.309 VLD1 (single element to all lanes)
11737// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011738bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011739EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011740{
11741#if 0
11742 if ConditionPassed() then
11743 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11744 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11745 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11746 replicated_element = Replicate(MemU[address,ebytes], elements);
11747 for r = 0 to regs-1
11748 D[d+r] = replicated_element;
11749#endif
11750
11751 bool success = false;
11752
11753 if (ConditionPassed (opcode))
11754 {
11755 uint32_t ebytes;
11756 uint32_t elements;
11757 uint32_t regs;
11758 uint32_t alignment;
11759 uint32_t d;
11760 uint32_t n;
11761 uint32_t m;
11762 bool wback;
11763 bool register_index;
11764
11765 switch (encoding)
11766 {
11767 case eEncodingT1:
11768 case eEncodingA1:
11769 {
11770 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED;
11771 uint32_t size = Bits32 (opcode, 7, 6);
11772 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11773 return false;
11774
11775 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2;
11776 ebytes = 1 << size;
11777 elements = 8 / ebytes;
11778 if (BitIsClear (opcode, 5))
11779 regs = 1;
11780 else
11781 regs = 2;
11782
11783 //alignment = if a == ‘0’ then 1 else ebytes;
11784 if (BitIsClear (opcode, 4))
11785 alignment = 1;
11786 else
11787 alignment = ebytes;
11788
11789 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11790 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11791 n = Bits32 (opcode, 19, 16);
11792 m = Bits32 (opcode, 3, 0);
11793
11794 //wback = (m != 15); register_index = (m != 15 && m != 13);
11795 wback = (m != 15);
11796 register_index = ((m != 15) && (m != 13));
11797
11798 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11799 if ((d + regs) > 32)
11800 return false;
11801
11802 if (n == 15)
11803 return false;
11804 }
11805 break;
11806
11807 default:
11808 break;
11809 }
11810
11811 Register base_reg;
11812 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
11813
11814 uint32_t Rn = ReadCoreReg (n, &success);
11815 if (!success)
11816 return false;
11817
11818 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11819 addr_t address = Rn;
11820 if ((address % alignment) != 0)
11821 return false;
11822
11823 EmulateInstruction::Context context;
11824 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11825 if (wback)
11826 {
11827 uint32_t Rm = ReadCoreReg (m, &success);
11828 if (!success)
11829 return false;
11830
11831 uint32_t offset;
11832 if (register_index)
11833 offset = Rm;
11834 else
11835 offset = ebytes;
11836
11837 context.type = eContextAdjustBaseRegister;
11838 context.SetRegisterPlusOffset (base_reg, offset);
11839
11840 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11841 return false;
11842 }
11843
11844 // replicated_element = Replicate(MemU[address,ebytes], elements);
11845
11846 context.type = eContextRegisterLoad;
11847 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11848 if (!success)
11849 return false;
11850
11851 uint64_t replicated_element;
11852 uint32_t esize = ebytes * 8;
11853 for (int e = 0; e < elements; ++e)
11854 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11855
11856 // for r = 0 to regs-1
11857 for (int r = 0; r < regs; ++r)
11858 {
11859 // D[d+r] = replicated_element;
11860 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11861 return false;
11862 }
11863 }
11864 return true;
11865}
11866
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011867EmulateInstructionARM::ARMOpcode*
11868EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000011869{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011870 static ARMOpcode
11871 g_arm_opcodes[] =
11872 {
11873 //----------------------------------------------------------------------
11874 // Prologue instructions
11875 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000011876
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011877 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000011878 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
11879 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000011880
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011881 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000011882 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
11883 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000011884 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000011885 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
11886 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
11887 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000011888
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011889 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000011890 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
11891 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000011892
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011893 // push one register
11894 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000011895 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000011896
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011897 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000011898 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
11899 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000011900
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011901 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000011902 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011903 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000011904
Caroline Tice4f605582011-03-31 00:02:51 +000011905 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
11906 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
11907 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
11908 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000011909
11910 //----------------------------------------------------------------------
11911 // Supervisor Call (previously Software Interrupt)
11912 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000011913 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000011914
11915 //----------------------------------------------------------------------
11916 // Branch instructions
11917 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000011918 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000011919 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000011920 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
11921 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
11922 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000011923 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000011924 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000011925 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000011926 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000011927
Caroline Ticeb9f76c32011-02-08 22:24:38 +000011928 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000011929 // Data-processing instructions
11930 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000011931 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011932 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000011933 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011934 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000011935 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011936 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000011937 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011938 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000011939 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000011940 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000011941 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000011942 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
11943 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000011944 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011945 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000011946 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011947 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000011948 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011949 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000011950 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011951 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000011952 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011953 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000011954 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011955 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000011956 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011957 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000011958 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011959 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000011960 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011961 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000011962 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011963 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000011964 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011965 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000011966 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011967 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000011968 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011969 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000011970 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011971 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000011972 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000011973 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000011974 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011975 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000011976 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011977 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000011978 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011979 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000011980 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011981 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000011982 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011983 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000011984 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011985 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000011986
Caroline Tice89c6d582011-03-29 19:53:44 +000011987 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011988 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
11989 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000011990 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011991 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000011992 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011993 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000011994 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011995 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000011996 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000011997 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000011998 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000011999 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012000 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012001 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012002 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012003 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012004 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012005 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012006 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012007 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012008 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012009 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012010 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012011 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012012 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012013 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012014 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012015 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012016 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012017 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012018 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012019 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012020 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012021 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012022 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012023 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +000012024
12025 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012026 // Load instructions
12027 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012028 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12029 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12030 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12031 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12032 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12033 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12034 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12035 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12036 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12037 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12038 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12039 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12040 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12041 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12042 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12043 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12044 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12045 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012046 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12047 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12048 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12049 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012050 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12051 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012052 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012053
12054 //----------------------------------------------------------------------
12055 // Store instructions
12056 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012057 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12058 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12059 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12060 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12061 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12062 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12063 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12064 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12065 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012066 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012067 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012068 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12069 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12070 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12071 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12072 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012073 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012074
Caroline Tice6bf65162011-03-03 17:42:58 +000012075 //----------------------------------------------------------------------
12076 // Other instructions
12077 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012078 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12079 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12080 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12081 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12082 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012083
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012084 };
12085 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12086
12087 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12088 {
12089 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
12090 return &g_arm_opcodes[i];
12091 }
12092 return NULL;
12093}
Greg Clayton64c84432011-01-21 22:02:52 +000012094
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012095
12096EmulateInstructionARM::ARMOpcode*
12097EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +000012098{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012099
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012100 static ARMOpcode
12101 g_thumb_opcodes[] =
12102 {
12103 //----------------------------------------------------------------------
12104 // Prologue instructions
12105 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012106
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012107 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012108 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12109 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12110 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012111
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012112 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012113 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012114 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012115 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012116 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012117 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012118
Johnny Chen864a8e82011-02-18 00:07:39 +000012119 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012120 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012121
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012122 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012123 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12124 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12125 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12126 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12127 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012128
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012129 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012130 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12131 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012132
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012133 //----------------------------------------------------------------------
12134 // Epilogue instructions
12135 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012136
Caroline Tice4f605582011-03-31 00:02:51 +000012137 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12138 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12139 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12140 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12141 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12142 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12143 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012144
12145 //----------------------------------------------------------------------
12146 // Supervisor Call (previously Software Interrupt)
12147 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012148 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012149
12150 //----------------------------------------------------------------------
12151 // If Then makes up to four following instructions conditional.
12152 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012153 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012154
12155 //----------------------------------------------------------------------
12156 // Branch instructions
12157 //----------------------------------------------------------------------
12158 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012159 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12160 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12161 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12162 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +000012163 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012164 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012165 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012166 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12167 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012168 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012169 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012170 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012171 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012172 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012173 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012174 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012175 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012176 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012177 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012178
12179 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012180 // Data-processing instructions
12181 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012182 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012183 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012184 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012185 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12186 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen157b9592011-02-18 21:13:05 +000012187 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012188 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012189 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012191 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012192 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12193 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12194 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012195 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012196 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012197 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12199 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012200 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012201 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012202 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012203 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12204 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012205 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012206 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012207 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012208 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12209 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012210 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012211 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012212 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012213 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12214 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012215 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12217 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012218 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012219 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012220 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012221 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012222 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012223 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12224 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +000012225 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012226 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12227 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12228 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12229 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012230 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012231 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12232 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12233 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12234 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012235 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12237 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012238 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012239 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12240 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012241 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012242 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012243 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012244 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012245 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012246 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012247 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012248 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12249 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012250
Johnny Chen7c5234d2011-02-18 23:41:11 +000012251
Johnny Chen338bf542011-02-10 19:29:03 +000012252 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012253 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012254 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012255 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012256 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012257 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012258 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012259 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12260 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12261 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012262 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012263 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012264 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012265 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12266 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012267 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012268 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012269 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012270 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12271 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012272 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012273 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12274 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012275 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012276 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012277 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012278 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012279 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012280 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12281 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012282 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012283 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12284 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012285 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012286 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12287 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012288 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012289 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12290 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012291 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012292 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12293 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012294 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012295 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12296 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012297 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012298 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012299 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012300 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012301 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012302 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12303 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012304 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012305 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012306 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012307 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012308
12309
12310 //----------------------------------------------------------------------
12311 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12312 // otherwise the wrong instructions will be selected.
12313 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012314
Caroline Tice080bf612011-04-05 18:46:00 +000012315 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12316 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12317
Johnny Chen26863dc2011-02-09 23:43:29 +000012318 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012319 // Load instructions
12320 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012321 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12322 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12323 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12324 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12325 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12326 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12327 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012328 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012329 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12330 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12331 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12332 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12333 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012334 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012335 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12336 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12337 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12338 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12339 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12340 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12341 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12342 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12343 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12344 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12345 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12346 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12347 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12348 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12349 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12350 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12351 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12352 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12353 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012354 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012355 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12356 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12357 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12358 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012359 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12360 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012361 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012362
12363 //----------------------------------------------------------------------
12364 // Store instructions
12365 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012366 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12367 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12368 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12369 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12370 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12371 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12372 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12373 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12374 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12375 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12376 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12377 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12378 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12379 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12380 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12381 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012382 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12383 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12384 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12385 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12386 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012387 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012388
12389 //----------------------------------------------------------------------
12390 // Other instructions
12391 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012392 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12393 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12394 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12395 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12396 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12397 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12398 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12399 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012400 };
12401
12402 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12403 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12404 {
12405 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
12406 return &g_thumb_opcodes[i];
12407 }
12408 return NULL;
12409}
Greg Clayton64c84432011-01-21 22:02:52 +000012410
Greg Clayton31e2a382011-01-30 20:03:56 +000012411bool
Greg Clayton395fc332011-02-15 21:59:32 +000012412EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012413{
Caroline Tice080bf612011-04-05 18:46:00 +000012414 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012415 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012416 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012417 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012418 {
Greg Clayton395fc332011-02-15 21:59:32 +000012419 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12420 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12421 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12422 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12423 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12424 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12425 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12426 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12427 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12428 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000012429 }
12430 return m_arm_isa != 0;
12431}
12432
Caroline Tice080bf612011-04-05 18:46:00 +000012433bool
12434EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr)
12435{
12436 m_opcode = insn_opcode;
12437
12438 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12439 m_opcode_mode = eModeThumb;
12440 else
12441 {
12442 AddressClass addr_class = inst_addr.GetAddressClass();
12443
12444 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12445 m_opcode_mode = eModeARM;
12446 else if (addr_class == eAddressClassCodeAlternateISA)
12447 m_opcode_mode = eModeThumb;
12448 else
12449 return false;
12450 }
12451 return true;
12452}
Greg Clayton31e2a382011-01-30 20:03:56 +000012453
Greg Clayton64c84432011-01-21 22:02:52 +000012454bool
12455EmulateInstructionARM::ReadInstruction ()
12456{
12457 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012458 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012459 if (success)
12460 {
12461 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12462 if (success)
12463 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012464 Context read_inst_context;
12465 read_inst_context.type = eContextReadOpcode;
12466 read_inst_context.SetNoArgs ();
12467
Greg Claytonb3448432011-03-24 21:19:54 +000012468 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012469 {
Greg Claytonb3448432011-03-24 21:19:54 +000012470 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012471 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012472
12473 if (success)
12474 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012475 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012476 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012477 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012478 }
12479 else
12480 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012481 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012482 }
12483 }
12484 }
12485 else
12486 {
Greg Claytonb3448432011-03-24 21:19:54 +000012487 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012488 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012489 }
12490 }
12491 }
12492 if (!success)
12493 {
Greg Claytonb3448432011-03-24 21:19:54 +000012494 m_opcode_mode = eModeInvalid;
12495 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012496 }
12497 return success;
12498}
12499
Johnny Chenee9b1f72011-02-09 01:00:31 +000012500uint32_t
12501EmulateInstructionARM::ArchVersion ()
12502{
12503 return m_arm_isa;
12504}
12505
Greg Clayton64c84432011-01-21 22:02:52 +000012506bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012507EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012508{
Greg Clayton64c84432011-01-21 22:02:52 +000012509
Greg Clayton7bc39082011-03-24 23:53:38 +000012510 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012511
12512 if (cond == UINT32_MAX)
12513 return false;
12514
12515 bool result = false;
12516 switch (UnsignedBits(cond, 3, 1))
12517 {
Caroline Tice080bf612011-04-05 18:46:00 +000012518 case 0:
12519 if (m_opcode_cpsr == 0)
12520 return true;
12521 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12522 break;
12523 case 1:
12524 if (m_opcode_cpsr == 0)
12525 return true;
12526 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12527 break;
12528 case 2:
12529 if (m_opcode_cpsr == 0)
12530 return true;
12531 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12532 break;
12533 case 3:
12534 if (m_opcode_cpsr == 0)
12535 return true;
12536 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12537 break;
12538 case 4:
12539 if (m_opcode_cpsr == 0)
12540 return true;
12541 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12542 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012543 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012544 if (m_opcode_cpsr == 0)
12545 return true;
12546 else
12547 {
Greg Claytonb3448432011-03-24 21:19:54 +000012548 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12549 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012550 result = n == v;
12551 }
12552 break;
12553 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012554 if (m_opcode_cpsr == 0)
12555 return true;
12556 else
12557 {
Greg Claytonb3448432011-03-24 21:19:54 +000012558 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12559 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12560 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012561 }
12562 break;
12563 case 7:
12564 result = true;
12565 break;
12566 }
12567
12568 if (cond & 1)
12569 result = !result;
12570 return result;
12571}
12572
Johnny Chen9ee056b2011-02-08 00:06:35 +000012573uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012574EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012575{
Greg Claytonb3448432011-03-24 21:19:54 +000012576 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012577 {
12578 default:
12579 case eModeInvalid:
12580 break;
12581
12582 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012583 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012584
12585 case eModeThumb:
12586 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12587 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012588 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012589 const uint32_t byte_size = m_opcode.GetByteSize();
12590 if (byte_size == 2)
12591 {
12592 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12593 return Bits32(opcode, 11, 7);
12594 }
12595 else
12596 {
12597 assert (byte_size == 4);
12598 if (Bits32(opcode, 31, 27) == 0x1e &&
12599 Bits32(opcode, 15, 14) == 0x02 &&
12600 Bits32(opcode, 12, 12) == 0x00 &&
12601 Bits32(opcode, 25, 22) <= 0x0d)
12602 {
12603 return Bits32(opcode, 25, 22);
12604 }
12605 }
12606
12607 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012608 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012609 }
12610 return UINT32_MAX; // Return invalid value
12611}
12612
Johnny Chen9ee056b2011-02-08 00:06:35 +000012613bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012614EmulateInstructionARM::InITBlock()
12615{
12616 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12617}
12618
12619bool
12620EmulateInstructionARM::LastInITBlock()
12621{
12622 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12623}
12624
Caroline Ticeb27771d2011-03-03 22:37:46 +000012625bool
12626EmulateInstructionARM::BadMode (uint32_t mode)
12627{
12628
12629 switch (mode)
12630 {
12631 case 16: return false; // '10000'
12632 case 17: return false; // '10001'
12633 case 18: return false; // '10010'
12634 case 19: return false; // '10011'
12635 case 22: return false; // '10110'
12636 case 23: return false; // '10111'
12637 case 27: return false; // '11011'
12638 case 31: return false; // '11111'
12639 default: return true;
12640 }
12641 return true;
12642}
12643
12644bool
12645EmulateInstructionARM::CurrentModeIsPrivileged ()
12646{
Greg Claytonb3448432011-03-24 21:19:54 +000012647 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012648
12649 if (BadMode (mode))
12650 return false;
12651
12652 if (mode == 16)
12653 return false;
12654
12655 return true;
12656}
12657
12658void
12659EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12660{
12661 bool privileged = CurrentModeIsPrivileged();
12662
12663 uint32_t tmp_cpsr = 0;
12664
Greg Claytonb3448432011-03-24 21:19:54 +000012665 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012666
12667 if (BitIsSet (bytemask, 3))
12668 {
12669 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12670 if (affect_execstate)
12671 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12672 }
12673
12674 if (BitIsSet (bytemask, 2))
12675 {
12676 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12677 }
12678
12679 if (BitIsSet (bytemask, 1))
12680 {
12681 if (affect_execstate)
12682 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12683 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12684 if (privileged)
12685 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12686 }
12687
12688 if (BitIsSet (bytemask, 0))
12689 {
12690 if (privileged)
12691 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12692 if (affect_execstate)
12693 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12694 if (privileged)
12695 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12696 }
12697
Greg Claytonb3448432011-03-24 21:19:54 +000012698 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012699}
12700
12701
Johnny Chen098ae2d2011-02-12 00:50:05 +000012702bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012703EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12704{
12705 addr_t target;
12706
Johnny Chenee9b1f72011-02-09 01:00:31 +000012707 // Check the current instruction set.
12708 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012709 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012710 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012711 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012712
Johnny Chen9ee056b2011-02-08 00:06:35 +000012713 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012714 return false;
12715
12716 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012717}
12718
12719// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12720bool
Johnny Chen668b4512011-02-15 21:08:58 +000012721EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012722{
12723 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012724 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12725 // we want to record it and issue a WriteRegister callback so the clients
12726 // can track the mode changes accordingly.
12727 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012728
12729 if (BitIsSet(addr, 0))
12730 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012731 if (CurrentInstrSet() != eModeThumb)
12732 {
12733 SelectInstrSet(eModeThumb);
12734 cpsr_changed = true;
12735 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012736 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000012737 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012738 }
12739 else if (BitIsClear(addr, 1))
12740 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012741 if (CurrentInstrSet() != eModeARM)
12742 {
12743 SelectInstrSet(eModeARM);
12744 cpsr_changed = true;
12745 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012746 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000012747 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012748 }
12749 else
12750 return false; // address<1:0> == '10' => UNPREDICTABLE
12751
Johnny Chen0f309db2011-02-09 19:11:32 +000012752 if (cpsr_changed)
12753 {
Johnny Chen558133b2011-02-09 23:59:17 +000012754 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012755 return false;
12756 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012757 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012758 return false;
12759
12760 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012761}
Greg Clayton64c84432011-01-21 22:02:52 +000012762
Johnny Chenee9b1f72011-02-09 01:00:31 +000012763// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
12764bool
Johnny Chen668b4512011-02-15 21:08:58 +000012765EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000012766{
12767 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000012768 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000012769 else
12770 return BranchWritePC((const Context)context, addr);
12771}
12772
Johnny Chen26863dc2011-02-09 23:43:29 +000012773// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
12774bool
Johnny Chen668b4512011-02-15 21:08:58 +000012775EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000012776{
12777 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000012778 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000012779 else
12780 return BranchWritePC((const Context)context, addr);
12781}
12782
Johnny Chenee9b1f72011-02-09 01:00:31 +000012783EmulateInstructionARM::Mode
12784EmulateInstructionARM::CurrentInstrSet ()
12785{
Greg Claytonb3448432011-03-24 21:19:54 +000012786 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012787}
12788
Greg Claytonb3448432011-03-24 21:19:54 +000012789// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000012790// ReadInstruction() is performed. This function has a side effect of updating
12791// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000012792bool
12793EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
12794{
Greg Claytonb3448432011-03-24 21:19:54 +000012795 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012796 switch (arm_or_thumb)
12797 {
12798 default:
12799 return false;
12800 eModeARM:
12801 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000012802 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012803 break;
12804 eModeThumb:
12805 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000012806 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012807 break;
12808 }
12809 return true;
12810}
12811
Johnny Chenef21b592011-02-10 01:52:38 +000012812// This function returns TRUE if the processor currently provides support for
12813// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
12814// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
12815bool
12816EmulateInstructionARM::UnalignedSupport()
12817{
12818 return (ArchVersion() >= ARMv7);
12819}
12820
Johnny Chenbf6ad172011-02-11 01:29:53 +000012821// The main addition and subtraction instructions can produce status information
12822// about both unsigned carry and signed overflow conditions. This status
12823// information can be used to synthesize multi-word additions and subtractions.
12824EmulateInstructionARM::AddWithCarryResult
12825EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
12826{
12827 uint32_t result;
12828 uint8_t carry_out;
12829 uint8_t overflow;
12830
12831 uint64_t unsigned_sum = x + y + carry_in;
12832 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
12833
12834 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000012835// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000012836 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000012837
12838 if (carry_in)
12839 carry_out = ((int32_t) x >= (int32_t) y) ? 1 : 0;
12840 else
12841 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000012842
12843 AddWithCarryResult res = { result, carry_out, overflow };
12844 return res;
12845}
12846
Johnny Chen157b9592011-02-18 21:13:05 +000012847uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000012848EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000012849{
Johnny Chene39f22d2011-02-19 01:36:13 +000012850 uint32_t reg_kind, reg_num;
12851 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000012852 {
Johnny Chene39f22d2011-02-19 01:36:13 +000012853 case SP_REG:
12854 reg_kind = eRegisterKindGeneric;
12855 reg_num = LLDB_REGNUM_GENERIC_SP;
12856 break;
12857 case LR_REG:
12858 reg_kind = eRegisterKindGeneric;
12859 reg_num = LLDB_REGNUM_GENERIC_RA;
12860 break;
12861 case PC_REG:
12862 reg_kind = eRegisterKindGeneric;
12863 reg_num = LLDB_REGNUM_GENERIC_PC;
12864 break;
12865 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000012866 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000012867 {
12868 reg_kind = eRegisterKindDWARF;
12869 reg_num = dwarf_r0 + num;
12870 }
Johnny Chen157b9592011-02-18 21:13:05 +000012871 else
Johnny Chene39f22d2011-02-19 01:36:13 +000012872 {
12873 assert(0 && "Invalid register number");
12874 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000012875 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000012876 }
12877 break;
Johnny Chen157b9592011-02-18 21:13:05 +000012878 }
Johnny Chene39f22d2011-02-19 01:36:13 +000012879
12880 // Read our register.
12881 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
12882
12883 // When executing an ARM instruction , PC reads as the address of the current
12884 // instruction plus 8.
12885 // When executing a Thumb instruction , PC reads as the address of the current
12886 // instruction plus 4.
12887 if (num == 15)
12888 {
12889 if (CurrentInstrSet() == eModeARM)
12890 val += 8;
12891 else
12892 val += 4;
12893 }
Johnny Chen157b9592011-02-18 21:13:05 +000012894
12895 return val;
12896}
12897
Johnny Chenca67d1c2011-02-17 01:35:27 +000012898// Write the result to the ARM core register Rd, and optionally update the
12899// condition flags based on the result.
12900//
12901// This helper method tries to encapsulate the following pseudocode from the
12902// ARM Architecture Reference Manual:
12903//
12904// if d == 15 then // Can only occur for encoding A1
12905// ALUWritePC(result); // setflags is always FALSE here
12906// else
12907// R[d] = result;
12908// if setflags then
12909// APSR.N = result<31>;
12910// APSR.Z = IsZeroBit(result);
12911// APSR.C = carry;
12912// // APSR.V unchanged
12913//
12914// In the above case, the API client does not pass in the overflow arg, which
12915// defaults to ~0u.
12916bool
Johnny Chen10530c22011-02-17 22:37:12 +000012917EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
12918 const uint32_t result,
12919 const uint32_t Rd,
12920 bool setflags,
12921 const uint32_t carry,
12922 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000012923{
12924 if (Rd == 15)
12925 {
12926 if (!ALUWritePC (context, result))
12927 return false;
12928 }
12929 else
12930 {
Johnny Chena695f952011-02-23 21:24:25 +000012931 uint32_t reg_kind, reg_num;
12932 switch (Rd)
12933 {
12934 case SP_REG:
12935 reg_kind = eRegisterKindGeneric;
12936 reg_num = LLDB_REGNUM_GENERIC_SP;
12937 break;
12938 case LR_REG:
12939 reg_kind = eRegisterKindGeneric;
12940 reg_num = LLDB_REGNUM_GENERIC_RA;
12941 break;
12942 default:
12943 reg_kind = eRegisterKindDWARF;
12944 reg_num = dwarf_r0 + Rd;
12945 }
12946 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000012947 return false;
12948 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000012949 return WriteFlags (context, result, carry, overflow);
12950 }
12951 return true;
12952}
12953
12954// This helper method tries to encapsulate the following pseudocode from the
12955// ARM Architecture Reference Manual:
12956//
12957// APSR.N = result<31>;
12958// APSR.Z = IsZeroBit(result);
12959// APSR.C = carry;
12960// APSR.V = overflow
12961//
12962// Default arguments can be specified for carry and overflow parameters, which means
12963// not to update the respective flags.
12964bool
12965EmulateInstructionARM::WriteFlags (Context &context,
12966 const uint32_t result,
12967 const uint32_t carry,
12968 const uint32_t overflow)
12969{
Greg Claytonb3448432011-03-24 21:19:54 +000012970 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000012971 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
12972 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000012973 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000012974 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000012975 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000012976 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000012977 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000012978 {
12979 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
12980 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000012981 }
12982 return true;
12983}
12984
Greg Clayton64c84432011-01-21 22:02:52 +000012985bool
12986EmulateInstructionARM::EvaluateInstruction ()
12987{
Johnny Chenc315f862011-02-05 00:46:10 +000012988 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000012989 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000012990 m_it_session.ITAdvance();
12991
Caroline Tice080bf612011-04-05 18:46:00 +000012992
12993 ARMOpcode *opcode_data;
12994
12995 if (m_opcode_mode == eModeThumb)
12996 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32());
12997 else if (m_opcode_mode == eModeARM)
12998 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32());
12999 else
13000 return false;
13001
13002 if (!opcode_data)
13003 return false;
13004 // Verify that we're the right arch for this opcode
13005
13006 switch (m_arm_isa)
13007 {
13008 case ARMv4:
13009 if (opcode_data->variants != ARMvAll)
13010 return false;
13011 break;
13012
13013 case ARMv4T:
13014 if ((opcode_data->variants!= ARMvAll)
13015 && (opcode_data->variants != ARMV4T_ABOVE))
13016 return false;
13017 break;
13018
13019 case ARMv5T:
13020 case ARMv5TE:
13021 if ((opcode_data->variants != ARMvAll)
13022 && (opcode_data->variants != ARMV4T_ABOVE)
13023 && (opcode_data->variants != ARMV5_ABOVE))
13024 return false;
13025 break;
13026
13027 case ARMv5TEJ:
13028 if ((opcode_data->variants != ARMvAll)
13029 && (opcode_data->variants != ARMV4T_ABOVE)
13030 && (opcode_data->variants != ARMV5_ABOVE)
13031 && (opcode_data->variants != ARMV5J_ABOVE))
13032 return false;
13033 break;
13034
13035 case ARMv6:
13036 case ARMv6K:
13037 if ((opcode_data->variants != ARMvAll)
13038 && (opcode_data->variants != ARMV4T_ABOVE)
13039 && (opcode_data->variants != ARMV5_ABOVE)
13040 && (opcode_data->variants != ARMV5J_ABOVE)
13041 && (opcode_data->variants != ARMV6_ABOVE))
13042 return false;
13043 break;
13044
13045 case ARMv6T2:
13046 case ARMv7:
13047 case ARMv8:
13048 if ((opcode_data->variants != ARMvAll)
13049 && (opcode_data->variants != ARMV4T_ABOVE)
13050 && (opcode_data->variants != ARMV5_ABOVE)
13051 && (opcode_data->variants != ARMV5J_ABOVE)
13052 && (opcode_data->variants != ARMV6_ABOVE)
13053 && (opcode_data->variants != ARMV6T2_ABOVE))
13054 return false;
13055 break;
13056
13057 default:
13058// if (opcode_data->variants != ARMvAll)
13059// return false;
13060 break;
13061 }
13062
13063 // Just for now, for testing purposes.
Caroline Ticeaf591802011-04-05 23:22:54 +000013064 if (m_baton == NULL)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013065 fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(),
13066 opcode_data->name);
13067
13068 bool success;
13069 if (m_baton)
13070 {
13071 uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
13072 if (success)
13073 m_opcode_cpsr = cpsr_value;
13074 }
Caroline Tice080bf612011-04-05 18:46:00 +000013075
Caroline Tice0fe5a532011-04-08 23:33:06 +000013076 uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13077 if (!success)
13078 return false;
13079
13080 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
13081 if (!success)
13082 return false;
13083
13084 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13085 if (!success)
13086 return false;
13087
13088 if (m_advance_pc && (after_pc_value == orig_pc_value))
13089 {
13090 if (opcode_data->size == eSize32)
13091 after_pc_value += 4;
13092 else if (opcode_data->size == eSize16)
13093 after_pc_value += 2;
13094
13095 EmulateInstruction::Context context;
13096 context.type = eContextAdvancePC;
13097 context.SetNoArgs();
13098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13099 return false;
13100
13101 }
13102
13103 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013104}